SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriLinearLgn.h
Go to the documentation of this file.
1 //
2 // For more information, please see: http://software.sci.utah.edu
3 //
4 // The MIT License
5 //
6 // Copyright (c) 2009 Scientific Computing and Imaging Institute,
7 // University of Utah.
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 // DEALINGS IN THE SOFTWARE.
27 //
28 /// @file TriLinearLgn.h
29 /// @author Martin Cole, Frank B. Sachse
30 /// @date Dec 04 2004
31 
32 #ifndef CORE_BASIS_TRILINEARLGN_H
33 #define CORE_BASIS_TRILINEARLGN_H 1
34 
35 #include <float.h>
36 
40 
41 namespace SCIRun {
42 namespace Core {
43 namespace Basis {
44 
45 /// Class for describing unit geometry of TriLinearLgn
47 public:
48  /// Parametric coordinates of vertices of unit edge
49  static SCISHARE double unit_vertices[3][2];
50  /// References to vertices of unit edge
51  static SCISHARE int unit_edges[3][2];
52  /// References to vertices of unit face
53  static SCISHARE int unit_faces[1][3];
54  /// References to normal of unit face
55  static SCISHARE double unit_face_normals[1][3];
56  /// The center of the unit element
57  static SCISHARE double unit_center[2];
58 
61 
62  /// return dimension of domain
63  static int domain_dimension()
64  { return 2; }
65 
66  /// return size of the domain
67  static double domain_size()
68  { return 0.5; }
69 
70  /// return number of vertices
71  static int number_of_vertices()
72  { return 3; }
73 
74  /// return number of vertices in mesh
76  { return 3; }
77 
78  /// return degrees of freedom
79  static int dofs()
80  { return 3; }
81 
82  /// return number of edges
83  static int number_of_edges()
84  { return 3; }
85 
86  /// return number of vertices per face
87  static int vertices_of_face()
88  { return 3; }
89 
90  /// return number of faces per cell
91  static int faces_of_cell()
92  { return 1; }
93 
94  static inline double length(int edge)
95  {
96  const double *v0 = unit_vertices[unit_edges[edge][0]];
97  const double *v1 = unit_vertices[unit_edges[edge][1]];
98  const double dx = v1[0] - v0[0];
99  const double dy = v1[1] - v0[1];
100  return sqrt(dx*dx+dy*dy);
101  }
102 
103  static double area(int /* face */) { return 0.5; } ///< return area
104  static double volume() { return 0.; } ///< return volume
105 };
106 
107 
108 /// Class for creating geometrical approximations of Tri meshes
109 class TriApprox {
110 public:
112  virtual ~TriApprox() {}
113 
114  /// Approximate edge for element by piecewise linear segments
115  /// return: coords gives parametric coordinates of the approximation.
116  /// Use interpolate with coordinates to get the world coordinates.
117  template<class VECTOR>
118  void approx_edge(const unsigned edge,
119  const unsigned div_per_unit,
120  VECTOR &coords) const
121  {
122  typedef typename VECTOR::value_type VECTOR2;
123 
124  coords.resize(div_per_unit+1);
125 
127  const double *v1 = TriLinearLgnUnitElement::unit_vertices[TriLinearLgnUnitElement::unit_edges[edge][1]];
128 
129  const double &p1x = v0[0];
130  const double &p1y = v0[1];
131  const double dx = v1[0] - p1x;
132  const double dy = v1[1] - p1y;
133 
134  for(unsigned i = 0; i <= div_per_unit; i++) {
135  const double d = (double)i / (double)div_per_unit;
136  typename VECTOR::value_type &tmp = coords[i];
137  tmp.resize(2);
138  tmp[0] = static_cast<typename VECTOR2::value_type>(p1x + d * dx);
139  tmp[1] = static_cast<typename VECTOR2::value_type>(p1y + d * dy);
140  }
141  }
142 
143  /// Approximate faces for element by piecewise linear elements
144  /// return: coords gives parametric coordinates at the approximation point.
145  /// Use interpolate with coordinates to get the world coordinates.
146  template<class VECTOR>
147  void approx_face(const unsigned /* face */,
148  const unsigned div_per_unit,
149  VECTOR &coords) const
150  {
151  typedef typename VECTOR::value_type VECTOR2;
152  typedef typename VECTOR2::value_type VECTOR3;
153 
154  coords.resize(div_per_unit);
155  const double d = 1. / div_per_unit;
156 
157  for(unsigned j = 0; j < div_per_unit; j++)
158  {
159  const double dj = (double)j / (double)div_per_unit;
160  unsigned e = 0;
161  coords[j].resize((div_per_unit - j) * 2 + 1);
162  typename VECTOR2::value_type& tmp = coords[j][e++];
163  tmp.resize(2);
164  tmp[0] = 0;
165  tmp[1] = dj;
166  for(unsigned i = 0; i<div_per_unit - j; i++)
167  {
168  const double di = (double)i / (double)div_per_unit;
169  typename VECTOR2::value_type& tmp1 = coords[j][e++];
170  tmp1.resize(2);
171  tmp1[0] = static_cast<typename VECTOR3::value_type>(di);
172  tmp1[1] = static_cast<typename VECTOR3::value_type>(dj + d);
173  typename VECTOR2::value_type& tmp2 = coords[j][e++];
174  tmp2.resize(2);
175  tmp2[0] = static_cast<typename VECTOR3::value_type>(di + d);
176  tmp2[1] = static_cast<typename VECTOR3::value_type>(dj);
177  }
178  }
179  }
180 };
181 
182 /// Class for searching of parametric coordinates related to a
183 /// value in Tri meshes and fields
184 template <class ElemBasis>
185 class TriLocate : public Dim2Locate<ElemBasis> {
186 public:
187  typedef typename ElemBasis::value_type T;
188 
190  virtual ~TriLocate() {}
191 
192  /// find value in interpolation for given value
193  template <class ElemData, class VECTOR>
194  bool get_coords(const ElemBasis *pEB, VECTOR &coords,
195  const T& value, const ElemData &cd) const
196  {
197  initial_guess(pEB, value, cd, coords);
198  if (this->get_iterative(pEB, coords, value, cd))
199  return check_coords(coords);
200  return false;
201  }
202 
203  template<class VECTOR>
204  inline bool check_coords(const VECTOR &x) const
205  {
209  return true;
210 
211  return false;
212  }
213 
214 protected:
215  /// find a reasonable initial guess
216  template <class ElemData, class VECTOR>
217  void initial_guess(const ElemBasis *pElem, const T &val, const ElemData &cd,
218  VECTOR & guess) const
219  {
220  double dist = DBL_MAX;
221 
222  VECTOR coord(2);
223  StackVector<T,2> derivs;
224  guess.resize(2);
225 
226  const int end = 3;
227  for (int x = 1; x < end; x++)
228  {
229  coord[0] = x / (double) end;
230  for (int y = 1; y < end; y++)
231  {
232  coord[1] = y / (double) end;
233  if (coord[0]+coord[1]>Dim2Locate<ElemBasis>::thresholdDist1)
234  break;
235  double cur_d;
236  if (compare_distance(pElem->interpolate(coord, cd),
237  val, cur_d, dist))
238  {
239  pElem->derivate(coord, cd, derivs);
240  if (!check_zero(derivs)) {
241  dist = cur_d;
242  guess = coord;
243  }
244  }
245  }
246  }
247  }
248 };
249 
250 
251 /// Class with weights and coordinates for 2nd order Gaussian integration
252 template <class T>
254 {
255 public:
256  static int GaussianNum;
257  static T GaussianPoints[1][2];
258  static T GaussianWeights[1];
259 };
260 
261 template <class T>
263 
264 template <class T>
265 T TriGaussian1<T>::GaussianPoints[1][2] = { {1./3.,1./3.}};
266 
267 template <class T>
269 
270 /// Class with weights and coordinates for 2nd order Gaussian integration
271 template <class T>
273 {
274 public:
275  static int GaussianNum;
276  static T GaussianPoints[3][2];
277  static T GaussianWeights[3];
278 };
279 
280 template <class T>
282 
283 template <class T>
285  {1./6.,1./6.}, {2./3.,1./6.}, {1./6.,2./3.}};
286 
287 template <class T>
288 T TriGaussian2<T>::GaussianWeights[3] = {1./3., 1./3., 1./3.};
289 
290 /// Class with weights and coordinates for 3rd order Gaussian integration
291 template <class T>
293 {
294 public:
295  static int GaussianNum;
296  static T GaussianPoints[7][2];
297  static T GaussianWeights[7];
298 };
299 
300 template <class T>
302 
303 template <class T>
305  {0.1012865073, 0.1012865073}, {0.7974269853, 0.1012865073}, {0.1012865073, 0.7974269853},
306  {0.4701420641, 0.0597158717}, {0.4701420641, 0.4701420641}, {0.0597158717, 0.4701420641},
307  {0.3333333333, 0.3333333333}};
308 
309 template <class T>
310 T TriGaussian3<T>::GaussianWeights[7] =
311  {0.1259391805, 0.1259391805, 0.1259391805, 0.1323941527, 0.1323941527, 0.1323941527, 0.225};
312 
313 #ifdef _WIN32
314 // force the instantiation of TriGaussian3<double>
315 template class TriGaussian1<double>;
316 template class TriGaussian2<double>;
317 template class TriGaussian3<double>;
318 #endif
319 
320 
321 /// Class for handling of element of type triangle with
322 /// linear lagrangian interpolation
323 template <class T>
324 class TriLinearLgn :
325  public BasisSimple<T>,
326  public TriApprox,
327  public TriGaussian1<double>,
328  public TriSamplingSchemes,
330  public TriElementWeights
331 {
332 public:
333  typedef T value_type;
334 
336  virtual ~TriLinearLgn() {}
337 
338  static int polynomial_order() { return 1; }
339 
340  template<class VECTOR>
341  inline void get_weights(const VECTOR& coords, double *w) const
342  { get_linear_weights(coords,w); }
343 
344  template<class VECTOR>
345  inline void get_derivate_weights(const VECTOR& coords, double *w) const
346  { get_linear_derivate_weights(coords,w); }
347 
348  /// get value at parametric coordinate
349  template <class ElemData, class VECTOR>
350  T interpolate(const VECTOR &coords, const ElemData &cd) const
351  {
352  double w[3];
353  get_linear_weights(coords, w);
354 
355  return (T)(w[0] * cd.node0() +
356  w[1] * cd.node1() +
357  w[2] * cd.node2());
358  }
359 
360  /// get first derivative at parametric coordinate
361  template <class ElemData, class VECTOR1, class VECTOR2>
362  void derivate(const VECTOR1& /*coords*/, const ElemData &cd,
363  VECTOR2 &derivs) const
364  {
365  derivs.resize(2);
366 
367  derivs[0] = static_cast<typename VECTOR2::value_type>(-1. * cd.node0() + cd.node1());
368  derivs[1] = static_cast<typename VECTOR2::value_type>(-1. * cd.node0() + cd.node2());
369  }
370 
371  /// get the parametric coordinate for value within the element
372  template <class ElemData, class VECTOR>
373  bool get_coords(VECTOR &coords, const T& value,
374  const ElemData &cd) const
375  {
377  return CL.get_coords(this, coords, value, cd);
378  }
379 
380  /// get arc length for edge
381  template <class ElemData>
382  double get_arc_length(const unsigned edge, const ElemData &cd) const
383  {
384  return get_arc2d_length<CrvGaussian1<double> >(this, edge, cd);
385  }
386 
387  /// get area
388  template <class ElemData>
389  double get_area(const unsigned face, const ElemData &cd) const
390  {
391  return get_area2<TriGaussian2<double> >(this, face, cd);
392  }
393 
394  /// get volume
395  template <class ElemData>
396  double get_volume(const ElemData & /* cd */) const
397  {
398  return 0.;
399  }
400 
401  template<class VECTOR>
402  void approx_edge(const unsigned int edge,
403  const unsigned int div_per_unit,
404  VECTOR &coords) const
405  {
406  typedef typename VECTOR::value_type VECTOR2;
407 
408  coords.resize(div_per_unit + 1);
409 
411  const double *v1 = TriLinearLgnUnitElement::unit_vertices[TriLinearLgnUnitElement::unit_edges[edge][1]];
412 
413  const double &p1x = v0[0];
414  const double &p1y = v0[1];
415  const double dx = v1[0] - p1x;
416  const double dy = v1[1] - p1y;
417 
418  for(unsigned int i = 0; i <= div_per_unit; i++) {
419  const double d = (double)i / (double)div_per_unit;
420  typename VECTOR::value_type &tmp = coords[i];
421  tmp.resize(2);
422  tmp[0] = static_cast<typename VECTOR2::value_type>(p1x + d * dx);
423  tmp[1] = static_cast<typename VECTOR2::value_type>(p1y + d * dy);
424  }
425  }
426 
427  template<class VECTOR>
428  void approx_face(const unsigned int /*face*/,
429  const unsigned int div_per_unit,
430  VECTOR &coords) const
431  {
432  typedef typename VECTOR::value_type VECTOR2;
433  typedef typename VECTOR2::value_type VECTOR3;
434 
436  const double *v1 = TriLinearLgnUnitElement::unit_vertices[TriLinearLgnUnitElement::unit_faces[0][1]];
437  const double *v2 = TriLinearLgnUnitElement::unit_vertices[TriLinearLgnUnitElement::unit_faces[0][2]];
438 
439  coords.resize(div_per_unit);
440  const double d = 1. / div_per_unit;
441  for(unsigned int j = 0; j<div_per_unit; j++)
442  {
443  const double dj = (double)j / (double)div_per_unit;
444  unsigned int e = 0;
445  coords[j].resize((div_per_unit - j) * 2 + 1);
446  typename VECTOR2::value_type &tmp = coords[j][e++];
447  tmp.resize(2);
448  tmp[0] = static_cast<typename VECTOR3::value_type>(v0[0] + dj * (v2[0] - v0[0]));
449  tmp[1] = static_cast<typename VECTOR3::value_type>(v0[1] + dj * (v2[1] - v0[1]));
450 
451  for(unsigned int i = 0; i<div_per_unit - j; i++)
452  {
453  const double di = (double)i / (double)div_per_unit;
454  typename VECTOR2::value_type &tmp1 = coords[j][e++];
455  tmp1.resize(2);
456  tmp1[0] = static_cast<typename VECTOR3::value_type>(v0[0] + (dj + d) * (v2[0] - v0[0]) + di * (v1[0] - v0[0]));
457  tmp1[1] = static_cast<typename VECTOR3::value_type>(v0[1] + (dj + d) * (v2[1] - v0[1]) + di * (v1[1] - v0[1]));
458 
459  typename VECTOR2::value_type &tmp2 = coords[j][e++];
460  tmp2.resize(2);
461  tmp2[0] = static_cast<typename VECTOR3::value_type>(v0[0] + dj * (v2[0] - v0[0]) + (di + d) * (v1[0] - v0[0]));
462  tmp2[1] = static_cast<typename VECTOR3::value_type>(v0[1] + dj * (v2[1] - v0[1]) + (di + d) * (v1[1] - v0[1]));
463  }
464  }
465  }
466 
467 
468  static const std::string type_name(int n = -1);
469 
470 
471  virtual void io (Piostream& str);
472 
473 };
474 
475 
476 
477 template <class T>
478 const std::string
480 {
481  ASSERT((n >= -1) && n <= 1);
482  if (n == -1)
483  {
484  static const std::string name = TypeNameGenerator::make_template_id(type_name(0), type_name(1));
485  return name;
486  }
487  else if (n == 0)
488  {
489  static const std::string nm("TriLinearLgn");
490  return nm;
491  } else {
492  return find_type_name((T *)0);
493  }
494 }
495 
496 }}
497 
498 template <class T>
500 {
501  static TypeDescription* td = 0;
502  if(!td){
503  const TypeDescription *sub = get_type_description((T*)0);
505  (*subs)[0] = sub;
506  td = new TypeDescription("TriLinearLgn", subs,
507  std::string(__FILE__),
508  "SCIRun",
510  }
511  return td;
512 }
513 
514  const int TRILINEARLGN_VERSION = 1;
515  template <class T>
516  void
518  {
519  stream.begin_class(get_type_description(this)->get_name(),
521  stream.end_class();
522  }
523 }
524 
525 #endif
void get_derivate_weights(const VECTOR &coords, double *w) const
Definition: TriLinearLgn.h:345
TriLinearLgn()
Definition: TriLinearLgn.h:335
static SCISHARE int unit_faces[1][3]
References to vertices of unit face.
Definition: TriLinearLgn.h:53
Class with weights and coordinates for 2nd order Gaussian integration.
Definition: TriLinearLgn.h:272
static int number_of_mesh_vertices()
return number of vertices in mesh
Definition: TriLinearLgn.h:75
static SCISHARE int unit_edges[3][2]
References to vertices of unit edge.
Definition: TriLinearLgn.h:51
static T GaussianPoints[3][2]
Definition: TriLinearLgn.h:276
double check_zero(const VECTOR &derivs, double epsilon=1e-7)
Definition: Locate.h:709
bool get_coords(const ElemBasis *pEB, VECTOR &coords, const T &value, const ElemData &cd) const
find value in interpolation for given value
Definition: TriLinearLgn.h:194
virtual ~TriLinearLgnUnitElement()
Definition: TriLinearLgn.h:60
static int domain_dimension()
return dimension of domain
Definition: TriLinearLgn.h:63
T value_type
Definition: TriLinearLgn.h:333
Definition: Persistent.h:89
Class for creating geometrical approximations of Tri meshes.
Definition: TriLinearLgn.h:109
static int GaussianNum
Definition: TriLinearLgn.h:295
static int dofs()
return degrees of freedom
Definition: TriLinearLgn.h:79
bool get_coords(VECTOR &coords, const T &value, const ElemData &cd) const
get the parametric coordinate for value within the element
Definition: TriLinearLgn.h:373
static const std::string type_name(int n=-1)
Definition: TriLinearLgn.h:479
const int TRILINEARLGN_VERSION
Definition: TriLinearLgn.h:514
Definition: TypeDescription.h:45
#define SCISHARE
Definition: share.h:39
std::vector< const TypeDescription * > td_vec
Definition: TypeDescription.h:56
bool check_coords(const VECTOR &x) const
Definition: TriLinearLgn.h:204
void initial_guess(const ElemBasis *pElem, const T &val, const ElemData &cd, VECTOR &guess) const
find a reasonable initial guess
Definition: TriLinearLgn.h:217
Class with weights and coordinates for 2nd order Gaussian integration.
Definition: TriLinearLgn.h:253
void approx_edge(const unsigned edge, const unsigned div_per_unit, VECTOR &coords) const
Definition: TriLinearLgn.h:118
#define ASSERT(condition)
Definition: Assert.h:110
Class for describing interfaces to basis elements.
Definition: Basis.h:48
static int faces_of_cell()
return number of faces per cell
Definition: TriLinearLgn.h:91
static int vertices_of_face()
return number of vertices per face
Definition: TriLinearLgn.h:87
virtual int begin_class(const std::string &name, int current_version)
Definition: Persistent.cc:143
static int number_of_edges()
return number of edges
Definition: TriLinearLgn.h:83
ElemBasis::value_type T
Definition: Locate.h:587
T interpolate(const VECTOR &coords, const ElemData &cd) const
get value at parametric coordinate
Definition: TriLinearLgn.h:350
const string find_type_name(float *)
Definition: TypeName.cc:63
static double domain_size()
return size of the domain
Definition: TriLinearLgn.h:67
static T GaussianPoints[1][2]
Definition: TriLinearLgn.h:257
static double volume()
return volume
Definition: TriLinearLgn.h:104
static T GaussianWeights[7]
Definition: TriLinearLgn.h:297
static SCISHARE double unit_center[2]
The center of the unit element.
Definition: TriLinearLgn.h:57
const char * name[]
Definition: BoostGraphExampleTests.cc:87
double get_area(const unsigned face, const ElemData &cd) const
get area
Definition: TriLinearLgn.h:389
static int number_of_vertices()
return number of vertices
Definition: TriLinearLgn.h:71
Definition: StackVector.h:50
TriApprox()
Definition: TriLinearLgn.h:111
Definition: Locate.h:585
TriLocate()
Definition: TriLinearLgn.h:189
static int GaussianNum
Definition: TriLinearLgn.h:275
static SCISHARE double unit_vertices[3][2]
Parametric coordinates of vertices of unit edge.
Definition: TriLinearLgn.h:49
void approx_face(const unsigned int, const unsigned int div_per_unit, VECTOR &coords) const
Definition: TriLinearLgn.h:428
static T GaussianWeights[1]
Definition: TriLinearLgn.h:258
static const std::string make_template_id(const std::string &templateName, const std::string &templateParam)
Definition: TypeName.h:62
void get_weights(const VECTOR &coords, double *w) const
Definition: TriLinearLgn.h:341
static T GaussianWeights[3]
Definition: TriLinearLgn.h:277
double get_arc_length(const unsigned edge, const ElemData &cd) const
get arc length for edge
Definition: TriLinearLgn.h:382
Class for describing unit geometry of TriLinearLgn.
Definition: TriLinearLgn.h:46
void approx_edge(const unsigned int edge, const unsigned int div_per_unit, VECTOR &coords) const
Definition: TriLinearLgn.h:402
Definition: TriElementWeights.h:36
Definition: TriLinearLgn.h:324
virtual void io(Piostream &str)
Definition: TriLinearLgn.h:517
virtual ~TriApprox()
Definition: TriLinearLgn.h:112
bool compare_distance(const T &interp, const T &val, double &cur_d, double dist)
Definition: Locate.h:667
static SCISHARE double unit_face_normals[1][3]
References to normal of unit face.
Definition: TriLinearLgn.h:55
static int GaussianNum
Definition: TriLinearLgn.h:256
virtual void end_class()
Definition: Persistent.cc:178
void derivate(const VECTOR1 &, const ElemData &cd, VECTOR2 &derivs) const
get first derivative at parametric coordinate
Definition: TriLinearLgn.h:362
double get_volume(const ElemData &) const
get volume
Definition: TriLinearLgn.h:396
void resize(size_t size, const value_type &val=value_type())
Definition: StackVector.h:61
static double area(int)
return area
Definition: TriLinearLgn.h:103
void approx_face(const unsigned, const unsigned div_per_unit, VECTOR &coords) const
Definition: TriLinearLgn.h:147
Definition: TriSamplingSchemes.h:43
int n
Definition: eab.py:9
bool get_iterative(const ElemBasis *pEB, VECTOR &x, const T &value, const ElemData &cd) const
find value in interpolation for given value
Definition: Locate.h:597
Class with weights and coordinates for 3rd order Gaussian integration.
Definition: TriLinearLgn.h:292
virtual ~TriLinearLgn()
Definition: TriLinearLgn.h:336
static int polynomial_order()
Definition: TriLinearLgn.h:338
virtual ~TriLocate()
Definition: TriLinearLgn.h:190
static double length(int edge)
Definition: TriLinearLgn.h:94
Definition: TriLinearLgn.h:185
TriLinearLgnUnitElement()
Definition: TriLinearLgn.h:59
ElemBasis::value_type T
Definition: TriLinearLgn.h:187
static T GaussianPoints[7][2]
Definition: TriLinearLgn.h:296
Definition: TypeDescription.h:49
const TypeDescription * get_type_description(Core::Basis::ConstantBasis< T > *)
Definition: Constant.h:209