SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PrismLinearLgn.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 PrismLinearLgn.h
29 /// @author Martin Cole, Frank B. Sachse
30 /// @date Dec 04 2004
31 
32 #ifndef CORE_BASIS_PRISMLINEARLGN_H
33 #define CORE_BASIS_PRISMLINEARLGN_H 1
34 
35 #include <float.h>
36 
42 
43 #include <Core/Basis/share.h>
44 
45 namespace SCIRun {
46 namespace Core {
47 namespace Basis {
48 
49 /// Class for describing unit geometry of PrismLinearLgn
51 public:
52  /// Parametric coordinates of vertices of unit edge
53  static SCISHARE double unit_vertices[6][3];
54  /// References to vertices of unit edge
55  static SCISHARE int unit_edges[9][2];
56  /// References to vertices of unit face
57  static SCISHARE int unit_faces[5][4];
58  /// Normals of unit face
59  static SCISHARE double unit_face_normals[5][3];
60  /// Precalculated area of faces
61  static SCISHARE double unit_face_areas[5];
62  /// Center of the unit element
63  static SCISHARE double unit_center[3];
64 
67 
68  /// return dimension of domain
69  static int domain_dimension()
70  { return 3; }
71 
72  /// return size of the domain
73  static double domain_size()
74  { return 0.5; }
75 
76  /// return number of vertices
77  static int number_of_vertices()
78  { return 6; }
79 
80  /// return number of vertices in mesh
82  { return 6; }
83 
84  /// return number of edges
85  static int number_of_edges()
86  { return 9; }
87 
88  /// return degrees of freedom
89  static int dofs()
90  { return 6; }
91 
92  /// return number of vertices per face
93  static int vertices_of_face()
94  { return 3; }
95 
96  /// return number of faces per cell
97  static int faces_of_cell()
98  { return 5; }
99 
100  static inline double length(int edge)
101  { ///< return length
102  const double *v0 = unit_vertices[unit_edges[edge][0]];
103  const double *v1 = unit_vertices[unit_edges[edge][1]];
104  const double dx = v1[0] - v0[0];
105  const double dy = v1[1] - v0[1];
106  const double dz = v1[2] - v0[2];
107  return sqrt(dx*dx+dy*dy+dz*dz);
108  }
109  static double area(int face) { return unit_face_areas[face]; } ///< return area
110  static double volume() { return .5; } ///< return volume
111 };
112 
113 /// Class for creating geometrical approximations of Prism meshes
114 class PrismApprox {
115 public:
116 
118  virtual ~PrismApprox() {}
119 
120  /// Approximate edge for element by piecewise linear segments
121  /// return: coords gives parametric coordinates of the approximation.
122  /// Use interpolate with coordinates to get the world coordinates.
123  template<class VECTOR>
124  void approx_edge(const unsigned edge,
125  const unsigned div_per_unit,
126  VECTOR &coords) const
127  {
128  typedef typename VECTOR::value_type VECTOR2;
129 
130  coords.resize(div_per_unit + 1);
131 
133  const double *v1 = PrismLinearLgnUnitElement::unit_vertices[PrismLinearLgnUnitElement::unit_edges[edge][1]];
134 
135  const double &p1x = v0[0];
136  const double &p1y = v0[1];
137  const double &p1z = v0[2];
138  const double dx = v1[0] - p1x;
139  const double dy = v1[1] - p1y;
140  const double dz = v1[2] - p1z;
141 
142  for(unsigned int i = 0; i <= div_per_unit; i++) {
143  const double d = (double)i / (double)div_per_unit;
144  typename VECTOR::value_type &tmp = coords[i];
145  tmp.resize(3);
146  tmp[0] = static_cast<typename VECTOR2::value_type>(p1x + d * dx);
147  tmp[1] = static_cast<typename VECTOR2::value_type>(p1y + d * dy);
148  tmp[2] = static_cast<typename VECTOR2::value_type>(p1z + d * dz);
149  }
150  }
151 
152  /// Approximate faces for element by piecewise linear elements
153  /// return: coords gives parametric coordinates at the approximation point.
154  /// Use interpolate with coordinates to get the world coordinates.
155  template<class VECTOR>
156  void approx_face(const unsigned face,
157  const unsigned div_per_unit,
158  VECTOR &coords) const
159  {
160  typedef typename VECTOR::value_type VECTOR2;
161  typedef typename VECTOR2::value_type VECTOR3;
162 
163  unsigned int fe = (PrismLinearLgnUnitElement::unit_faces[face][3] == -1 ? 1 : 2);
164  coords.resize(fe * div_per_unit);
165 
166  for(unsigned int f = 0; f<fe; f++)
167  {
168  double *v0, *v1, *v2;
169 
170  if (f==0)
171  {
173  v1 = PrismLinearLgnUnitElement::unit_vertices[PrismLinearLgnUnitElement::unit_faces[face][1]];
174  v2 = PrismLinearLgnUnitElement::unit_vertices[PrismLinearLgnUnitElement::unit_faces[face][2]];
175  } else
176  {
178  v1 = PrismLinearLgnUnitElement::unit_vertices[PrismLinearLgnUnitElement::unit_faces[face][3]];
179  v2 = PrismLinearLgnUnitElement::unit_vertices[PrismLinearLgnUnitElement::unit_faces[face][0]];
180  }
181 
182  const double d = 1. / div_per_unit;
183  for(unsigned int j = 0; j < div_per_unit; j++)
184  {
185  unsigned int k = j + f * div_per_unit;
186  const double dj = (double)j / (double)div_per_unit;
187  unsigned int e = 0;
188  coords[k].resize((div_per_unit - j) * 2 + 1);
189  typename VECTOR2::value_type &tmp = coords[k][e++];
190  tmp.resize(3);
191  tmp[0] = static_cast<typename VECTOR3::value_type>(v0[0] + dj * (v2[0] - v0[0]));
192  tmp[1] = static_cast<typename VECTOR3::value_type>(v0[1] + dj * (v2[1] - v0[1]));
193  tmp[2] = static_cast<typename VECTOR3::value_type>(v0[2] + dj * (v2[2] - v0[2]));
194 
195  for(unsigned int i = 0; i < div_per_unit - j; i++)
196  {
197  const double di = (double)i / (double)div_per_unit;
198  typename VECTOR2::value_type &tmp1 = coords[j + f * div_per_unit][e++];
199  tmp1.resize(3);
200  tmp1[0] = static_cast<typename VECTOR3::value_type>(v0[0] + (dj + d) * (v2[0] - v0[0]) + di * (v1[0] - v0[0]));
201  tmp1[1] = static_cast<typename VECTOR3::value_type>(v0[1] + (dj + d) * (v2[1] - v0[1]) + di * (v1[1] - v0[1]));
202  tmp1[2] = static_cast<typename VECTOR3::value_type>(v0[2] + (dj + d) * (v2[2] - v0[2]) + di * (v1[2] - v0[2]));
203  typename VECTOR2::value_type &tmp2 = coords[j + f * div_per_unit][e++];
204  tmp2.resize(3);
205  tmp2[0] = static_cast<typename VECTOR3::value_type>(v0[0] + dj * (v2[0] - v0[0]) + (di + d) * (v1[0] - v0[0]));
206  tmp2[1] = static_cast<typename VECTOR3::value_type>(v0[1] + dj * (v2[1] - v0[1]) + (di + d) * (v1[1] - v0[1]));
207  tmp2[2] = static_cast<typename VECTOR3::value_type>(v0[2] + dj * (v2[2] - v0[2]) + (di + d) * (v1[2] - v0[2]));
208  }
209  }
210  }
211  }
212 };
213 
214 /// Class for searching of parametric coordinates related to a value in Prism meshes and fields
215 /// to do
216 template <class ElemBasis>
217 class PrismLocate : public Dim3Locate<ElemBasis> {
218 public:
219  typedef typename ElemBasis::value_type T;
220 
222  virtual ~PrismLocate() {}
223 
224  template <class ElemData, class VECTOR>
225  bool get_coords(const ElemBasis *pEB, VECTOR &coords,
226  const T& value, const ElemData &cd) const
227  {
228  initial_guess(pEB, value, cd, coords);
229  if (this->get_iterative(pEB, coords, value, cd))
230  return check_coords(coords);
231  return false;
232  }
233 
234 protected:
235  template <class VECTOR>
236  inline bool check_coords(const VECTOR &x) const
237  {
243  return true;
244 
245  return false;
246  }
247 
248  /// find a reasonable initial guess
249  template <class ElemData, class VECTOR>
250  void initial_guess(const ElemBasis *pElem, const T &val, const ElemData &cd,
251  VECTOR & guess) const
252  {
253  double dist = DBL_MAX;
254 
255  VECTOR coord(3);
256  StackVector<T,3> derivs;
257  guess.resize(3);
258 
259  const int end = 3;
260  for (int x = 1; x < end; x++)
261  {
262  coord[0] = x / (double) end;
263  for (int y = 1; y < end; y++)
264  {
265  coord[1] = y / (double) end;
266  if (coord[0]+coord[1]>Dim3Locate<ElemBasis>::thresholdDist1)
267  break;
268  for (int z = 1; z < end; z++)
269  {
270  coord[2] = z / (double) end;
271  double cur_d;
272  if (compare_distance(pElem->interpolate(coord, cd),
273  val, cur_d, dist))
274  {
275  pElem->derivate(coord, cd, derivs);
276  if (!check_zero(derivs))
277  {
278  dist = cur_d;
279  guess = coord;
280  }
281  }
282  }
283  }
284  }
285  }
286 };
287 
288 
289 /// Class with weights and coordinates for 2nd order Gaussian integration
290 template <class T>
292 {
293 public:
294  static int GaussianNum;
295  static T GaussianPoints[1][3];
296  static T GaussianWeights[1];
297 };
298 
299 #ifdef _WIN32
300 // force the instantiation of PrismGaussian1<double>
301 template class PrismGaussian1<double>;
302 #endif
303 
304 template <class T>
306 
307 template <class T>
309  {1./3.,1./3., 0.5}};
310 
311 template <class T>
313  {1.0};
314 
315 /// Class with weights and coordinates for 2nd order Gaussian integration
316 template <class T>
318 {
319 public:
320  static int GaussianNum;
321  static T GaussianPoints[6][3];
322  static T GaussianWeights[6];
323 };
324 
325 #ifdef _WIN32
326 // force the instantiation of TetGaussian2<double>
327 template class PrismGaussian2<double>;
328 #endif
329 
330 template <class T>
332 
333 template <class T>
335  {1./6.,1./6., 0.211324865405}, {2./3.,1./6., 0.211324865405},
336  {1./6.,2./3., 0.211324865405}, {1./6.,1./6., 0.788675134595},
337  {2./3.,1./6., 0.788675134595}, {1./6.,2./3., 0.788675134595}};
338 
339 template <class T>
340 T PrismGaussian2<T>::GaussianWeights[6] =
341  {1./6., 1./6., 1./6., 1./6., 1./6., 1./6.};
342 
343 /// Class with weights and coordinates for 3rd order Gaussian integration
344 /// to do
345 
346 /// Class for handling of element of type prism with linear lagrangian interpolation
347 template <class T>
349  public BasisSimple<T>,
350  public PrismApprox,
351  public PrismGaussian2<double>,
352  public PrismSamplingSchemes,
354  public PrismElementWeights
355 {
356 public:
357  typedef T value_type;
358 
360  virtual ~PrismLinearLgn() {}
361 
362  static int polynomial_order() { return 1; }
363 
364  template<class VECTOR>
365  inline void get_weights(const VECTOR& coords, double *w) const
366  { get_linear_weights(coords,w); }
367 
368  template<class VECTOR>
369  inline void get_derivate_weights(const VECTOR& coords, double *w) const
370  { get_linear_derivate_weights(coords,w); }
371 
372  /// get value at parametric coordinate
373  template <class ElemData, class VECTOR>
374  T interpolate(const VECTOR &coords, const ElemData &cd) const
375  {
376  double w[6];
377  get_linear_weights(coords, w);
378 
379  return (T)(w[0] * cd.node0() +
380  w[1] * cd.node1() +
381  w[2] * cd.node2() +
382  w[3] * cd.node3() +
383  w[4] * cd.node4() +
384  w[5] * cd.node5());
385  }
386 
387  /// get first derivative at parametric coordinate
388  template <class ElemData, class VECTOR1, class VECTOR2>
389  void derivate(const VECTOR1 &coords, const ElemData &cd,
390  VECTOR2 &derivs) const
391  {
392  double w[18];
393  get_linear_derivate_weights(coords, w);
394 
395  derivs.resize(3);
396 
397  derivs[0] = static_cast<typename VECTOR2::value_type>(
398  w[0] * cd.node0() +
399  w[1] * cd.node1() +
400  w[2] * cd.node2() +
401  w[3] * cd.node3() +
402  w[4] * cd.node4() +
403  w[5] * cd.node5());
404 
405  derivs[1] = static_cast<typename VECTOR2::value_type>(
406  w[6] * cd.node0() +
407  w[7] * cd.node1() +
408  w[8] * cd.node2() +
409  w[9] * cd.node3() +
410  w[10] * cd.node4() +
411  w[11] * cd.node5());
412 
413  derivs[2] = static_cast<typename VECTOR2::value_type>(
414  w[12] * cd.node0() +
415  w[13] * cd.node1() +
416  w[14] * cd.node2() +
417  w[15] * cd.node3() +
418  w[16] * cd.node4() +
419  w[17] * cd.node5()); }
420 
421  /// get parametric coordinate for value within the element
422  template <class ElemData, class VECTOR>
423  bool get_coords(VECTOR &coords, const T& value,
424  const ElemData &cd) const
425  {
427  return CL.get_coords(this, coords, value, cd);
428  }
429 
430  /// get arc length for edge
431  template <class ElemData>
432  double get_arc_length(const unsigned edge, const ElemData &cd) const
433  {
434  return get_arc3d_length<CrvGaussian1<double> >(this, edge, cd);
435  }
436 
437  /// get area
438  template <class ElemData>
439  double get_area(const unsigned face, const ElemData &cd) const
440  {
441  if (unit_faces[face][3]==-1)
442  return get_area3<TriGaussian2<double> >(this, face, cd);
443  else
444  return get_area3<QuadGaussian2<double> >(this, face, cd);
445  }
446 
447  /// get volume
448  template <class ElemData>
449  double get_volume(const ElemData & cd) const
450  {
451  return get_volume3(this, cd);
452  }
453 
454 
455  static const std::string type_name(int n = -1);
456 
457  virtual void io (Piostream& str);
458 
459 };
460 
461 
462 
463 
464 
465 template <class T>
466 const std::string
468 {
469  ASSERT((n >= -1) && n <= 1);
470  if (n == -1)
471  {
472  static const std::string name = TypeNameGenerator::make_template_id(type_name(0), type_name(1));
473  return name;
474  }
475  else if (n == 0)
476  {
477  static const std::string nm("PrismLinearLgn");
478  return nm;
479  } else {
480  return find_type_name((T *)0);
481  }
482 }
483 
484 
485 
486 
487 }}
488 template <class T>
490 {
491  static TypeDescription* td = 0;
492  if(!td){
493  const TypeDescription *sub = get_type_description((T*)0);
495  (*subs)[0] = sub;
496  td = new TypeDescription("PrismLinearLgn", subs,
497  std::string(__FILE__),
498  "SCIRun",
500  }
501  return td;
502 }
503 
505 template <class T>
506 void
508 {
509  stream.begin_class(get_type_description(this)->get_name(),
511  stream.end_class();
512 }
513 }
514 
515 #endif
void initial_guess(const ElemBasis *pElem, const T &val, const ElemData &cd, VECTOR &guess) const
find a reasonable initial guess
Definition: PrismLinearLgn.h:250
void approx_face(const unsigned face, const unsigned div_per_unit, VECTOR &coords) const
Definition: PrismLinearLgn.h:156
T value_type
Definition: PrismLinearLgn.h:357
Class for creating geometrical approximations of Prism meshes.
Definition: PrismLinearLgn.h:114
static int GaussianNum
Definition: PrismLinearLgn.h:320
double check_zero(const VECTOR &derivs, double epsilon=1e-7)
Definition: Locate.h:709
PrismLinearLgnUnitElement()
Definition: PrismLinearLgn.h:65
Class for describing unit geometry of PrismLinearLgn.
Definition: PrismLinearLgn.h:50
static SCISHARE int unit_edges[9][2]
References to vertices of unit edge.
Definition: PrismLinearLgn.h:55
static int vertices_of_face()
return number of vertices per face
Definition: PrismLinearLgn.h:93
static SCISHARE double unit_center[3]
Center of the unit element.
Definition: PrismLinearLgn.h:63
static SCISHARE double unit_vertices[6][3]
Parametric coordinates of vertices of unit edge.
Definition: PrismLinearLgn.h:53
Definition: Persistent.h:89
Definition: PrismLinearLgn.h:217
bool get_coords(const ElemBasis *pEB, VECTOR &coords, const T &value, const ElemData &cd) const
Definition: PrismLinearLgn.h:225
Class with weights and coordinates for 2nd order Gaussian integration.
Definition: PrismLinearLgn.h:317
virtual ~PrismLinearLgnUnitElement()
Definition: PrismLinearLgn.h:66
void get_derivate_weights(const VECTOR &coords, double *w) const
Definition: PrismLinearLgn.h:369
Definition: TypeDescription.h:45
#define SCISHARE
Definition: share.h:39
std::vector< const TypeDescription * > td_vec
Definition: TypeDescription.h:56
static const std::string type_name(int n=-1)
Definition: PrismLinearLgn.h:467
static int faces_of_cell()
return number of faces per cell
Definition: PrismLinearLgn.h:97
static T GaussianPoints[1][3]
Definition: PrismLinearLgn.h:295
ElemBasis::value_type T
Definition: Locate.h:549
virtual void io(Piostream &str)
Definition: PrismLinearLgn.h:507
#define ASSERT(condition)
Definition: Assert.h:110
Class for describing interfaces to basis elements.
Definition: Basis.h:48
virtual int begin_class(const std::string &name, int current_version)
Definition: Persistent.cc:143
const string find_type_name(float *)
Definition: TypeName.cc:63
static SCISHARE int unit_faces[5][4]
References to vertices of unit face.
Definition: PrismLinearLgn.h:57
static T GaussianWeights[1]
Definition: PrismLinearLgn.h:296
Class with weights and coordinates for 2nd order Gaussian integration.
Definition: PrismLinearLgn.h:291
static int number_of_vertices()
return number of vertices
Definition: PrismLinearLgn.h:77
const char * name[]
Definition: BoostGraphExampleTests.cc:87
void approx_edge(const unsigned edge, const unsigned div_per_unit, VECTOR &coords) const
Definition: PrismLinearLgn.h:124
Definition: StackVector.h:50
double get_arc_length(const unsigned edge, const ElemData &cd) const
get arc length for edge
Definition: PrismLinearLgn.h:432
static int GaussianNum
Definition: PrismLinearLgn.h:294
static double volume()
return volume
Definition: PrismLinearLgn.h:110
bool check_coords(const VECTOR &x) const
Definition: PrismLinearLgn.h:236
T interpolate(const VECTOR &coords, const ElemData &cd) const
get value at parametric coordinate
Definition: PrismLinearLgn.h:374
double get_area(const unsigned face, const ElemData &cd) const
get area
Definition: PrismLinearLgn.h:439
static double length(int edge)
Definition: PrismLinearLgn.h:100
static int number_of_edges()
return number of edges
Definition: PrismLinearLgn.h:85
void derivate(const VECTOR1 &coords, const ElemData &cd, VECTOR2 &derivs) const
get first derivative at parametric coordinate
Definition: PrismLinearLgn.h:389
Definition: PrismElementWeights.h:36
PrismApprox()
Definition: PrismLinearLgn.h:117
virtual ~PrismApprox()
Definition: PrismLinearLgn.h:118
virtual ~PrismLinearLgn()
Definition: PrismLinearLgn.h:360
Definition: PrismSamplingSchemes.h:42
static const std::string make_template_id(const std::string &templateName, const std::string &templateParam)
Definition: TypeName.h:62
static SCISHARE double unit_face_normals[5][3]
Normals of unit face.
Definition: PrismLinearLgn.h:59
static SCISHARE double unit_face_areas[5]
Precalculated area of faces.
Definition: PrismLinearLgn.h:61
static int polynomial_order()
Definition: PrismLinearLgn.h:362
static int dofs()
return degrees of freedom
Definition: PrismLinearLgn.h:89
PrismLinearLgn()
Definition: PrismLinearLgn.h:359
bool compare_distance(const T &interp, const T &val, double &cur_d, double dist)
Definition: Locate.h:667
virtual void end_class()
Definition: Persistent.cc:178
virtual ~PrismLocate()
Definition: PrismLinearLgn.h:222
static double domain_size()
return size of the domain
Definition: PrismLinearLgn.h:73
void resize(size_t size, const value_type &val=value_type())
Definition: StackVector.h:61
Class for handling of element of type prism with linear lagrangian interpolation. ...
Definition: PrismLinearLgn.h:348
PrismLocate()
Definition: PrismLinearLgn.h:221
Definition: Locate.h:547
ElemBasis::value_type T
Definition: PrismLinearLgn.h:219
bool get_coords(VECTOR &coords, const T &value, const ElemData &cd) const
get parametric coordinate for value within the element
Definition: PrismLinearLgn.h:423
const int PRISMLINEARLGN_VERSION
Definition: PrismLinearLgn.h:504
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:559
double get_volume3(const ElemBasis *pEB, const ElemData &cd)
Definition: Locate.h:179
static int number_of_mesh_vertices()
return number of vertices in mesh
Definition: PrismLinearLgn.h:81
double get_volume(const ElemData &cd) const
get volume
Definition: PrismLinearLgn.h:449
static double area(int face)
return area
Definition: PrismLinearLgn.h:109
static int domain_dimension()
return dimension of domain
Definition: PrismLinearLgn.h:69
Definition: TypeDescription.h:49
void get_weights(const VECTOR &coords, double *w) const
Definition: PrismLinearLgn.h:365
const TypeDescription * get_type_description(Core::Basis::ConstantBasis< T > *)
Definition: Constant.h:209