SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LatVolMesh.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 
29 
30 #ifndef CORE_DATATYPES_LATVOLMESH_H
31 #define CORE_DATATYPES_LATVOLMESH_H 1
32 
33 /// Include what kind of support we want to have
34 /// Need to fix this and couple it to sci-defs
36 
38 
39 #include <Core/Basis/Locate.h>
41 
44 #include <Core/Math/MiscMath.h>
45 
51 
53 
54 namespace SCIRun {
55 
56 /////////////////////////////////////////////////////
57 // Declarations for virtual interface
58 
59 
60 /// Functions for creating the virtual interface
61 /// Declare the functions that instantiate the virtual interface
62 template <class Basis>
63 class LatVolMesh;
64 
65 /// make sure any other mesh other than the preinstantiate ones
66 /// returns no virtual interface. Altering this behavior will allow
67 /// for dynamically compiling the interface if needed.
68 template<class MESH>
69 VMesh* CreateVLatVolMesh(MESH*) { return (0); }
70 
71 /// These declarations are needed for a combined dynamic compilation as
72 /// as well as virtual functions solution.
73 /// Declare that these can be found in a library that is already
74 /// precompiled. So dynamic compilation will not instantiate them again.
75 
76 #if (SCIRUN_LATVOL_SUPPORT > 0)
77 
78 SCISHARE VMesh* CreateVLatVolMesh(LatVolMesh<Core::Basis::HexTrilinearLgn<Core::Geometry::Point> >* mesh);
79 
80 #endif
81 /////////////////////////////////////////////////////
82 
83 
84 template <class Basis>
85 class LatVolMesh : public Mesh
86 {
87 
88 template <class MESH>
89 friend class VLatVolMesh;
90 
91 public:
92  // Types that change depending on 32 or 64bits
97 
98  typedef boost::shared_ptr<LatVolMesh<Basis> > handle_type;
99  typedef Basis basis_type;
100 
101  struct LatIndex;
102  friend struct LatIndex;
103 
104  struct LatIndex
105  {
106  public:
107  LatIndex() : i_(0), j_(0), k_(0), mesh_(0) {}
109  i_(i), j_(j), k_(k), mesh_(m) {}
110 
111  operator index_type() const {
112  ASSERT(mesh_);
113  return i_ + ni()*j_ + ni()*nj()*k_;
114  }
115 
116  std::ostream& str_render(std::ostream& os) const
117  {
118  os << "[" << i_ << "," << j_ << "," << k_ << "]";
119  return os;
120  }
121 
122  // Make sure mesh_ is valid before calling these convience accessors
123  index_type ni() const { ASSERT(mesh_); return mesh_->get_ni(); }
124  index_type nj() const { ASSERT(mesh_); return mesh_->get_nj(); }
125  index_type nk() const { ASSERT(mesh_); return mesh_->get_nk(); }
126 
128 
129  // Needs to be here so we can compute a sensible index.
131  };
132 
133  struct CellIndex : public LatIndex
134  {
137  : LatIndex(m, i,j,k) {}
138 
139  operator index_type() const {
140  ASSERT(this->mesh_);
141  return (this->i_ + (this->ni()-1)*this->j_ +
142  (this->ni()-1)*(this->nj()-1)*this->k_);
143  }
144  };
145 
146  struct NodeIndex : public LatIndex
147  {
150  : LatIndex(m, i,j,k) {}
151  static std::string type_name(int i=-1) {
152  ASSERT(i < 1);
153  return LatVolMesh<Basis>::type_name(-1) + "::NodeIndex";
154  }
155  };
156 
157 
158  struct LatSize
159  {
160  public:
161  LatSize() : i_(0), j_(0), k_(0) {}
162  LatSize(size_type i, size_type j, size_type k) : i_(i), j_(j), k_(k) {}
163 
164  operator size_type() const { return i_*j_*k_; }
165 
166  std::ostream& str_render(std::ostream& os) const {
167  os << i_*j_*k_ << " (" << i_ << " x " << j_ << " x " << k_ << ")";
168  return os;
169  }
170 
172  };
173 
174  struct CellSize : public LatSize
175  {
176  CellSize() : LatSize() {}
178  };
179 
180  struct NodeSize : public LatSize
181  {
182  NodeSize() : LatSize() {}
184  };
185 
186 
187  struct LatIter : public LatIndex
188  {
189  LatIter() : LatIndex() {}
191  : LatIndex(m, i, j, k) {}
192 
193  const LatIndex &operator *() { return *this; }
194 
195  bool operator ==(const LatIter &a) const
196  {
197  return (this->i_ == a.i_ && this->j_ == a.j_ &&
198  this->k_ == a.k_ && this->mesh_ == a.mesh_);
199  }
200 
201  bool operator !=(const LatIter &a) const
202  {
203  return !(*this == a);
204  }
205  };
206 
207 
208  struct NodeIter : public LatIter
209  {
210  NodeIter() : LatIter() {}
212  : LatIter(m, i, j, k) {}
213 
214  const NodeIndex &operator *() const { return (const NodeIndex&)(*this); }
215 
217  {
218  this->i_++;
219  if (this->i_ >= this->mesh_->min_i_+this->mesh_->get_ni()) {
220  this->i_ = this->mesh_->min_i_;
221  this->j_++;
222  if (this->j_ >= this->mesh_->min_j_+this->mesh_->get_nj()) {
223  this->j_ = this->mesh_->min_j_;
224  this->k_++;
225  }
226  }
227  return *this;
228  }
229 
230  private:
231 
232  NodeIter operator++(int)
233  {
234  NodeIter result(*this);
235  operator++();
236  return result;
237  }
238  };
239 
240 
241  struct CellIter : public LatIter
242  {
243  CellIter() : LatIter() {}
245  : LatIter(m, i, j, k) {}
246 
247  const CellIndex &operator *() const { return (const CellIndex&)(*this); }
248 
249  operator index_type() const {
250  ASSERT(this->mesh_);
251  return this->i_ + (this->ni()-1)*this->j_ + (this->ni()-1)*(this->nj()-1)*this->k_;;
252  }
253 
255  {
256  this->i_++;
257  if (this->i_ >= this->mesh_->min_i_+this->ni()-1) {
258  this->i_ = this->mesh_->min_i_;
259  this->j_++;
260  if (this->j_ >= this->mesh_->min_j_+this->nj()-1) {
261  this->j_ = this->mesh_->min_j_;
262  this->k_++;
263  }
264  }
265  return *this;
266  }
267 
268  private:
269 
270  CellIter operator++(int)
271  {
272  CellIter result(*this);
273  operator++();
274  return result;
275  }
276  };
277 
278  //////////////////////////////////////////////////////////////////
279  // Range Iterators
280  //
281  // These iterators are designed to loop over a sub-set of the mesh
282  //
283 
284  struct RangeNodeIter : public NodeIter
285  {
287  // Pre: min, and max are both valid iterators over this mesh
288  // min.A <= max.A where A is (i_, j_, k_)
290  index_type max_i, index_type max_j, index_type max_k)
291  : NodeIter(m, i, j, k), min_i_(i), min_j_(j), min_k_(k),
292  max_i_(max_i), max_j_(max_j), max_k_(max_k)
293  {}
294 
295  const NodeIndex &operator *() const { return (const NodeIndex&)(*this); }
296 
298  {
299  this->i_++;
300  // Did i_ loop over the line
301  // mesh_->min_x is the starting point of the x range for the mesh
302  // min_i_ is the starting point of the range on x
303  // max_i_ is the ending point of the range on x
304  if (this->i_ >= this->mesh_->min_i_ + max_i_) {
305  // set i_ to the beginning of the range
306  this->i_ = min_i_;
307  this->j_++;
308  // Did j_ loop over the face
309  // mesh_->min_j_ is the starting point of the y range for the mesh
310  // min_j is the starting point of the range on y
311  // max_j is the ending point of the range on y
312  if (this->j_ >= this->mesh_->min_j_ + max_j_) {
313  this->j_ = min_j_;
314  this->k_++;
315  }
316  }
317  return *this;
318  }
319 
320  void end(NodeIter &end_iter)
321  {
322  // This tests is designed for a slice in the xy plane. If z (or k)
323  // is equal then you have this condition. When this happens you
324  // need to increment k so that you will iterate over the xy values.
325  if (min_k_ != max_k_)
326  end_iter = NodeIter(this->mesh_, min_i_, min_j_, max_k_);
327  else {
328  // We need to check to see if the min and max extents are the same.
329  // If they are then set the end iterator such that it will be equal
330  // to the beginning. When they are the same anj for() loop using
331  // these iterators [for(;iter != end_iter; iter++)] will never enter.
332  if (min_i_ != max_i_ || min_j_ != max_j_)
333  end_iter = NodeIter(this->mesh_, min_i_, min_j_, max_k_ + 1);
334  else
335  end_iter = NodeIter(this->mesh_, min_i_, min_j_, max_k_);
336  }
337  }
338 
339  private:
340  // The minimum extents
341  index_type min_i_, min_j_, min_k_;
342  // The maximum extents
343  index_type max_i_, max_j_, max_k_;
344 
346  {
347  RangeNodeIter result(*this);
348  operator++();
349  return result;
350  }
351  };
352 
353  struct RangeCellIter : public CellIter
354  {
356  // Pre: min, and max are both valid iterators over this mesh
357  // min.A <= max.A where A is (i_, j_, k_)
359  index_type max_i, index_type max_j, index_type max_k)
360  : CellIter(m, i, j, k), min_i_(i), min_j_(j), min_k_(k),
361  max_i_(max_i), max_j_(max_j), max_k_(max_k)
362  {}
363 
364  const CellIndex &operator *() const { return (const CellIndex&)(*this); }
365 
367  {
368  this->i_++;
369  // Did i_ loop over the line
370  // mesh_->min_x is the starting point of the x range for the mesh
371  // min_i_ is the starting point of the range on x
372  // max_i_ is the ending point of the range on x
373  if (this->i_ >= this->mesh_->min_i_ + max_i_) {
374  // set i_ to the beginning of the range
375  this->i_ = min_i_;
376  this->j_++;
377  // Did j_ loop over the face
378  // mesh_->min_j_ is the starting point of the y range for the mesh
379  // min_j is the starting point of the range on y
380  // max_j is the ending point of the range on y
381  if (this->j_ >= this->mesh_->min_j_ + max_j_) {
382  this->j_ = min_j_;
383  this->k_++;
384  }
385  }
386  return *this;
387  }
388 
389  void end(CellIter &end_iter) {
390  // This tests is designed for a slice in the xy plane. If z (or k)
391  // is equal then you have this condition. When this happens you
392  // need to increment k so that you will iterate over the xy values.
393  if (min_k_ != max_k_)
394  end_iter = CellIter(this->mesh_, min_i_, min_j_, max_k_);
395  else {
396  // We need to check to see if the min and max extents are the same.
397  // If they are then set the end iterator such that it will be equal
398  // to the beginning. When they are the same anj for() loop using
399  // these iterators [for(;iter != end_iter; iter++)] will never enter.
400  if (min_i_ != max_i_ || min_j_ != max_j_)
401  end_iter = CellIter(this->mesh_, min_i_, min_j_, max_k_ + 1);
402  else
403  end_iter = CellIter(this->mesh_, min_i_, min_j_, max_k_);
404  }
405  }
406 
407  private:
408  // The minimum extents
409  index_type min_i_, min_j_, min_k_;
410  // The maximum extents
411  index_type max_i_, max_j_, max_k_;
412 
414  {
415  RangeCellIter result(*this);
416  operator++();
417  return result;
418  }
419  };
420 
421 
422  /// Index and Iterator types required for Mesh Concept.
423  struct Node {
429  };
430 
431  struct Edge {
435  typedef std::vector<index_type> array_type;
436  };
437 
438  struct Face {
442  typedef std::vector<index_type> array_type;
443  };
444 
445  struct Cell {
449  typedef std::vector<index_type> array_type;
451  };
452 
453  typedef Cell Elem;
454  typedef Face DElem;
455 
456  friend struct NodeIter;
457  friend struct CellIter;
458  friend struct EdgeIter;
459  friend struct FaceIter;
460 
461  friend struct RangeCellIter;
462  friend struct RangeNodeIter;
463 
464  friend class ElemData;
465 
466  class ElemData
467  {
468  public:
470 
472  const typename Cell::index_type ind) :
473  mesh_(msh),
474  index_(ind)
475  {}
476 
477  // the following designed to coordinate with ::get_nodes
478  inline
480  return (index_.i_ + mesh_.get_ni()*index_.j_ +
481  mesh_.get_ni()*mesh_.get_nj()*index_.k_);
482  }
483  inline
485  return (index_.i_+ 1 + mesh_.get_ni()*index_.j_ +
486  mesh_.get_ni()*mesh_.get_nj()*index_.k_);
487  }
488  inline
490  return (index_.i_ + 1 + mesh_.get_ni()*(index_.j_ + 1) +
491  mesh_.get_ni()*mesh_.get_nj()*index_.k_);
492 
493  }
494  inline
496  return (index_.i_ + mesh_.get_ni()*(index_.j_ + 1) +
497  mesh_.get_ni()*mesh_.get_nj()*index_.k_);
498  }
499  inline
501  return (index_.i_ + mesh_.get_ni()*index_.j_ +
502  mesh_.get_ni()*mesh_.get_nj()*(index_.k_ + 1));
503  }
504  inline
506  return (index_.i_ + 1 + mesh_.get_ni()*index_.j_ +
507  mesh_.get_ni()*mesh_.get_nj()*(index_.k_ + 1));
508  }
509 
510  inline
512  return (index_.i_ + 1 + mesh_.get_ni()*(index_.j_ + 1) +
513  mesh_.get_ni()*mesh_.get_nj()*(index_.k_ + 1));
514  }
515  inline
517  return (index_.i_ + mesh_.get_ni()*(index_.j_ + 1) +
518  mesh_.get_ni()*mesh_.get_nj()*(index_.k_ + 1));
519  }
520 
521  inline
522  const Core::Geometry::Point node0() const {
523  Core::Geometry::Point p(index_.i_, index_.j_, index_.k_);
524  return mesh_.transform_.project(p);
525  }
526  inline
527  const Core::Geometry::Point node1() const {
528  Core::Geometry::Point p(index_.i_ + 1, index_.j_, index_.k_);
529  return mesh_.transform_.project(p);
530  }
531  inline
532  const Core::Geometry::Point node2() const {
533  Core::Geometry::Point p(index_.i_ + 1, index_.j_ + 1, index_.k_);
534  return mesh_.transform_.project(p);
535  }
536  inline
537  const Core::Geometry::Point node3() const {
538  Core::Geometry::Point p(index_.i_, index_.j_ + 1, index_.k_);
539  return mesh_.transform_.project(p);
540  }
541  inline
542  const Core::Geometry::Point node4() const {
543  Core::Geometry::Point p(index_.i_, index_.j_, index_.k_+ 1);
544  return mesh_.transform_.project(p);
545  }
546  inline
547  const Core::Geometry::Point node5() const {
548  Core::Geometry::Point p(index_.i_ + 1, index_.j_, index_.k_+ 1);
549  return mesh_.transform_.project(p);
550  }
551  inline
552  const Core::Geometry::Point node6() const {
553  Core::Geometry::Point p(index_.i_ + 1, index_.j_ + 1, index_.k_+ 1);
554  return mesh_.transform_.project(p);
555  }
556  inline
557  const Core::Geometry::Point node7() const {
558  Core::Geometry::Point p(index_.i_, index_.j_ + 1, index_.k_+ 1);
559  return mesh_.transform_.project(p);
560  }
561 
562  private:
563  const LatVolMesh<Basis> &mesh_;
564  const typename Cell::index_type index_;
565  };
566 
567 
569  min_i_(0),
570  min_j_(0),
571  min_k_(0),
572  ni_(1),
573  nj_(1),
574  nk_(1)
575  {
576  DEBUG_CONSTRUCTOR("LatVolMesh")
578 
579  /// Create a new virtual interface for this copy
580  /// all pointers have changed hence create a new
581  /// virtual interface class
582  vmesh_.reset(CreateVLatVolMesh(this));
583  }
584 
586  const Core::Geometry::Point &min, const Core::Geometry::Point &max);
587 
588  LatVolMesh(LatVolMesh* /* mh */,
589  size_type mx, size_type my, size_type mz,
590  size_type x, size_type y, size_type z) :
591  min_i_(mx),
592  min_j_(my),
593  min_k_(mz),
594  ni_(x),
595  nj_(y),
596  nk_(z)
597  {
598  DEBUG_CONSTRUCTOR("LatVolMesh")
599  compute_jacobian();
600 
601  /// Create a new virtual interface for this copy
602  /// all pointers have changed hence create a new
603  /// virtual interface class
604  vmesh_.reset(CreateVLatVolMesh(this));
605  }
606 
607  LatVolMesh(const LatVolMesh &copy) :
608  Mesh(copy),
609  min_i_(copy.min_i_),
610  min_j_(copy.min_j_),
611  min_k_(copy.min_k_),
612  ni_(copy.get_ni()),
613  nj_(copy.get_nj()),
614  nk_(copy.get_nk()),
615  transform_(copy.transform_),
616  basis_(copy.basis_)
617  {
618  DEBUG_CONSTRUCTOR("LatVolMesh")
620  compute_jacobian();
621 
622  /// Create a new virtual interface for this copy
623  /// all pointers have changed hence create a new
624  /// virtual interface class
625  vmesh_.reset(CreateVLatVolMesh(this));
626  }
627 
628  virtual LatVolMesh *clone() const { return new LatVolMesh(*this); }
629  virtual ~LatVolMesh()
630  {
631  DEBUG_DESTRUCTOR("LatVolMesh")
632  }
633 
634  /// Access point to virtual interface
635  virtual VMesh* vmesh() {
636  return (vmesh_.get());
637  }
638 
639  virtual MeshFacadeHandle getFacade() const { return boost::make_shared<Core::Datatypes::VirtualMeshFacade<VMesh>>(vmesh_); }
640 
641  virtual int basis_order() { return (basis_.polynomial_order()); }
642 
643  virtual bool has_normals() const { return false; }
644  virtual bool has_face_normals() const { return false; }
645  virtual bool is_editable() const { return false; }
646 
647  Basis &get_basis() { return basis_; }
648 
649  /// Generate the list of points that make up a sufficiently accurate
650  /// piecewise linear approximation of an edge.
651  void pwl_approx_edge(std::vector<std::vector<double> > &coords,
652  typename Elem::index_type /*ci*/,
653  unsigned int which_edge,
654  unsigned int div_per_unit) const
655  {
656  // Needs to match unit_edges in Basis/HexTrilinearLgn.cc
657  // compare get_nodes order to the basis order
658  int emap[] = {0, 2, 8, 10, 3, 1, 11, 9, 4, 5, 7, 6};
659  basis_.approx_edge(emap[which_edge], div_per_unit, coords);
660  }
661 
662  /// Generate the list of points that make up a sufficiently accurate
663  /// piecewise linear approximation of an face.
664  void pwl_approx_face(std::vector<std::vector<std::vector<double> > > &coords,
665  typename Elem::index_type /*ci*/,
666  unsigned int which_face,
667  unsigned int div_per_unit) const
668  {
669  // Needs to match unit_edges in Basis/HexTrilinearLgn.cc
670  // compare get_nodes order to the basis order
671  int fmap[] = {0, 5, 4, 2, 1, 3};
672  basis_.approx_face(fmap[which_face], div_per_unit, coords);
673  }
674 
675  /// Synchronize functions, as there is nothing to synchronize, these
676  /// functions always succeed
677 
678  virtual bool synchronize(mask_type /*sync*/) { return (true); }
679  virtual bool unsynchronize(mask_type /*sync*/) { return (true); }
680  bool clear_synchronization() { return (true); }
681 
682  /// Get the local coordinates for a certain point within an element
683  /// This function uses a couple of newton iterations to find the local
684  /// coordinate of a point
685  template<class VECTOR>
686  bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, typename Elem::index_type idx) const
687  {
688  // If polynomial order is larger, use the complicated HO basis implementation
689  // Since this is a latvol and most probably linear, this function is to expensive
690  if (basis_.polynomial_order() > 1)
691  {
692  ElemData ed(*this, idx);
693  return (basis_.get_coords(coords, p, ed));
694  }
695 
696  // Cheap implementation that assumes it is a regular grid
697  // This implementation should be faster then the interpolate of the linear
698  // basis which needs to work as well for the unstructured hexvol :(
700  coords.resize(3);
701  coords[0] = static_cast<typename VECTOR::value_type>(r.x()-static_cast<double>(idx.i_));
702  coords[1] = static_cast<typename VECTOR::value_type>(r.y()-static_cast<double>(idx.j_));
703  coords[2] = static_cast<typename VECTOR::value_type>(r.z()-static_cast<double>(idx.k_));
704 
705  const double epsilon = 1e-8;
706 
707  if (static_cast<double>(coords[0]) < 0.0) if (static_cast<double>(coords[0]) > -(epsilon))
708  coords[0] = static_cast<typename VECTOR::value_type>(0.0); else return (false);
709  if (static_cast<double>(coords[0]) > 1.0) if (static_cast<double>(coords[0]) < 1.0+(epsilon))
710  coords[0] = static_cast<typename VECTOR::value_type>(1.0); else return (false);
711  if (static_cast<double>(coords[1]) < 0.0) if (static_cast<double>(coords[1]) > -(epsilon))
712  coords[1] = static_cast<typename VECTOR::value_type>(0.0); else return (false);
713  if (static_cast<double>(coords[1]) > 1.0) if (static_cast<double>(coords[1]) < 1.0+(epsilon))
714  coords[1] = static_cast<typename VECTOR::value_type>(1.0); else return (false);
715  if (static_cast<double>(coords[2]) < 0.0) if (static_cast<double>(coords[2]) > -(epsilon))
716  coords[2] = static_cast<typename VECTOR::value_type>(0.0); else return (false);
717  if (static_cast<double>(coords[2]) > 1.0) if (static_cast<double>(coords[2]) < 1.0+(epsilon))
718  coords[2] = static_cast<typename VECTOR::value_type>(1.0); else return (false);
719 
720  return (true);
721  }
722 
723  /// Find the location in the global coordinate system for a local coordinate
724  /// This function is the opposite of get_coords.
725  template<class VECTOR>
726  void interpolate(Core::Geometry::Point &pt, const VECTOR &coords, typename Elem::index_type idx) const
727  {
728  // only makes sense for higher order
729  if (basis_.polynomial_order() > 1)
730  {
731  ElemData ed(*this, idx);
732  pt = basis_.interpolate(coords, ed);
733  return;
734  }
735  // Cheaper implementation
736 
737  Core::Geometry::Point p(static_cast<double>(idx.i_)+static_cast<double>(coords[0]),
738  static_cast<double>(idx.j_)+static_cast<double>(coords[1]),
739  static_cast<double>(idx.k_)+static_cast<double>(coords[2]));
740  pt = transform_.project(p);
741 
742  }
743 
744  /// Interpolate the derivate of the function, This infact will return the
745  /// jacobian of the local to global coordinate transformation. This function
746  /// is mainly intended for the non linear elements
747  template<class VECTOR1, class VECTOR2>
748  void derivate(const VECTOR1 &coords, typename Elem::index_type idx, VECTOR2 &J) const
749  {
750  // only makes sense for higher order
751  if (basis_.polynomial_order() > 1)
752  {
753  ElemData ed(*this, idx);
754  basis_.derivate(coords, ed, J);
755  return;
756  }
757 
758  // Cheaper implementation
759  J.resize(3);
760  J[0] = (transform_.project(Core::Geometry::Vector(1.0,0.0,0.0))).asPoint();
761  J[1] = (transform_.project(Core::Geometry::Vector(0.0,1.0,0.0))).asPoint();
762  J[2] = (transform_.project(Core::Geometry::Vector(0.0,0.0,1.0))).asPoint();
763 
764  }
765 
766  /// Get the determinant of the jacobian, which is the local volume of an element
767  /// and is intended to help with the integration of functions over an element.
768  template<class VECTOR>
769  double det_jacobian(const VECTOR& coords, typename Elem::index_type idx) const
770  {
771  return (det_jacobian_);
772  }
773 
774  /// Get the jacobian of the transformation. In case one wants the non inverted
775  /// version of this matrix. This is currentl here for completeness of the
776  /// interface
777  template<class VECTOR>
778  void jacobian(const VECTOR& coords, typename Elem::index_type idx, double* J) const
779  {
780  J[0] = jacobian_[0];
781  J[1] = jacobian_[1];
782  J[2] = jacobian_[2];
783  J[3] = jacobian_[3];
784  J[4] = jacobian_[4];
785  J[5] = jacobian_[5];
786  J[6] = jacobian_[6];
787  J[7] = jacobian_[7];
788  J[8] = jacobian_[8];
789  }
790 
791  /// Get the inverse jacobian of the transformation. This one is needed to
792  /// translate local gradients into global gradients. Hence it is crucial for
793  /// calculating gradients of fields, or constructing finite elements.
794  template<class VECTOR>
795  double inverse_jacobian(const VECTOR& /*coords*/, typename Elem::index_type /*idx*/, double* Ji) const
796  {
797  Ji[0] = inverse_jacobian_[0];
798  Ji[1] = inverse_jacobian_[1];
799  Ji[2] = inverse_jacobian_[2];
800  Ji[3] = inverse_jacobian_[3];
801  Ji[4] = inverse_jacobian_[4];
802  Ji[5] = inverse_jacobian_[5];
803  Ji[6] = inverse_jacobian_[6];
804  Ji[7] = inverse_jacobian_[7];
805  Ji[8] = inverse_jacobian_[8];
806 
807  return (det_inverse_jacobian_);
808  }
809 
810  double scaled_jacobian_metric(typename Elem::index_type /*idx*/) const
811  { return (scaled_jacobian_); }
812 
813  double jacobian_metric(typename Elem::index_type /*idx*/) const
814  { return (det_jacobian_); }
815 
816  /// get the mesh statistics
817  index_type get_min_i() const { return min_i_; }
818  index_type get_min_j() const { return min_j_; }
819  index_type get_min_k() const { return min_k_; }
820  bool get_min(std::vector<index_type>&) const;
821  index_type get_ni() const { return ni_; }
822  index_type get_nj() const { return nj_; }
823  index_type get_nk() const { return nk_; }
824  virtual bool get_dim(std::vector<size_type>&) const;
826 
827  virtual Core::Geometry::BBox get_bounding_box() const;
828  virtual void transform(const Core::Geometry::Transform &t);
830 
831  /// set the mesh statistics
832  void set_min_i(index_type i) {min_i_ = i; }
833  void set_min_j(index_type j) {min_j_ = j; }
834  void set_min_k(index_type k) {min_k_ = k; }
835  void set_min(std::vector<index_type> mins);
837  {
838  ni_ = i;
839 
840  vmesh_.reset(CreateVLatVolMesh(this));
841  }
843  {
844  nj_ = j;
845 
846  vmesh_.reset(CreateVLatVolMesh(this));
847  }
849  {
850  nk_ = k;
851 
852  /// Create a new virtual interface for this copy
853  /// all pointers have changed hence create a new
854  /// virtual interface class
855  vmesh_.reset(CreateVLatVolMesh(this));
856  }
857  virtual void set_dim(std::vector<size_type> dims);
858 
859  void begin(typename Node::iterator &) const;
860  void begin(typename Edge::iterator &) const;
861  void begin(typename Face::iterator &) const;
862  void begin(typename Cell::iterator &) const;
863 
864  void end(typename Node::iterator &) const;
865  void end(typename Edge::iterator &) const;
866  void end(typename Face::iterator &) const;
867  void end(typename Cell::iterator &) const;
868 
869  void size(typename Node::size_type &) const;
870  void size(typename Edge::size_type &) const;
871  void size(typename Face::size_type &) const;
872  void size(typename Cell::size_type &) const;
873 
874  void to_index(typename Node::index_type &index, index_type i) const;
875  void to_index(typename Edge::index_type &index, index_type i) const
876  { index = i; }
877  void to_index(typename Face::index_type &index, index_type i) const
878  { index = i; }
879  void to_index(typename Cell::index_type &index, index_type i) const;
880 
881  /// get the child elements of the given index
882  void get_nodes(typename Node::array_type &, typename Edge::index_type) const;
883  void get_nodes(typename Node::array_type &, typename Face::index_type) const;
884  void get_nodes(typename Node::array_type &,
885  const typename Cell::index_type &) const;
886  void get_edges(typename Edge::array_type &,
887  typename Face::index_type) const;
888  void get_edges(typename Edge::array_type &,
889  const typename Cell::index_type &) const;
890  void get_faces(typename Face::array_type &,
891  const typename Cell::index_type &) const;
892 
893  /// get the parent element(s) of the given index
894  void get_elems(typename Elem::array_type &result,
895  const typename Node::index_type &idx) const;
896  void get_elems(typename Elem::array_type &result,
897  const typename Edge::index_type &idx) const;
898  void get_elems(typename Elem::array_type &result,
899  const typename Face::index_type &idx) const;
900 
901 
902  /// Wrapper to get the derivative elements from this element.
903  void get_delems(typename DElem::array_type &result,
904  const typename Elem::index_type &idx) const
905  {
906  get_faces(result, idx);
907  }
908 
909  /// return all cell_indecies that overlap the BBox in arr.
910  void get_cells(typename Cell::array_type &arr, const Core::Geometry::BBox &box);
911  /// returns the min and max indices that fall within or on the BBox
912  void get_cells(typename Cell::index_type &begin,
913  typename Cell::index_type &end,
914  const Core::Geometry::BBox &bbox);
915  void get_nodes(typename Node::index_type &begin,
916  typename Node::index_type &end,
917  const Core::Geometry::BBox &bbox);
918 
919  bool get_neighbor(typename Cell::index_type &neighbor,
920  const typename Cell::index_type &from,
921  typename Face::index_type face) const;
922 
923  /// get the center point (in object space) of an element
924  void get_center(Core::Geometry::Point &, const typename Node::index_type &) const;
925  void get_center(Core::Geometry::Point &, typename Edge::index_type) const;
926  void get_center(Core::Geometry::Point &, typename Face::index_type) const;
927  void get_center(Core::Geometry::Point &, const typename Cell::index_type &) const;
928 
929  /// Get the size of an elemnt (length, area, volume)
930  double get_size(const typename Node::index_type &idx) const;
931  double get_size(typename Edge::index_type idx) const;
932  double get_size(typename Face::index_type idx) const;
933  double get_size(const typename Cell::index_type &idx) const;
934  double get_length(typename Edge::index_type idx) const
935  { return get_size(idx); };
936  double get_area(typename Face::index_type idx) const
937  { return get_size(idx); };
938  double get_volume(const typename Cell::index_type &i) const
939  { return get_size(i); };
940 
941  bool locate(typename Node::index_type &, const Core::Geometry::Point &) const;
942  bool locate(typename Edge::index_type &, const Core::Geometry::Point &) const
943  { return false; }
944  bool locate(typename Face::index_type &, const Core::Geometry::Point &) const
945  { return false; }
946  bool locate(typename Elem::index_type &, const Core::Geometry::Point &) const;
947 
948  int get_weights(const Core::Geometry::Point &p, typename Node::array_type &l, double *w);
949  int get_weights(const Core::Geometry::Point & , typename Edge::array_type & , double * )
950  { ASSERTFAIL("LatVolMesh::get_weights for edges isn't supported"); }
951  int get_weights(const Core::Geometry::Point & , typename Face::array_type & , double * )
952  { ASSERTFAIL("LatVolMesh::get_weights for faces isn't supported"); }
953  int get_weights(const Core::Geometry::Point &p, typename Cell::array_type &l, double *w);
954 
955  void get_point(Core::Geometry::Point &p, const typename Node::index_type &i) const
956  { get_center(p, i); }
957 
958  void get_normal(Core::Geometry::Vector &, const typename Node::index_type &) const
959  { ASSERTFAIL("This mesh type does not have node normals."); }
960  void get_normal(Core::Geometry::Vector &, std::vector<double> &, typename Elem::index_type,
961  unsigned int)
962  { ASSERTFAIL("This mesh type does not have element normals."); }
964  const typename Elem::index_type &,
965  FieldRNG &rng) const;
966 
967  /// This function will find the closest element and the location on that
968  /// element that is the closest
969  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
970  typename Node::index_type &elem,
971  const Core::Geometry::Point &p) const;
972 
973  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
974  typename Node::index_type &elem,
975  const Core::Geometry::Point &p, double maxdist) const;
976 
977  /// This function will find the closest element and the location on that
978  /// element that is the closest
979  template <class ARRAY>
980  bool find_closest_elem(double& pdist,
981  Core::Geometry::Point &result,
982  ARRAY& coords,
983  typename Elem::index_type &elem,
984  const Core::Geometry::Point &p,
985  double maxdist) const
986  {
987  bool ret = find_closest_elem(pdist,result,coords,elem,p);
988  if(!ret) return (false);
989  if (maxdist < 0.0 || pdist < maxdist) return (true);
990  return (false);
991  }
992 
993 
994  /// This function will find the closest element and the location on that
995  /// element that is the closest
996  template <class ARRAY>
997  bool find_closest_elem(double& pdist,
998  Core::Geometry::Point &result,
999  ARRAY& coords,
1000  typename Elem::index_type &elem,
1001  const Core::Geometry::Point &p) const
1002  {
1003  if (ni_ == 0 || nj_ == 0 || nk_ == 0) return (false);
1004 
1006 
1007  double ii = r.x();
1008  double jj = r.y();
1009  double kk = r.z();
1010  const double nii = static_cast<double>(ni_-1);
1011  const double njj = static_cast<double>(nj_-1);
1012  const double nkk = static_cast<double>(nk_-1);
1013 
1014  if (ii < 0.0) ii = 0.0; if (ii >= nii) ii = nii;
1015  if (jj < 0.0) jj = 0.0; if (jj >= njj) jj = njj;
1016  if (kk < 0.0) kk = 0.0; if (kk >= nkk) kk = nkk;
1017 
1018  double fi = floor(ii); if (fi == nii) fi--;
1019  double fj = floor(jj); if (fj == njj) fj--;
1020  double fk = floor(kk); if (fk == nkk) fk--;
1021 
1022  elem.i_ = static_cast<index_type>(fi);
1023  elem.j_ = static_cast<index_type>(fj);
1024  elem.k_ = static_cast<index_type>(fk);
1025  elem.mesh_ = this;
1026 
1027  result = transform_.project(Core::Geometry::Point(ii,jj,kk));
1028  pdist = (p-result).length();
1029 
1030  coords.resize(3);
1031  coords[0] = ii-fi;
1032  coords[1] = jj-fj;
1033  coords[2] = kk-fk;
1034 
1035  return (true);
1036  }
1037 
1038 
1039  bool find_closest_elem(double& pdist,
1040  Core::Geometry::Point& result,
1041  typename Elem::index_type &elem,
1042  const Core::Geometry::Point &p) const
1043  {
1044  StackVector<double,3> coords;
1045  return(find_closest_elem(pdist,result,coords,elem,p));
1046  }
1047 
1048  /// This function will return multiple elements if the closest point is
1049  /// located on a node or edge. All bordering elements are returned in that
1050  /// case.
1051  bool find_closest_elems(double& pdist, Core::Geometry::Point &result,
1052  std::vector<typename Elem::index_type> &elem,
1053  const Core::Geometry::Point &p) const;
1054 
1055  double get_epsilon() const;
1056 
1057  /// Export this class using the old Pio system
1058  virtual void io(Piostream&);
1059  /// These IDs are created as soon as this class will be instantiated
1060  /// The first one is for Pio and the second for the virtual interface
1061  /// These are currently different as they serve different needs. static PersistentTypeID type_idts;
1062 private:
1063  static PersistentTypeID latvol_typeid;
1064  /// Core functionality for getting the name of a templated mesh class
1065 
1066 public:
1067  static const std::string type_name(int n = -1);
1068  virtual std::string dynamic_type_name() const { return latvol_typeid.type; }
1069 
1070  // Unsafe due to non-constness of unproject.
1073  {
1074  transform_ = trans;
1076  compute_jacobian();
1077  return transform_;
1078  }
1079 
1080  virtual int dimensionality() const { return 3; }
1081  virtual int topology_geometry() const { return (STRUCTURED | REGULAR); }
1082 
1083  /// Type description, used for finding names of the mesh class for
1084  /// dynamic compilation purposes. Some of this should be obsolete
1085  virtual const TypeDescription *get_type_description() const;
1086  static const TypeDescription* cell_type_description();
1087  static const TypeDescription* face_type_description();
1088  static const TypeDescription* edge_type_description();
1089  static const TypeDescription* node_type_description();
1091  { return cell_type_description(); }
1092 
1093  /// This function returns a maker for Pio.
1094  static Persistent *maker() { return new LatVolMesh(); }
1095  /// This function returns a handle for the virtual interface.
1096  static MeshHandle mesh_maker() { return boost::make_shared<LatVolMesh>(); }
1097  /// This function returns a handle for the virtual interface.
1099  {
1100  return boost::make_shared<LatVolMesh>(x,y,z,min,max);
1101  }
1102 
1103 protected:
1104 
1105  void compute_jacobian();
1106 
1107  /// the min_Node::index_type ( incase this is a subLattice )
1109  /// the Node::index_type space extents of a LatVolMesh
1110  /// (min=min_Node::index_type, max=min+extents-1)
1112 
1114  Basis basis_;
1115 
1116  // The jacobian is the same for every element
1117  // hence store them as soon as we know the transfrom_
1118  // This should speed up FE computations on these regular grids.
1119  double jacobian_[9];
1124 
1125  boost::shared_ptr<VMesh> vmesh_;
1126 };
1127 
1128 template <class Basis>
1130 {
1131  static TypeDescription *td = 0;
1132  if (!td)
1133  {
1134  const TypeDescription *sub = get_type_description((Basis*)0);
1136  (*subs)[0] = sub;
1137  td = new TypeDescription("LatVolMesh", subs,
1138  std::string(__FILE__),
1139  "SCIRun",
1141  }
1142  return td;
1143 }
1144 
1145 
1146 template <class Basis>
1147 const TypeDescription*
1149 {
1151 }
1152 
1153 
1154 template <class Basis>
1155 const TypeDescription*
1157 {
1158  static TypeDescription *td = 0;
1159  if (!td)
1160  {
1161  const TypeDescription *me =
1163  td = new TypeDescription(me->get_name() + "::Node",
1164  std::string(__FILE__),
1165  "SCIRun",
1167  }
1168  return td;
1169 }
1170 
1171 
1172 template <class Basis>
1173 const TypeDescription*
1175 {
1176  static TypeDescription *td = 0;
1177  if (!td)
1178  {
1179  const TypeDescription *me =
1181  td = new TypeDescription(me->get_name() + "::Edge",
1182  std::string(__FILE__),
1183  "SCIRun",
1185  }
1186  return td;
1187 }
1188 
1189 
1190 template <class Basis>
1191 const TypeDescription*
1193 {
1194  static TypeDescription *td = 0;
1195  if (!td)
1196  {
1197  const TypeDescription *me =
1199  td = new TypeDescription(me->get_name() + "::Face",
1200  std::string(__FILE__),
1201  "SCIRun",
1203  }
1204  return td;
1205 }
1206 
1207 
1208 template <class Basis>
1209 const TypeDescription*
1211 {
1212  static TypeDescription *td = 0;
1213  if (!td)
1214  {
1215  const TypeDescription *me =
1217  td = new TypeDescription(me->get_name() + "::Cell",
1218  std::string(__FILE__),
1219  "SCIRun",
1221  }
1222  return td;
1223 }
1224 
1225 template <class Basis>
1228 
1229 template <class Basis>
1231  const Core::Geometry::Point &min, const Core::Geometry::Point &max)
1232  : min_i_(0), min_j_(0), min_k_(0),
1233  ni_(i), nj_(j), nk_(k)
1234 {
1235  DEBUG_CONSTRUCTOR("LatVolMesh")
1236 
1237  transform_.pre_scale(Core::Geometry::Vector(1.0 / (i-1.0), 1.0 / (j-1.0), 1.0 / (k-1.0)));
1238  transform_.pre_scale(max - min);
1241  compute_jacobian();
1242 
1243  /// Initialize the virtual interface when the mesh is created
1244  vmesh_.reset(CreateVLatVolMesh(this));
1245 }
1246 
1247 
1248 template <class Basis>
1249 void
1251  const typename Elem::index_type &ei,
1252  FieldRNG &rng) const
1253 {
1254  // build the three principal edge vectors
1255  typename Node::array_type ra;
1256  get_nodes(ra,ei);
1257  Core::Geometry::Point p0,p1,p2,p3;
1258  get_point(p0,ra[0]);
1259  get_point(p1,ra[1]);
1260  get_point(p2,ra[3]);
1261  get_point(p3,ra[4]);
1262  Core::Geometry::Vector v0(p1-p0);
1263  Core::Geometry::Vector v1(p2-p0);
1264  Core::Geometry::Vector v2(p3-p0);
1265 
1266  // Choose a random point in the cell.
1267  const double t = rng();
1268  const double u = rng();
1269  const double v = rng();
1270 
1271  p = p0+(v0*t)+(v1*u)+(v2*v);
1272 }
1273 
1274 
1275 template <class Basis>
1278 {
1279  Core::Geometry::Point p0(min_i_, min_j_, min_k_);
1280  Core::Geometry::Point p1(min_i_ + ni_-1, min_j_, min_k_);
1281  Core::Geometry::Point p2(min_i_ + ni_-1, min_j_ + nj_-1, min_k_);
1282  Core::Geometry::Point p3(min_i_, min_j_ + nj_-1, min_k_);
1283  Core::Geometry::Point p4(min_i_, min_j_, min_k_ + nk_-1);
1284  Core::Geometry::Point p5(min_i_ + ni_-1, min_j_, min_k_ + nk_-1);
1285  Core::Geometry::Point p6(min_i_ + ni_-1, min_j_ + nj_-1, min_k_ + nk_-1);
1286  Core::Geometry::Point p7(min_i_, min_j_ + nj_-1, min_k_ + nk_-1);
1287 
1288  Core::Geometry::BBox result;
1289  result.extend(transform_.project(p0))
1290  .extend(transform_.project(p1))
1291  .extend(transform_.project(p2))
1292  .extend(transform_.project(p3))
1293  .extend(transform_.project(p4))
1294  .extend(transform_.project(p5))
1295  .extend(transform_.project(p6))
1296  .extend(transform_.project(p7));
1297  return result;
1298 }
1299 
1300 
1301 template <class Basis>
1304 {
1305  return get_bounding_box().diagonal();
1306 }
1307 
1308 
1309 template <class Basis>
1310 void
1312 {
1313  transform_.pre_trans(t);
1314  transform_.compute_imat();
1315  compute_jacobian();
1316 }
1317 
1318 
1319 template <class Basis>
1320 void
1322 {
1323  t = transform_;
1324  t.post_scale(Core::Geometry::Vector(ni_ - 1.0, nj_ - 1.0, nk_ - 1.0));
1325 }
1326 
1327 
1328 template <class Basis>
1329 bool
1330 LatVolMesh<Basis>::get_min(std::vector<index_type> &array) const
1331 {
1332  array.resize(3);
1333  array.clear();
1334 
1335  array.push_back(min_i_);
1336  array.push_back(min_j_);
1337  array.push_back(min_k_);
1338 
1339  return true;
1340 }
1341 
1342 
1343 template <class Basis>
1344 bool
1345 LatVolMesh<Basis>::get_dim(std::vector<index_type> &array) const
1346 {
1347  array.resize(3);
1348  array.clear();
1349 
1350  array.push_back(ni_);
1351  array.push_back(nj_);
1352  array.push_back(nk_);
1353 
1354  return true;
1355 }
1356 
1357 
1358 template <class Basis>
1359 void
1360 LatVolMesh<Basis>::set_min(std::vector<index_type> min)
1361 {
1362  min_i_ = min[0];
1363  min_j_ = min[1];
1364  min_k_ = min[2];
1365 }
1366 
1367 
1368 template <class Basis>
1369 void
1370 LatVolMesh<Basis>::set_dim(std::vector<index_type> dim)
1371 {
1372  ni_ = dim[0];
1373  nj_ = dim[1];
1374  nk_ = dim[2];
1375 
1376  /// Create a new virtual interface for this copy
1377  /// all pointers have changed hence create a new
1378  /// virtual interface class
1379  vmesh_.reset(CreateVLatVolMesh(this));
1380 }
1381 
1382 
1383 // Note: This code does not respect boundaries of the mesh
1384 template <class Basis>
1385 void
1387  typename Edge::index_type idx) const
1388 {
1389  array.resize(2);
1390  // The (const unsigned int) on the next line is due
1391  // to a bug in the OSX 10.4 compiler that gives xidx
1392  // the wrong type
1393  const size_type xidx = (const size_type)idx;
1394  if (xidx < (ni_ - 1) * nj_ * nk_)
1395  {
1396  const index_type i = xidx % (ni_ - 1);
1397  const index_type jk = xidx / (ni_ - 1);
1398  const index_type j = jk % nj_;
1399  const index_type k = jk / nj_;
1400 
1401  array[0] = typename Node::index_type(this, i+0, j, k);
1402  array[1] = typename Node::index_type(this, i+1, j, k);
1403  }
1404  else
1405  {
1406  const index_type yidx = idx - (ni_ - 1) * nj_ * nk_;
1407  if (yidx < (ni_ * (nj_ - 1) * nk_))
1408  {
1409  const index_type j = yidx % (nj_ - 1);
1410  const index_type ik = yidx / (nj_ - 1);
1411  const index_type i = ik / nk_;
1412  const index_type k = ik % nk_;
1413 
1414  array[0] = typename Node::index_type(this, i, j+0, k);
1415  array[1] = typename Node::index_type(this, i, j+1, k);
1416  }
1417  else
1418  {
1419  const index_type zidx = yidx - (ni_ * (nj_ - 1) * nk_);
1420  const index_type k = zidx % (nk_ - 1);
1421  const index_type ij = zidx / (nk_ - 1);
1422  const index_type i = ij % ni_;
1423  const index_type j = ij / ni_;
1424 
1425  array[0] = typename Node::index_type(this, i, j, k+0);
1426  array[1] = typename Node::index_type(this, i, j, k+1);
1427  }
1428  }
1429 }
1430 
1431 
1432 // Note: This code does not respect boundaries of the mesh
1433 template <class Basis>
1434 void
1436  typename Face::index_type idx) const
1437 {
1438  array.resize(4);
1439  // The (const unsigned int) on the next line is due
1440  // to a bug in the OSX 10.4 compiler that gives xidx
1441  // the wrong type
1442  const index_type xidx = (const index_type)idx;
1443  if (xidx < (ni_ - 1) * (nj_ - 1) * nk_)
1444  {
1445  const index_type i = xidx % (ni_ - 1);
1446  const index_type jk = xidx / (ni_ - 1);
1447  const index_type j = jk % (nj_ - 1);
1448  const index_type k = jk / (nj_ - 1);
1449  array[0] = typename Node::index_type(this, i+0, j+0, k);
1450  array[1] = typename Node::index_type(this, i+1, j+0, k);
1451  array[2] = typename Node::index_type(this, i+1, j+1, k);
1452  array[3] = typename Node::index_type(this, i+0, j+1, k);
1453  }
1454  else
1455  {
1456  const index_type yidx = idx - (ni_ - 1) * (nj_ - 1) * nk_;
1457  if (yidx < ni_ * (nj_ - 1) * (nk_ - 1))
1458  {
1459  const index_type j = yidx % (nj_ - 1);
1460  const index_type ik = yidx / (nj_ - 1);
1461  const index_type k = ik % (nk_ - 1);
1462  const index_type i = ik / (nk_ - 1);
1463  array[0] = typename Node::index_type(this, i, j+0, k+0);
1464  array[1] = typename Node::index_type(this, i, j+1, k+0);
1465  array[2] = typename Node::index_type(this, i, j+1, k+1);
1466  array[3] = typename Node::index_type(this, i, j+0, k+1);
1467  }
1468  else
1469  {
1470  const index_type zidx = yidx - ni_ * (nj_ - 1) * (nk_ - 1);
1471  const index_type k = zidx % (nk_ - 1);
1472  const index_type ij = zidx / (nk_ - 1);
1473  const index_type i = ij % (ni_ - 1);
1474  const index_type j = ij / (ni_ - 1);
1475  array[0] = typename Node::index_type(this, i+0, j, k+0);
1476  array[1] = typename Node::index_type(this, i+0, j, k+1);
1477  array[2] = typename Node::index_type(this, i+1, j, k+1);
1478  array[3] = typename Node::index_type(this, i+1, j, k+0);
1479  }
1480  }
1481 }
1482 
1483 
1484 // Note: This code does not respect boundaries of the mesh.
1485 template <class Basis>
1486 void
1488  const typename Cell::index_type &idx) const
1489 {
1490  array.resize(8);
1491  array[0].i_ = idx.i_; array[0].j_ = idx.j_; array[0].k_ = idx.k_;
1492  array[1].i_ = idx.i_+1; array[1].j_ = idx.j_; array[1].k_ = idx.k_;
1493  array[2].i_ = idx.i_+1; array[2].j_ = idx.j_+1; array[2].k_ = idx.k_;
1494  array[3].i_ = idx.i_; array[3].j_ = idx.j_+1; array[3].k_ = idx.k_;
1495  array[4].i_ = idx.i_; array[4].j_ = idx.j_; array[4].k_ = idx.k_+1;
1496  array[5].i_ = idx.i_+1; array[5].j_ = idx.j_; array[5].k_ = idx.k_+1;
1497  array[6].i_ = idx.i_+1; array[6].j_ = idx.j_+1; array[6].k_ = idx.k_+1;
1498  array[7].i_ = idx.i_; array[7].j_ = idx.j_+1; array[7].k_ = idx.k_+1;
1499 
1500  array[0].mesh_ = this;
1501  array[1].mesh_ = this;
1502  array[2].mesh_ = this;
1503  array[3].mesh_ = this;
1504  array[4].mesh_ = this;
1505  array[5].mesh_ = this;
1506  array[6].mesh_ = this;
1507  array[7].mesh_ = this;
1508 }
1509 
1510 
1511 template <class Basis>
1512 void
1514  typename Face::index_type idx) const
1515 {
1516  array.resize(4);
1517  const index_type num_i_faces = (ni_-1)*(nj_-1)*nk_; // lie in ij plane ijk
1518  const index_type num_j_faces = ni_*(nj_-1)*(nk_-1); // lie in jk plane jki
1519  const index_type num_k_faces = (ni_-1)*nj_*(nk_-1); // lie in ki plane kij
1520 
1521  const index_type num_i_edges = (ni_-1)*nj_*nk_; // ijk
1522  const index_type num_j_edges = ni_*(nj_-1)*nk_; // jki
1523 
1524  index_type facei, facej, facek;
1525  index_type face = idx;
1526 
1527  if (face < num_i_faces)
1528  {
1529  facei = face % (ni_-1);
1530  facej = (face / (ni_-1)) % (nj_-1);
1531  facek = face / ((ni_-1)*(nj_-1));
1532  array[0] = facei+facej*(ni_-1)+facek*(ni_-1)*(nj_);
1533  array[1] = facei+(facej+1)*(ni_-1)+facek*(ni_-1)*(nj_);
1534  array[2] = num_i_edges + facei*(nj_-1)*(nk_)+facej+facek*(nj_-1);
1535  array[3] = num_i_edges + (facei+1)*(nj_-1)*(nk_)+facej+facek*(nj_-1);
1536  }
1537  else if (face - num_i_faces < num_j_faces)
1538  {
1539  face -= num_i_faces;
1540  facei = face / ((nj_-1) *(nk_-1));
1541  facej = face % (nj_-1);
1542  facek = (face / (nj_-1)) % (nk_-1);
1543  array[0] = num_i_edges + facei*(nj_-1)*(nk_)+facej+facek*(nj_-1);
1544  array[1] = num_i_edges + facei*(nj_-1)*(nk_)+facej+(facek+1)*(nj_-1);
1545  array[2] = (num_i_edges + num_j_edges +
1546  facei*(nk_-1)+facej*(ni_)*(nk_-1)+facek);
1547  array[3] = (num_i_edges + num_j_edges +
1548  facei*(nk_-1)+(facej+1)*(ni_)*(nk_-1)+facek);
1549 
1550  }
1551  else if (face - num_i_faces - num_j_faces < num_k_faces)
1552  {
1553  face -= (num_i_faces + num_j_faces);
1554  facei = (face / (nk_-1)) % (ni_-1);
1555  facej = face / ((ni_-1) * (nk_-1));
1556  facek = face % (nk_-1);
1557  array[0] = facei+facej*(ni_-1)+facek*(ni_-1)*(nj_);
1558  array[1] = facei+facej*(ni_-1)+(facek+1)*(ni_-1)*(nj_);
1559  array[2] = (num_i_edges + num_j_edges +
1560  facei*(nk_-1)+facej*(ni_)*(nk_-1)+facek);
1561  array[3] = (num_i_edges + num_j_edges +
1562  (facei+1)*(nk_-1)+facej*(ni_)*(nk_-1)+facek);
1563  }
1564  else {
1565  ASSERTFAIL(
1566  "LatVolMesh<Basis>::get_edges(Edge, Face) Face idx out of bounds");
1567  }
1568 }
1569 
1570 
1571 template <class Basis>
1572 void
1574  const typename Cell::index_type &idx) const
1575 {
1576  array.resize(12);
1577  const index_type j_start= (ni_-1)*nj_*nk_;
1578  const index_type k_start = ni_*(nj_-1)*nk_ + j_start;
1579 
1580  array[0] = idx.i_ + idx.j_*(ni_-1) + idx.k_*(ni_-1)*(nj_);
1581  array[1] = idx.i_ + (idx.j_+1)*(ni_-1) + idx.k_*(ni_-1)*(nj_);
1582  array[2] = idx.i_ + idx.j_*(ni_-1) + (idx.k_+1)*(ni_-1)*(nj_);
1583  array[3] = idx.i_ + (idx.j_+1)*(ni_-1) + (idx.k_+1)*(ni_-1)*(nj_);
1584 
1585  array[4] = j_start + idx.i_*(nj_-1)*(nk_) + idx.j_ + idx.k_*(nj_-1);
1586  array[5] = j_start + (idx.i_+1)*(nj_-1)*(nk_) + idx.j_ + idx.k_*(nj_-1);
1587  array[6] = j_start + idx.i_*(nj_-1)*(nk_) + idx.j_ + (idx.k_+1)*(nj_-1);
1588  array[7] = j_start + (idx.i_+1)*(nj_-1)*(nk_) + idx.j_ + (idx.k_+1)*(nj_-1);
1589 
1590  array[8] = k_start + idx.i_*(nk_-1) + idx.j_*(ni_)*(nk_-1) + idx.k_;
1591  array[9] = k_start + (idx.i_+1)*(nk_-1) + idx.j_*(ni_)*(nk_-1) + idx.k_;
1592  array[10] = k_start + idx.i_*(nk_-1) + (idx.j_+1)*(ni_)*(nk_-1) + idx.k_;
1593  array[11] = k_start + (idx.i_+1)*(nk_-1) + (idx.j_+1)*(ni_)*(nk_-1) + idx.k_;
1594 
1595 }
1596 
1597 
1598 template <class Basis>
1599 void
1601  const typename Edge::index_type &eidx) const
1602 {
1603  result.reserve(4);
1604  result.clear();
1605  const index_type offset1 = (ni_-1)*nj_*nk_;
1606  const index_type offset2 = offset1 + ni_*(nj_-1)*nk_;
1607  index_type idx = eidx;
1608 
1609  if (idx < offset1)
1610  {
1611  index_type k = idx/((nj_)*(ni_-1)); idx -= k*(nj_)*(ni_-1);
1612  index_type j = idx/(ni_-1); idx -= j*(ni_-1);
1613  index_type i = idx;
1614 
1615  if (j > 0)
1616  {
1617  if (k < (nk_-1)) result.push_back(CellIndex(this,i,j-1,k));
1618  if (k > 0) result.push_back(CellIndex(this,i,j-1,k-1));
1619  }
1620 
1621  if (j < (nj_-1))
1622  {
1623  if (k < (nk_-1)) result.push_back(CellIndex(this,i,j,k));
1624  if (k > 0) result.push_back(CellIndex(this,i,j,k-1));
1625  }
1626  }
1627  else if (idx >= offset2)
1628  {
1629  idx -= offset2;
1630  index_type j = idx/((nk_-1)*(ni_)); idx -= j*(nk_-1)*(ni_);
1631  index_type i = idx/(nk_-1); idx -= i*(nk_-1);
1632  index_type k = idx;
1633 
1634  if (i > 0)
1635  {
1636  if (j < (nj_-1)) result.push_back(CellIndex(this,i-1,j,k));
1637  if (j > 0) result.push_back(CellIndex(this,i-1,j-1,k));
1638  }
1639 
1640  if (i < (ni_-1))
1641  {
1642  if (j < (nj_-1)) result.push_back(CellIndex(this,i,j,k));
1643  if (j > 0) result.push_back(CellIndex(this,i,j-1,k));
1644  }
1645  }
1646  else
1647  {
1648  idx -= offset1;
1649  index_type i = idx/((nk_)*(nj_-1)); idx -= i*(nk_)*(nj_-1);
1650  index_type k = idx/(nj_-1); idx -= k*(nj_-1);
1651  index_type j = idx;
1652 
1653  if (k > 0)
1654  {
1655  if (i < (nk_-1)) result.push_back(CellIndex(this,i,j,k-1));
1656  if (i > 0) result.push_back(CellIndex(this,i-1,j,k-1));
1657  }
1658 
1659  if (k < (nk_-1))
1660  {
1661  if (i < (ni_-1)) result.push_back(CellIndex(this,i,j,k));
1662  if (i > 0) result.push_back(CellIndex(this,i-1,j,k));
1663  }
1664  }
1665 }
1666 
1667 
1668 template <class Basis>
1669 void
1671  const typename Cell::index_type &idx) const
1672 {
1673  array.resize(6);
1674 
1675  const index_type i = idx.i_;
1676  const index_type j = idx.j_;
1677  const index_type k = idx.k_;
1678 
1679  const index_type offset1 = (ni_ - 1) * (nj_ - 1) * nk_;
1680  const index_type offset2 = offset1 + ni_ * (nj_ - 1) * (nk_ - 1);
1681 
1682  array[0] = i + (j + k * (nj_-1)) * (ni_-1);
1683  array[1] = i + (j + (k+1) * (nj_-1)) * (ni_-1);
1684 
1685  array[2] = offset1 + j + (k + i * (nk_-1)) * (nj_-1);
1686  array[3] = offset1 + j + (k + (i+1) * (nk_-1)) * (nj_-1);
1687 
1688  array[4] = offset2 + k + (i + j * (ni_-1)) * (nk_-1);
1689  array[5] = offset2 + k + (i + (j+1) * (ni_-1)) * (nk_-1);
1690 }
1691 
1692 
1693 template <class Basis>
1694 void
1696  const typename Face::index_type &fidx) const
1697 {
1698  result.reserve(2);
1699  result.clear();
1700  const index_type offset1 = (ni_ - 1) * (nj_ - 1) * nk_;
1701  const index_type offset2 = offset1 + ni_ * (nj_ - 1) * (nk_ - 1);
1702  index_type idx = fidx;
1703 
1704  if (idx < offset1)
1705  {
1706  index_type k = idx/((nj_-1)*(ni_-1)); idx -= k*(nj_-1)*(ni_-1);
1707  index_type j = idx/(ni_-1); idx -= j*(ni_-1);
1708  index_type i = idx;
1709 
1710  if (k < (nk_-1)) result.push_back(CellIndex(this,i,j,k));
1711  if (k > 0) result.push_back(CellIndex(this,i,j,k-1));
1712  }
1713  else if (idx >= offset2)
1714  {
1715  idx -= offset2;
1716  index_type j = idx/((nk_-1)*(ni_-1)); idx -= j*(nk_-1)*(ni_-1);
1717  index_type i = idx/(nk_-1); idx -= i*(nk_-1);
1718  index_type k = idx;
1719 
1720  if (j < (nj_-1)) result.push_back(CellIndex(this,i,j,k));
1721  if (j > 0) result.push_back(CellIndex(this,i,j-1,k));
1722  }
1723  else
1724  {
1725  idx -= offset1;
1726  index_type i = idx/((nk_-1)*(nj_-1)); idx -= i*(nk_-1)*(nj_-1);
1727  index_type k = idx/(nj_-1); idx -= k*(nj_-1);
1728  index_type j = idx;
1729 
1730  if (i < (ni_-1)) result.push_back(CellIndex(this,i,j,k));
1731  if (i > 0) result.push_back(CellIndex(this,i-1,j,k));
1732  }
1733 }
1734 
1735 template <class Basis>
1736 void
1738  const typename Node::index_type &idx) const
1739 {
1740  result.reserve(8);
1741  result.clear();
1742  const index_type i0 = idx.i_ ? idx.i_ - 1 : 0;
1743  const index_type j0 = idx.j_ ? idx.j_ - 1 : 0;
1744  const index_type k0 = idx.k_ ? idx.k_ - 1 : 0;
1745 
1746  const index_type i1 = idx.i_ < ni_-1 ? idx.i_+1 : ni_-1;
1747  const index_type j1 = idx.j_ < nj_-1 ? idx.j_+1 : nj_-1;
1748  const index_type k1 = idx.k_ < nk_-1 ? idx.k_+1 : nk_-1;
1749 
1750  index_type i, j, k;
1751  for (k = k0; k < k1; k++)
1752  for (j = j0; j < j1; j++)
1753  for (i = i0; i < i1; i++)
1754  result.push_back(typename Cell::index_type(this, i, j, k));
1755 }
1756 
1757 
1758 /// return all cell_indecies that overlap the BBox in arr.
1759 
1760 template <class Basis>
1761 void
1763 {
1764  // Get our min and max
1765  typename Cell::index_type min, max;
1766  get_cells(min, max, bbox);
1767 
1768  // Clear the input array. Limited to range of ints.
1769  arr.clear();
1770 
1771  // Loop over over min to max and fill the array
1772  index_type i, j, k;
1773  for (i = min.i_; i <= max.i_; i++) {
1774  for (j = min.j_; j <= max.j_; j++) {
1775  for (k = min.k_; k <= max.k_; k++) {
1776  arr.push_back(typename Cell::index_type(this, i,j,k));
1777  }
1778  }
1779  }
1780 }
1781 
1782 
1783 /// Returns the min and max indices that fall within or on the BBox.
1784 
1785 // If the max index lies "in front of" (meaning that any of the
1786 // indexes are negative) then the max will be set to [0,0,0] and the
1787 // min to [1,1,1] in the hopes that they will be used something like
1788 // this: for(unsigned int i = min.i_; i <= max.i_; i++).... Otherwise
1789 // you can expect the min and max to be set clamped to the boundaries.
1790 template <class Basis>
1791 void
1793  const Core::Geometry::BBox &bbox) {
1794 
1795  const Core::Geometry::Point minp = transform_.unproject(bbox.min());
1796  index_type mini = (index_type)floor(minp.x());
1797  index_type minj = (index_type)floor(minp.y());
1798  index_type mink = (index_type)floor(minp.z());
1799  if (mini < 0) { mini = 0; }
1800  if (minj < 0) { minj = 0; }
1801  if (mink < 0) { mink = 0; }
1802 
1803  const Core::Geometry::Point maxp = transform_.unproject(bbox.max());
1804  index_type maxi = (index_type)floor(maxp.x());
1805  index_type maxj = (index_type)floor(maxp.y());
1806  index_type maxk = (index_type)floor(maxp.z());
1807  if (maxi >= (index_type)(ni_ - 1)) { maxi = ni_ - 2; }
1808  if (maxj >= (index_type)(nj_ - 1)) { maxj = nj_ - 2; }
1809  if (maxk >= (index_type)(nk_ - 1)) { maxk = nk_ - 2; }
1810  // We also need to protect against when any of these guys are
1811  // negative. In this case we should not have any iteration. We
1812  // can't however express negative numbers with unsigned ints (in the
1813  // case of index_type).
1814  if (maxi < 0 || maxj < 0 || maxk < 0) {
1815  // We should create a range which will not be iterated over
1816  mini = minj = mink = 1;
1817  maxi = maxj = maxk = 0;
1818  }
1819 
1820  begin = typename Cell::index_type(this, mini, minj, mink);
1821  end = typename Cell::index_type(this, maxi, maxj, maxk);
1822 }
1823 
1824 
1825 template <class Basis>
1826 bool
1828  const typename Cell::index_type &from,
1829  typename Face::index_type face) const
1830 {
1831  // The (const unsigned int) on the next line is due
1832  // to a bug in the OSX 10.4 compiler that gives xidx
1833  // the wrong type
1834  const index_type xidx = (const index_type)face;
1835  if (xidx < (ni_ - 1) * (nj_ - 1) * nk_)
1836  {
1837  const index_type jk = xidx / (ni_ - 1);
1838  const index_type k = jk / (nj_ - 1);
1839 
1840  if (k == from.k_ && k > 0)
1841  {
1842  neighbor.i_ = from.i_;
1843  neighbor.j_ = from.j_;
1844  neighbor.k_ = k-1;
1845  neighbor.mesh_ = this;
1846  return true;
1847  }
1848  else if (k == (from.k_+1) && k < (nk_-1))
1849  {
1850  neighbor.i_ = from.i_;
1851  neighbor.j_ = from.j_;
1852  neighbor.k_ = k;
1853  neighbor.mesh_ = this;
1854  return true;
1855  }
1856  }
1857  else
1858  {
1859  const index_type yidx = xidx - (ni_ - 1) * (nj_ - 1) * nk_;
1860  if (yidx < ni_ * (nj_ - 1) * (nk_ - 1))
1861  {
1862  const index_type ik = yidx / (nj_ - 1);
1863  const index_type i = ik / (nk_ - 1);
1864 
1865  if (i == from.i_ && i > 0)
1866  {
1867  neighbor.i_ = i-1;
1868  neighbor.j_ = from.j_;
1869  neighbor.k_ = from.k_;
1870  neighbor.mesh_ = this;
1871  return true;
1872  }
1873  else if (i == (from.i_+1) && i < (ni_-1))
1874  {
1875  neighbor.i_ = i;
1876  neighbor.j_ = from.j_;
1877  neighbor.k_ = from.k_;
1878  neighbor.mesh_ = this;
1879  return true;
1880  }
1881  }
1882  else
1883  {
1884  const index_type zidx = yidx - ni_ * (nj_ - 1) * (nk_ - 1);
1885  const index_type ij = zidx / (nk_ - 1);
1886  const index_type j = ij / (ni_ - 1);
1887 
1888  if (j == from.j_ && j > 0)
1889  {
1890  neighbor.i_ = from.i_;
1891  neighbor.j_ = j-1;
1892  neighbor.k_ = from.k_;
1893  neighbor.mesh_ = this;
1894  return true;
1895  }
1896  else if (j == (from.j_+1) && j < (nj_-1))
1897  {
1898  neighbor.i_ = from.i_;
1899  neighbor.j_ = j;
1900  neighbor.k_ = from.k_;
1901  neighbor.mesh_ = this;
1902  return true;
1903  }
1904  }
1905  }
1906  return false;
1907 }
1908 
1909 
1910 template <class Basis>
1911 void
1913  typename Node::index_type &end,
1914  const Core::Geometry::BBox &bbox)
1915 {
1916  // get the min and max points of the bbox and make sure that they lie
1917  // inside the mesh boundaries.
1918  Core::Geometry::BBox mesh_boundary = get_bounding_box();
1919  // crop by min boundary
1920  Core::Geometry::Point min = Max(bbox.min(), mesh_boundary.min());
1921  Core::Geometry::Point max = Max(bbox.max(), mesh_boundary.min());
1922  // crop by max boundary
1923  min = Min(min, mesh_boundary.max());
1924  max = Min(max, mesh_boundary.max());
1925  typename Node::index_type min_index, max_index;
1926 
1927  // If one of the locates return true, then we have a valid iteration
1928  bool min_located = locate(min_index, min);
1929  bool max_located = locate(max_index, max);
1930  if (!min_located && !max_located)
1931  {
1932  // first check to see if there is a bbox overlap
1934  box.extend(min);
1935  box.extend(max);
1936  if ( box.overlaps(mesh_boundary) )
1937  {
1938  Core::Geometry::Point r = transform_.unproject(min);
1939  double rx = floor(r.x());
1940  double ry = floor(r.y());
1941  double rz = floor(r.z());
1942  min_index.i_ = (index_type)std::max(rx, 0.0);
1943  min_index.j_ = (index_type)std::max(ry, 0.0);
1944  min_index.k_ = (index_type)std::max(rz, 0.0);
1945  r = transform_.unproject(max);
1946  rx = floor(r.x());
1947  ry = floor(r.y());
1948  rz = floor(r.z());
1949  max_index.i_ = (index_type)std::min(rx, (double)ni_ );
1950  max_index.j_ = (index_type)std::min(ry, (double)nj_ );
1951  max_index.k_ = (index_type)std::min(rz, (double)nk_ );
1952  }
1953  else
1954  {
1955  // Set the min and max extents of the range iterator to be the
1956  // same thing. When they are the same end_iter will be set to
1957  // the starting state of the range iterator, thereby causing any
1958  // for loop using these iterators [for(;iter != end_iter;
1959  // iter++)] to never enter.
1960  min_index = typename Node::index_type(this, 0,0,0);
1961  max_index = typename Node::index_type(this, 0,0,0);
1962  }
1963  }
1964  else if ( !min_located )
1965  {
1966  const Core::Geometry::Point r = transform_.unproject(min);
1967  const double rx = floor(r.x());
1968  const double ry = floor(r.y());
1969  const double rz = floor(r.z());
1970  min_index.i_ = (index_type)std::max(rx, 0.0);
1971  min_index.j_ = (index_type)std::max(ry, 0.0);
1972  min_index.k_ = (index_type)std::max(rz, 0.0);
1973  }
1974  else
1975  { // !max_located
1976  const Core::Geometry::Point r = transform_.unproject(max);
1977  const double rx = floor(r.x());
1978  const double ry = floor(r.y());
1979  const double rz = floor(r.z());
1980  max_index.i_ = (index_type)std::min(rx, (double) ni_ );
1981  max_index.j_ = (index_type)std::min(ry, (double) nj_ );
1982  max_index.k_ = (index_type)std::min(rz, (double) nk_ );
1983  }
1984 
1985  begin = min_index;
1986  end = max_index;
1987 }
1988 
1989 
1990 template <class Basis>
1991 void
1993  typename Edge::index_type idx) const
1994 {
1995  typename Node::array_type arr;
1996  get_nodes(arr, idx);
1998  get_center(result, arr[0]);
1999  get_center(p1, arr[1]);
2000 
2001  result += p1;
2002  result *= 0.5;
2003 }
2004 
2005 
2006 template <class Basis>
2007 void
2009  typename Face::index_type idx) const
2010 {
2011  typename Node::array_type nodes;
2012  get_nodes(nodes, idx);
2013  ASSERT(nodes.size() == 4);
2014  typename Node::array_type::iterator nai = nodes.begin();
2015  get_point(result, *nai);
2016  ++nai;
2018  while (nai != nodes.end())
2019  {
2020  get_point(pp, *nai);
2021  result += pp;
2022  ++nai;
2023  }
2024  result *= (1.0 / 4.0);
2025 }
2026 
2027 
2028 template <class Basis>
2029 void
2031  const typename Cell::index_type &idx) const
2032 {
2033  Core::Geometry::Point p(idx.i_ + 0.5, idx.j_ + 0.5, idx.k_ + 0.5);
2034  result = transform_.project(p);
2035 }
2036 
2037 
2038 template <class Basis>
2039 void
2041  const typename Node::index_type &idx) const
2042 {
2043  Core::Geometry::Point p(idx.i_, idx.j_, idx.k_);
2044  result = transform_.project(p);
2045 }
2046 
2047 
2048 template <class Basis>
2049 double
2050 LatVolMesh<Basis>::get_size(const typename Node::index_type& /*idx*/) const
2051 {
2052  return 0.0;
2053 }
2054 
2055 
2056 template <class Basis>
2057 double
2059 {
2060  typename Node::array_type arr;
2061  get_nodes(arr, idx);
2062  Core::Geometry::Point p0, p1;
2063  get_center(p0, arr[0]);
2064  get_center(p1, arr[1]);
2065 
2066  return (p1 - p0).length();
2067 }
2068 
2069 
2070 template <class Basis>
2071 double
2073 {
2074  typename Node::array_type nodes;
2075  get_nodes(nodes, idx);
2076 
2077  Core::Geometry::Point p0, p1, p2;
2078  get_point(p0, nodes[0]);
2079  get_point(p1, nodes[1]);
2080  get_point(p2, nodes[2]);
2081  Core::Geometry::Vector v0 = p1 - p0;
2082  Core::Geometry::Vector v1 = p2 - p0;
2083 
2084  Core::Geometry::Vector v = Cross(v0,v1);
2085  return (v.length());
2086 }
2087 
2088 
2089 template <class Basis>
2090 double
2091 LatVolMesh<Basis>::get_size(const typename Cell::index_type& /*idx*/) const
2092 {
2093  // Correct implementation, the old one did not take into account skewing
2094  // the latvol!!!
2095 
2096  // As they are all the same we precompute these
2097  return (det_jacobian_);
2098 }
2099 
2100 
2101 template <class Basis>
2102 bool
2104 {
2105  const double epsilon = 1e-7;
2106 
2107  if (ni_ == 0 || nj_ == 0 || nk_ == 0) return (false);
2108 
2109  const Core::Geometry::Point r = transform_.unproject(p);
2110 
2111  double ii = r.x();
2112  double jj = r.y();
2113  double kk = r.z();
2114 
2115  const double nii = static_cast<double>(ni_-1);
2116  const double njj = static_cast<double>(nj_-1);
2117  const double nkk = static_cast<double>(nk_-1);
2118 
2119  if (ii>=nii && (ii-epsilon)<nii) ii=nii-epsilon;
2120  if (jj>=njj && (jj-epsilon)<njj) jj=njj-epsilon;
2121  if (kk>=nkk && (kk-epsilon)<nkk) kk=nkk-epsilon;
2122 
2123  if (ii<0 && ii>(-epsilon)) ii=0.0;
2124  if (jj<0 && jj>(-epsilon)) jj=0.0;
2125  if (kk<0 && kk>(-epsilon)) kk=0.0;
2126 
2127  const index_type i = static_cast<index_type>(floor(ii));
2128  const index_type j = static_cast<index_type>(floor(jj));
2129  const index_type k = static_cast<index_type>(floor(kk));
2130 
2131  if (i < (ni_-1) && i >= 0 &&
2132  j < (nj_-1) && j >= 0 &&
2133  k < (nk_-1) && k >= 0 &&
2134  ii >= 0.0 && jj >= 0.0 && kk >= 0.0)
2135  {
2136  elem.i_ = i;
2137  elem.j_ = j;
2138  elem.k_ = k;
2139  elem.mesh_ = this;
2140  return (true);
2141  }
2142 
2143  return (false);
2144 }
2145 
2146 
2147 template <class Basis>
2148 bool
2150 {
2151  if (ni_ == 0 || nj_ == 0 || nk_ == 0) return (false);
2152 
2153  const Core::Geometry::Point r = transform_.unproject(p);
2154 
2155  double rx = floor(r.x() + 0.5);
2156  double ry = floor(r.y() + 0.5);
2157  double rz = floor(r.z() + 0.5);
2158 
2159  const double nii = static_cast<double>(ni_-1);
2160  const double njj = static_cast<double>(nj_-1);
2161  const double nkk = static_cast<double>(nk_-1);
2162 
2163  if (rx < 0.0) rx = 0.0; if (rx > nii) rx = nii;
2164  if (ry < 0.0) ry = 0.0; if (ry > njj) ry = njj;
2165  if (rz < 0.0) rz = 0.0; if (rz > nkk) rz = nkk;
2166 
2167  node.i_ = static_cast<index_type>(rx);
2168  node.j_ = static_cast<index_type>(ry);
2169  node.k_ = static_cast<index_type>(rz);
2170  node.mesh_ = this;
2171 
2172  return (true);
2173 }
2174 
2175 
2176 
2177 template <class Basis>
2178 bool
2180  Core::Geometry::Point &result,
2181  typename Node::index_type &node,
2182  const Core::Geometry::Point &p) const
2183 {
2184  if (ni_ == 0 || nj_ == 0 || nk_ == 0) return (false);
2185 
2186  const Core::Geometry::Point r = transform_.unproject(p);
2187 
2188  double rx = floor(r.x() + 0.5);
2189  double ry = floor(r.y() + 0.5);
2190  double rz = floor(r.z() + 0.5);
2191 
2192  const double nii = static_cast<double>(ni_-1);
2193  const double njj = static_cast<double>(nj_-1);
2194  const double nkk = static_cast<double>(nk_-1);
2195 
2196  if (rx < 0.0) rx = 0.0; if (rx > nii) rx = nii;
2197  if (ry < 0.0) ry = 0.0; if (ry > njj) ry = njj;
2198  if (rz < 0.0) rz = 0.0; if (rz > nkk) rz = nkk;
2199 
2200  result = transform_.project(Core::Geometry::Point(rx,ry,rz));
2201  node.i_ = static_cast<index_type>(rx);
2202  node.j_ = static_cast<index_type>(ry);
2203  node.k_ = static_cast<index_type>(rz);
2204  node.mesh_ = this;
2205 
2206  pdist = (p-result).length();
2207  return (true);
2208 }
2209 
2210 
2211 
2212 template <class Basis>
2213 bool
2215  Core::Geometry::Point &result,
2216  typename Node::index_type &node,
2217  const Core::Geometry::Point &p, double maxdist) const
2218 {
2219  bool ret = find_closest_node(pdist,result,node,p);
2220  if (!ret) return (false);
2221  if (maxdist < 0.0 || pdist < maxdist) return (true);
2222  return (false);
2223 }
2224 
2225 template <class Basis>
2226 bool
2228  Core::Geometry::Point &result,
2229  std::vector<typename Elem::index_type> &elems,
2230  const Core::Geometry::Point &p) const
2231 {
2232  // For calculations inside the local element
2233  const double epsilon = 1e-8;
2234  elems.clear();
2235 
2236  if (ni_ == 0 || nj_ == 0 || nk_ == 0) return (false);
2237 
2238  const Core::Geometry::Point r = transform_.unproject(p);
2239 
2240  double ii = r.x();
2241  double jj = r.y();
2242  double kk = r.z();
2243  const double nii = static_cast<double>(ni_-2);
2244  const double njj = static_cast<double>(nj_-2);
2245  //const double nkk = static_cast<double>(nk_-2);
2246 
2247  if (ii < 0.0) ii = 0.0; if (ii > nii) ii = nii;
2248  if (jj < 0.0) jj = 0.0; if (jj > njj) jj = njj;
2249  if (jj < 0.0) jj = 0.0; if (jj > njj) jj = njj;
2250  const double fii = floor(ii);
2251  const double fjj = floor(jj);
2252  const double fkk = floor(kk);
2253 
2254  index_type i = static_cast<index_type>(fii);
2255  index_type j = static_cast<index_type>(fjj);
2256  index_type k = static_cast<index_type>(fkk);
2257 
2258  typename Elem::index_type elem;
2259 
2260  elem.i_ = i;
2261  elem.j_ = j;
2262  elem.k_ = k;
2263  elem.mesh_ = this;
2264  elems.push_back(elem);
2265 
2266  if ((fabs(fii-ii) < epsilon) && ((i-1)>0))
2267  {
2268  elem.i_ = i-1;
2269  elem.j_ = j;
2270  elem.k_ = k;
2271  elems.push_back(elem);
2272  }
2273 
2274  if ((fabs(fii-(ii+1.0)) < epsilon) && (i<(ni_-1)))
2275  {
2276  elem.i_ = i+1;
2277  elem.j_ = j;
2278  elem.k_ = k;
2279  elems.push_back(elem);
2280  }
2281 
2282  if ((fabs(fjj-jj) < epsilon) && ((j-1)>0))
2283  {
2284  elem.i_ = i;
2285  elem.j_ = j-1;
2286  elem.k_ = k;
2287  elems.push_back(elem);
2288  }
2289 
2290  if ((fabs(fjj-(jj+1.0)) < epsilon) && (j<(nj_-1)))
2291  {
2292  elem.i_ = i;
2293  elem.j_ = j+1;
2294  elem.k_ = k;
2295  elems.push_back(elem);
2296  }
2297 
2298  if ((fabs(fkk-kk) < epsilon) && ((k-1)>0))
2299  {
2300  elem.i_ = i;
2301  elem.j_ = j;
2302  elem.k_ = k-1;
2303  elems.push_back(elem);
2304  }
2305 
2306  if ((fabs(fkk-(kk+1.0)) < epsilon) && (k<(nk_-1)))
2307  {
2308  elem.i_ = i;
2309  elem.j_ = j;
2310  elem.k_ = k+1;
2311  elems.push_back(elem);
2312  }
2313  result = transform_.project(Core::Geometry::Point(ii,jj,kk));
2314 
2315  pdist = (p-result).length();
2316  return (true);
2317 }
2318 
2319 
2320 
2321 template <class Basis>
2322 int
2324  typename Node::array_type &locs,
2325  double *w)
2326 {
2327  typename Cell::index_type idx;
2328  if (locate(idx, p)) {
2329  get_nodes(locs, idx);
2330  std::vector<double> coords(3);
2331  if (get_coords(coords, p, idx)) {
2332  basis_.get_weights(coords, w);
2333  return basis_.dofs();
2334  }
2335  }
2336  return 0;
2337 }
2338 
2339 
2340 template <class Basis>
2341 int
2342 LatVolMesh<Basis>::get_weights(const Core::Geometry::Point &p, typename Cell::array_type &l,
2343  double *w)
2344 {
2345  typename Cell::index_type idx;
2346  if (locate(idx, p))
2347  {
2348  l.resize(1);
2349  l[0] = idx;
2350  w[0] = 1.0;
2351  return 1;
2352  }
2353  return 0;
2354 }
2355 
2356 
2357 template <class Basis>
2358 const std::string
2360 {
2361  static std::string name = LatVolMesh<Basis>::type_name(-1) + "::NodeIndex";
2362  return name;
2363 }
2364 
2365 
2366 template <class Basis>
2367 const std::string
2369 {
2370  static std::string name = LatVolMesh<Basis>::type_name(-1) + "::CellIndex";
2371  return name;
2372 }
2373 
2374 #define LATVOLMESH_VERSION 5
2375 
2376 template <class Basis>
2377 void
2379 {
2380  int version = stream.begin_class(type_name(-1), LATVOLMESH_VERSION);
2381 
2382  Mesh::io(stream);
2383 
2384  // IO data members, in order
2385  if (version < 5)
2386  {
2387  unsigned int ni = static_cast<unsigned int>(ni_);
2388  unsigned int nj = static_cast<unsigned int>(nj_);
2389  unsigned int nk = static_cast<unsigned int>(nk_);
2390  Pio(stream, ni);
2391  Pio(stream, nj);
2392  Pio(stream, nk);
2393  ni_ = static_cast<size_type>(ni);
2394  nj_ = static_cast<size_type>(nj);
2395  nk_ = static_cast<size_type>(nk);
2396  }
2397  else
2398  {
2399  Pio_size(stream, ni_);
2400  Pio_size(stream, nj_);
2401  Pio_size(stream, nk_);
2402  }
2403 
2404  if (version < 2 && stream.reading())
2405  {
2407  Pio(stream, min);
2408  Pio(stream, max);
2409  transform_.pre_scale(Core::Geometry::Vector(1.0 / (ni_ - 1.0),1.0 / (nj_ - 1.0),1.0 / (nk_ - 1.0)));
2410  transform_.pre_scale(max - min);
2411  transform_.pre_translate(Core::Geometry::Vector(min));
2412  transform_.compute_imat();
2413  }
2414  else if (version < 3 && stream.reading() )
2415  {
2416  Pio_old(stream, transform_);
2417  }
2418  else
2419  {
2420  Pio(stream, transform_);
2421  }
2422 
2423  if (version >= 4)
2424  {
2425  basis_.io(stream);
2426  }
2427 
2428  stream.end_class();
2429 
2430  if (stream.reading())
2431  {
2432  compute_jacobian();
2433  vmesh_.reset(CreateVLatVolMesh(this));
2434  }
2435 
2436 }
2437 
2438 template <class Basis>
2439 const std::string
2441 {
2442  ASSERT((n >= -1) && n <= 1);
2443  if (n == -1)
2444  {
2445  static const std::string name = TypeNameGenerator::make_template_id(type_name(0), type_name(1));
2446  return name;
2447  }
2448  else if (n == 0)
2449  {
2450  static const std::string nm("LatVolMesh");
2451  return nm;
2452  }
2453  else
2454  {
2455  return find_type_name((Basis *)0);
2456  }
2457 }
2458 
2459 
2460 template <class Basis>
2461 void
2463 {
2464  itr = typename Node::iterator(this, min_i_, min_j_, min_k_);
2465 }
2466 
2467 
2468 template <class Basis>
2469 void
2471 {
2472  itr = typename Node::iterator(this, min_i_, min_j_, min_k_ + nk_);
2473 }
2474 
2475 
2476 template <class Basis>
2477 void
2479 {
2480  s = typename Node::size_type(ni_,nj_,nk_);
2481 }
2482 
2483 
2484 template <class Basis>
2485 void
2487  index_type a) const
2488 {
2489  const index_type i = a % ni_;
2490  const index_type jk = a / ni_;
2491  const index_type j = jk % nj_;
2492  const index_type k = jk / nj_;
2493  idx = typename Node::index_type(this, i, j, k);
2494 }
2495 
2496 
2497 template <class Basis>
2498 void
2500 {
2501  itr = typename Edge::iterator(0);
2502 }
2503 
2504 
2505 template <class Basis>
2506 void
2508 {
2509  itr = ((ni_-1) * nj_ * nk_) + (ni_ * (nj_-1) * nk_) + (ni_ * nj_ * (nk_-1));
2510 }
2511 
2512 
2513 template <class Basis>
2514 void
2516 {
2517  s = ((ni_-1) * nj_ * nk_) + (ni_ * (nj_-1) * nk_) + (ni_ * nj_ * (nk_-1));
2518 }
2519 
2520 
2521 template <class Basis>
2522 void
2524 {
2525  itr = typename Face::iterator(0);
2526 }
2527 
2528 
2529 template <class Basis>
2530 void
2532 {
2533  itr = (ni_-1) * (nj_-1) * nk_ +
2534  ni_ * (nj_ - 1 ) * (nk_ - 1) +
2535  (ni_ - 1) * nj_ * (nk_ - 1);
2536 }
2537 
2538 
2539 template <class Basis>
2540 void
2542 {
2543  s = (ni_-1) * (nj_-1) * nk_ +
2544  ni_ * (nj_ - 1 ) * (nk_ - 1) +
2545  (ni_ - 1) * nj_ * (nk_ - 1);
2546 }
2547 
2548 
2549 template <class Basis>
2550 void
2552 {
2553  itr = typename Cell::iterator(this, min_i_, min_j_, min_k_);
2554 }
2555 
2556 
2557 template <class Basis>
2558 void
2560 {
2561  itr = typename Cell::iterator(this, min_i_, min_j_, min_k_ + nk_-1);
2562 }
2563 
2564 
2565 template <class Basis>
2566 void
2568 {
2569  s = typename Cell::size_type(ni_-1, nj_-1,nk_-1);
2570 }
2571 
2572 
2573 template <class Basis>
2574 void
2576  index_type a) const
2577 {
2578  const index_type i = a % (ni_-1);
2579  const index_type jk = a / (ni_-1);
2580  const index_type j = jk % (nj_-1);
2581  const index_type k = jk / (nj_-1);
2582  idx = typename Cell::index_type(this, i, j, k);
2583 }
2584 
2585 
2586 template <class Basis>
2587 void
2589 {
2590  Core::Geometry::Vector J1 = transform_.project(Core::Geometry::Vector(1.0,0.0,0.0));
2591  Core::Geometry::Vector J2 = transform_.project(Core::Geometry::Vector(0.0,1.0,0.0));
2592  Core::Geometry::Vector J3 = transform_.project(Core::Geometry::Vector(0.0,0.0,1.0));
2593 
2594  jacobian_[0] = J1.x();
2595  jacobian_[1] = J1.y();
2596  jacobian_[2] = J1.z();
2597  jacobian_[3] = J2.x();
2598  jacobian_[4] = J2.y();
2599  jacobian_[5] = J2.z();
2600  jacobian_[6] = J3.x();
2601  jacobian_[7] = J3.y();
2602  jacobian_[8] = J3.z();
2603 
2604  det_jacobian_ = DetMatrix3x3(jacobian_);
2605  scaled_jacobian_ = ScaledDetMatrix3x3(jacobian_);
2606  det_inverse_jacobian_ = InverseMatrix3x3(jacobian_,inverse_jacobian_);
2607 }
2608 
2609 template <class Basis>
2610 double
2612 {
2613  Core::Geometry::Point p0(static_cast<double>(ni_-1),
2614  static_cast<double>(nj_-1),
2615  static_cast<double>(nk_-1));
2616  Core::Geometry::Point p1(0.0,0.0,0.0);
2617  Core::Geometry::Point q0 = transform_.project(p0);
2618  Core::Geometry::Point q1 = transform_.project(p1);
2619  return ((q0-q1).length()*1e-8);
2620 }
2621 
2622 } // namespace SCIRun
2623 
2624 #endif
2625 
2626 
Definition: LatVolMesh.h:438
virtual MeshFacadeHandle getFacade() const
Definition: LatVolMesh.h:639
NodeIter iterator
Definition: LatVolMesh.h:425
bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, typename Elem::index_type idx) const
Definition: LatVolMesh.h:686
bool get_min(std::vector< index_type > &) const
Definition: LatVolMesh.h:1330
Interface to statically allocated std::vector class.
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, typename Elem::index_type &elem, const Core::Geometry::Point &p) const
Definition: LatVolMesh.h:1039
Definition: LatVolMesh.h:353
virtual Core::Geometry::BBox get_bounding_box() const
Definition: LatVolMesh.h:1277
RangeNodeIter()
Definition: LatVolMesh.h:286
CellIter & operator++()
Definition: LatVolMesh.h:254
bool reading() const
Definition: Persistent.h:164
index_type i_
Definition: LatVolMesh.h:127
std::vector< index_type > array_type
Definition: LatVolMesh.h:449
RangeNodeIter range_iter
Definition: LatVolMesh.h:428
void get_elems(typename Elem::array_type &result, const typename Node::index_type &idx) const
get the parent element(s) of the given index
Definition: LatVolMesh.h:1737
void get_point(Core::Geometry::Point &p, const typename Node::index_type &i) const
Definition: LatVolMesh.h:955
Definition: FieldRNG.h:37
index_type get_min_j() const
Definition: LatVolMesh.h:818
const Core::Geometry::Point node7() const
Definition: LatVolMesh.h:557
ElemData(const LatVolMesh< Basis > &msh, const typename Cell::index_type ind)
Definition: LatVolMesh.h:471
NodeIter & operator++()
Definition: LatVolMesh.h:216
FaceIndex< under_type > size_type
Definition: LatVolMesh.h:441
size_type nj_
Definition: LatVolMesh.h:1111
std::string get_name(const std::string &type_sep_start="<", const std::string &type_sep_end="> ") const
Definition: TypeDescription.cc:135
Distinct type for face Iterator.
Definition: FieldIterator.h:121
double inverse_jacobian_[9]
Definition: LatVolMesh.h:1120
std::ostream & str_render(std::ostream &os) const
Definition: LatVolMesh.h:116
void pwl_approx_face(std::vector< std::vector< std::vector< double > > > &coords, typename Elem::index_type, unsigned int which_face, unsigned int div_per_unit) const
Definition: LatVolMesh.h:664
index_type get_min_i() const
get the mesh statistics
Definition: LatVolMesh.h:817
Vector project(const Vector &p) const
Definition: Transform.cc:425
index_type node5_index() const
Definition: LatVolMesh.h:505
const Core::Geometry::Point node4() const
Definition: LatVolMesh.h:542
Point max() const
Definition: BBox.h:195
const CellIndex & operator*() const
Definition: LatVolMesh.h:247
static Persistent * maker()
This function returns a maker for Pio.
Definition: LatVolMesh.h:1094
void set_min_j(index_type j)
Definition: LatVolMesh.h:833
bool operator==(const LatIter &a) const
Definition: LatVolMesh.h:195
SCIRun::index_type index_type
Definition: LatVolMesh.h:94
static MeshHandle mesh_maker()
This function returns a handle for the virtual interface.
Definition: LatVolMesh.h:1096
Definition: LatVolMesh.h:63
Definition: Persistent.h:89
void pre_scale(const Vector &)
Definition: Transform.cc:193
Definition: LatVolMesh.h:431
Basis & get_basis()
Definition: LatVolMesh.h:647
LatSize(size_type i, size_type j, size_type k)
Definition: LatVolMesh.h:162
bool locate(typename Node::index_type &, const Core::Geometry::Point &) const
Definition: LatVolMesh.h:2149
Point unproject(const Point &p) const
Definition: Transform.cc:483
index_type nj() const
Definition: LatVolMesh.h:124
virtual bool unsynchronize(mask_type)
Definition: LatVolMesh.h:679
const Core::Geometry::Point node6() const
Definition: LatVolMesh.h:552
Basis basis_type
Definition: LatVolMesh.h:99
virtual const TypeDescription * get_type_description() const
Definition: LatVolMesh.h:1148
Definition: LatVolMesh.h:180
index_type get_min_k() const
Definition: LatVolMesh.h:819
int get_weights(const Core::Geometry::Point &, typename Edge::array_type &, double *)
Definition: LatVolMesh.h:949
void derivate(const VECTOR1 &coords, typename Elem::index_type idx, VECTOR2 &J) const
Definition: LatVolMesh.h:748
void y(const double)
Definition: Point.h:135
double get_length(typename Edge::index_type idx) const
Definition: LatVolMesh.h:934
FaceIndex< under_type > index_type
Definition: LatVolMesh.h:439
index_type ni() const
Definition: LatVolMesh.h:123
Definition: Persistent.h:187
double inverse_jacobian(const VECTOR &, typename Elem::index_type, double *Ji) const
Definition: LatVolMesh.h:795
BBox & extend(const Point &p)
Expand the bounding box to include point p.
Definition: BBox.h:98
virtual LatVolMesh * clone() const
Definition: LatVolMesh.h:628
index_type node3_index() const
Definition: LatVolMesh.h:495
static const TypeDescription * face_type_description()
Definition: LatVolMesh.h:1192
index_type node2_index() const
Definition: LatVolMesh.h:489
Definition: TypeDescription.h:50
void end(typename Node::iterator &) const
FieldHandle mesh()
Definition: BuildTDCSMatrixTests.cc:56
Definition: LatVolMesh.h:174
Definition: Point.h:49
LatIndex()
Definition: LatVolMesh.h:107
Definition: TypeDescription.h:45
#define SCISHARE
Definition: share.h:39
std::vector< const TypeDescription * > td_vec
Definition: TypeDescription.h:56
size_type k_
Definition: LatVolMesh.h:171
size_type nk_
Definition: LatVolMesh.h:1111
size_type j_
Definition: LatVolMesh.h:171
Definition: Mesh.h:45
std::ostream & str_render(std::ostream &os) const
Definition: LatVolMesh.h:166
Definition: BBox.h:46
boost::shared_ptr< Mesh > MeshHandle
Definition: DatatypeFwd.h:67
const LatIndex & operator*()
Definition: LatVolMesh.h:193
virtual std::string dynamic_type_name() const
Definition: LatVolMesh.h:1068
LatIter()
Definition: LatVolMesh.h:189
RangeNodeIter(const LatVolMesh *m, index_type i, index_type j, index_type k, index_type max_i, index_type max_j, index_type max_k)
Definition: LatVolMesh.h:289
void end(NodeIter &end_iter)
Definition: LatVolMesh.h:320
void compute_imat() const
Definition: Transform.cc:687
Definition: Mesh.h:61
NodeIndex index_type
Definition: LatVolMesh.h:424
unsigned int mask_type
Definition: Types.h:45
Definition: LatVolMesh.h:104
virtual bool has_normals() const
Definition: LatVolMesh.h:643
virtual int topology_geometry() const
Definition: LatVolMesh.h:1081
bool find_closest_node(double &pdist, Core::Geometry::Point &result, typename Node::index_type &elem, const Core::Geometry::Point &p) const
Definition: LatVolMesh.h:2179
Definition: LatVolMesh.h:158
index_type min_j_
Definition: LatVolMesh.h:1108
#define ASSERT(condition)
Definition: Assert.h:110
LatIndex(const LatVolMesh *m, index_type i, index_type j, index_type k)
Definition: LatVolMesh.h:108
virtual bool has_face_normals() const
Definition: LatVolMesh.h:644
index_type node0_index() const
Definition: LatVolMesh.h:479
RangeNodeIter & operator++()
Definition: LatVolMesh.h:297
index_type min_k_
Definition: LatVolMesh.h:1108
virtual int begin_class(const std::string &name, int current_version)
Definition: Persistent.cc:143
virtual void get_canonical_transform(Core::Geometry::Transform &t)
Definition: LatVolMesh.h:1321
EdgeIndex< under_type > size_type
Definition: LatVolMesh.h:434
virtual void transform(const Core::Geometry::Transform &t)
Definition: LatVolMesh.h:1311
void begin(typename Node::iterator &) const
void set_nj(index_type j)
Definition: LatVolMesh.h:842
bool locate(typename Edge::index_type &, const Core::Geometry::Point &) const
Definition: LatVolMesh.h:942
static std::string type_name(int i=-1)
Definition: LatVolMesh.h:151
Definition: Vector.h:63
Index and Iterator types required for Mesh Concept.
Definition: LatVolMesh.h:423
double get_size(const typename Node::index_type &idx) const
Get the size of an elemnt (length, area, volume)
Definition: LatVolMesh.h:2050
double det_inverse_jacobian_
Definition: LatVolMesh.h:1123
virtual bool is_editable() const
Definition: LatVolMesh.h:645
void get_random_point(Core::Geometry::Point &, const typename Elem::index_type &, FieldRNG &rng) const
Definition: LatVolMesh.h:1250
index_type j_
Definition: LatVolMesh.h:127
const string find_type_name(float *)
Definition: TypeName.cc:63
void z(const double)
Definition: Point.h:145
const Core::Geometry::Point node3() const
Definition: LatVolMesh.h:537
size_type ni_
Definition: LatVolMesh.h:1111
LatVolMesh()
Definition: LatVolMesh.h:568
void get_normal(Core::Geometry::Vector &, const typename Node::index_type &) const
Definition: LatVolMesh.h:958
double det_jacobian_
Definition: LatVolMesh.h:1121
NodeSize(size_type i, size_type j, size_type k)
Definition: LatVolMesh.h:183
double get_volume(const typename Cell::index_type &i) const
Definition: LatVolMesh.h:938
double scaled_jacobian_metric(typename Elem::index_type) const
Definition: LatVolMesh.h:810
T DetMatrix3x3(const T *p)
Definition: Locate.h:95
const NodeIndex & operator*() const
Definition: LatVolMesh.h:295
index_type min_i_
the min_Node::index_type ( incase this is a subLattice )
Definition: LatVolMesh.h:1108
Definition: ParallelLinearAlgebraTests.cc:358
FaceIterator< under_type > iterator
Definition: LatVolMesh.h:440
double get_epsilon() const
Definition: LatVolMesh.h:2611
Definition: LatVolMesh.h:187
const char * name[]
Definition: BoostGraphExampleTests.cc:87
void x(const double)
Definition: Point.h:125
const Core::Geometry::Point node0() const
Definition: LatVolMesh.h:522
static const TypeDescription * cell_type_description()
Definition: LatVolMesh.h:1210
virtual int dimensionality() const
Definition: LatVolMesh.h:1080
long long size_type
Definition: Types.h:40
StackVector< index_type, 8 > array_type
Definition: LatVolMesh.h:427
void get_faces(typename Face::array_type &, const typename Cell::index_type &) const
Definition: LatVolMesh.h:1670
double det_jacobian(const VECTOR &coords, typename Elem::index_type idx) const
Definition: LatVolMesh.h:769
RangeCellIter range_iter
Definition: LatVolMesh.h:450
const Core::Geometry::Point node2() const
Definition: LatVolMesh.h:532
Vector Cross(const Vector &v1, const Vector &v2)
Definition: Vector.h:378
void set_min(std::vector< index_type > mins)
Definition: LatVolMesh.h:1360
NodeSize()
Definition: LatVolMesh.h:182
double scaled_jacobian_
Definition: LatVolMesh.h:1122
CellSize(size_type i, size_type j, size_type k)
Definition: LatVolMesh.h:177
void set_nk(index_type k)
Definition: LatVolMesh.h:848
static const TypeDescription * node_type_description()
Definition: LatVolMesh.h:1156
void size(typename Node::size_type &) const
LatSize()
Definition: LatVolMesh.h:161
void get_delems(typename DElem::array_type &result, const typename Elem::index_type &idx) const
Wrapper to get the derivative elements from this element.
Definition: LatVolMesh.h:903
void get_center(Core::Geometry::Point &, const typename Node::index_type &) const
get the center point (in object space) of an element
Definition: LatVolMesh.h:2040
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, typename Elem::index_type &elem, const Core::Geometry::Point &p, double maxdist) const
Definition: LatVolMesh.h:980
LatVolMesh(const LatVolMesh &copy)
Definition: LatVolMesh.h:607
virtual int basis_order()
Definition: LatVolMesh.h:641
Core::Geometry::Vector diagonal() const
Definition: LatVolMesh.h:1303
NodeIndex(const LatVolMesh *m, size_type i, size_type j, size_type k)
Definition: LatVolMesh.h:149
friend struct FaceIter
Definition: LatVolMesh.h:459
Definition: LatVolMesh.h:208
void set_ni(index_type i)
Definition: LatVolMesh.h:836
double jacobian_[9]
Definition: LatVolMesh.h:1119
std::string type
Definition: Persistent.h:72
void get_cells(typename Cell::array_type &arr, const Core::Geometry::BBox &box)
return all cell_indecies that overlap the BBox in arr.
Definition: LatVolMesh.h:1762
static const TypeDescription * edge_type_description()
Definition: LatVolMesh.h:1174
void set_min_k(index_type k)
Definition: LatVolMesh.h:834
static const std::string type_name(int n=-1)
Core functionality for getting the name of a templated mesh class.
Definition: LatVolMesh.h:2440
Point min() const
Definition: BBox.h:192
Distinct type for face index.
Definition: FieldIndex.h:90
SCISHARE bool overlaps(const BBox &bb) const
bbox&#39;s that share a face overlap
Definition: BBox.cc:88
RangeCellIter & operator++()
Definition: LatVolMesh.h:366
Definition: Transform.h:53
size_type i_
Definition: LatVolMesh.h:171
Core::Geometry::Transform & get_transform()
Definition: LatVolMesh.h:1071
void x(double)
Definition: Vector.h:175
Basis basis_
Definition: LatVolMesh.h:1114
void to_index(typename Face::index_type &index, index_type i) const
Definition: LatVolMesh.h:877
Cell Elem
Definition: LatVolMesh.h:453
static MeshHandle latvol_maker(size_type x, size_type y, size_type z, const Core::Geometry::Point &min, const Core::Geometry::Point &max)
This function returns a handle for the virtual interface.
Definition: LatVolMesh.h:1098
virtual bool synchronize(mask_type)
Definition: LatVolMesh.h:678
std::vector< index_type > array_type
Definition: LatVolMesh.h:435
static const std::string make_template_id(const std::string &templateName, const std::string &templateParam)
Definition: TypeName.h:62
RangeCellIter(const LatVolMesh *m, index_type i, index_type j, index_type k, index_type max_i, index_type max_j, index_type max_k)
Definition: LatVolMesh.h:358
v
Definition: readAllFields.py:42
Definition: LatVolMesh.h:146
void pre_translate(const Vector &)
Definition: Transform.cc:278
bool find_closest_elems(double &pdist, Core::Geometry::Point &result, std::vector< typename Elem::index_type > &elem, const Core::Geometry::Point &p) const
Definition: LatVolMesh.h:2227
CellSize size_type
Definition: LatVolMesh.h:448
const Core::Geometry::Point node5() const
Definition: LatVolMesh.h:547
bool locate(typename Face::index_type &, const Core::Geometry::Point &) const
Definition: LatVolMesh.h:944
std::vector< index_type > array_type
Definition: LatVolMesh.h:442
Definition: LatVolMesh.h:241
void compute_jacobian()
Definition: LatVolMesh.h:2588
void y(double)
Definition: Vector.h:185
CellIndex(const LatVolMesh *m, index_type i, index_type j, index_type k)
Definition: LatVolMesh.h:136
LatVolMesh(LatVolMesh *, size_type mx, size_type my, size_type mz, size_type x, size_type y, size_type z)
Definition: LatVolMesh.h:588
double get_area(typename Face::index_type idx) const
Definition: LatVolMesh.h:936
Distinct type for edge Iterator.
Definition: FieldIterator.h:105
Definition: LatVolMesh.h:284
CellSize()
Definition: LatVolMesh.h:176
#define ASSERTFAIL(string)
Definition: Assert.h:52
index_type node4_index() const
Definition: LatVolMesh.h:500
void jacobian(const VECTOR &coords, typename Elem::index_type idx, double *J) const
Definition: LatVolMesh.h:778
LatIter(const LatVolMesh *m, index_type i, index_type j, index_type k)
Definition: LatVolMesh.h:190
void Pio(Piostream &stream, Array1< T > &array)
Definition: Array1.h:65
Some convenient simple iterators for fields.
friend struct EdgeIter
Definition: LatVolMesh.h:458
NodeIndex()
Definition: LatVolMesh.h:148
bool operator!=(const LatIter &a) const
Definition: LatVolMesh.h:201
index_type nk() const
Definition: LatVolMesh.h:125
CellIndex index_type
Definition: LatVolMesh.h:446
double jacobian_metric(typename Elem::index_type) const
Definition: LatVolMesh.h:813
virtual bool get_dim(std::vector< size_type > &) const
Definition: LatVolMesh.h:1345
double length() const
Definition: Vector.h:365
virtual void end_class()
Definition: Persistent.cc:178
CellIter iterator
Definition: LatVolMesh.h:447
virtual VMesh * vmesh()
Access point to virtual interface.
Definition: LatVolMesh.h:635
CellIter(const LatVolMesh *m, index_type i, index_type j, index_type k)
Definition: LatVolMesh.h:244
Core::Geometry::Transform & set_transform(const Core::Geometry::Transform &trans)
Definition: LatVolMesh.h:1072
T ScaledDetMatrix3x3(const T *p)
Definition: Locate.h:106
NodeIter(const LatVolMesh *m, index_type i, index_type j, index_type k)
Definition: LatVolMesh.h:211
index_type node1_index() const
Definition: LatVolMesh.h:484
void end(CellIter &end_iter)
Definition: LatVolMesh.h:389
LatVolMesh< Basis >::index_type index_type
Definition: LatVolMesh.h:469
long long index_type
Definition: Types.h:39
const NodeIndex & operator*() const
Definition: LatVolMesh.h:214
static const TypeDescription * elem_type_description()
Definition: LatVolMesh.h:1090
void resize(size_t size, const value_type &val=value_type())
Definition: StackVector.h:61
bool clear_synchronization()
Definition: LatVolMesh.h:680
VMesh * CreateVLatVolMesh(MESH *)
Definition: LatVolMesh.h:69
SCISHARE void Pio_old(Piostream &, Transform &)
Definition: Transform.cc:940
Face DElem
Definition: LatVolMesh.h:454
RangeCellIter()
Definition: LatVolMesh.h:355
NodeSize size_type
Definition: LatVolMesh.h:426
Definition: LatVolMesh.h:133
unsigned long long Max(unsigned long long d1, unsigned long long d2)
Definition: MiscMath.h:75
Core::Geometry::Transform transform_
Definition: LatVolMesh.h:1113
EdgeIterator< under_type > iterator
Definition: LatVolMesh.h:433
int get_weights(const Core::Geometry::Point &p, typename Node::array_type &l, double *w)
Definition: LatVolMesh.h:2323
Definition: Persistent.h:64
boost::shared_ptr< LatVolMesh< Basis > > handle_type
Definition: LatVolMesh.h:98
const Core::Geometry::Point node1() const
Definition: LatVolMesh.h:527
int get_weights(const Core::Geometry::Point &, typename Face::array_type &, double *)
Definition: LatVolMesh.h:951
Distinct type for edge index.
Definition: FieldIndex.h:81
unsigned long long Min(unsigned long long d1, unsigned long long d2)
Faster versions of several math functions.
Definition: MiscMath.h:70
int n
Definition: eab.py:9
SCIRun::mask_type mask_type
Definition: LatVolMesh.h:96
index_type get_nk() const
Definition: LatVolMesh.h:823
friend class VLatVolMesh
Definition: LatVolMesh.h:89
void to_index(typename Edge::index_type &index, index_type i) const
Definition: LatVolMesh.h:875
index_type get_nj() const
Definition: LatVolMesh.h:822
index_type get_ni() const
Definition: LatVolMesh.h:821
NodeIter()
Definition: LatVolMesh.h:210
T InverseMatrix3x3(const T *p, T *q)
Definition: Locate.h:47
index_type node7_index() const
Definition: LatVolMesh.h:516
void get_normal(Core::Geometry::Vector &, std::vector< double > &, typename Elem::index_type, unsigned int)
Definition: LatVolMesh.h:960
CellIter()
Definition: LatVolMesh.h:243
void post_scale(const Vector &)
Definition: Transform.cc:202
virtual void io(Piostream &)
Export this class using the old Pio system.
Definition: LatVolMesh.h:2378
CellIndex()
Definition: LatVolMesh.h:135
bool get_neighbor(typename Cell::index_type &neighbor, const typename Cell::index_type &from, typename Face::index_type face) const
Definition: LatVolMesh.h:1827
Definition: LatVolMesh.h:445
#define DEBUG_CONSTRUCTOR(type)
Definition: Debug.h:64
index_type node6_index() const
Definition: LatVolMesh.h:511
const LatVolMesh * mesh_
Definition: LatVolMesh.h:130
void io(Piostream &stream)
Persistent I/O.
Definition: Mesh.cc:387
SCIRun::size_type size_type
Definition: LatVolMesh.h:95
boost::shared_ptr< VMesh > vmesh_
Definition: LatVolMesh.h:1125
void set_min_i(index_type i)
set the mesh statistics
Definition: LatVolMesh.h:832
EdgeIndex< under_type > index_type
Definition: LatVolMesh.h:432
Definition: Mesh.h:63
void Pio_size(Piostream &stream, Size &size)
Definition: Persistent.h:273
void z(double)
Definition: Vector.h:195
void pwl_approx_edge(std::vector< std::vector< double > > &coords, typename Elem::index_type, unsigned int which_edge, unsigned int div_per_unit) const
Definition: LatVolMesh.h:651
virtual ~LatVolMesh()
Definition: LatVolMesh.h:629
boost::shared_ptr< MeshFacade< VMesh > > MeshFacadeHandle
Definition: MeshTraits.h:61
Definition: VMesh.h:53
index_type k_
Definition: LatVolMesh.h:127
virtual void set_dim(std::vector< size_type > dims)
Definition: LatVolMesh.h:1370
#define LATVOLMESH_VERSION
Definition: LatVolMesh.h:2374
void get_edges(typename Edge::array_type &, typename Face::index_type) const
Definition: LatVolMesh.h:1513
SCIRun::index_type under_type
Definition: LatVolMesh.h:93
void get_nodes(typename Node::array_type &, typename Edge::index_type) const
get the child elements of the given index
Definition: LatVolMesh.h:1386
const CellIndex & operator*() const
Definition: LatVolMesh.h:364
void to_index(typename Node::index_type &index, index_type i) const
#define DEBUG_DESTRUCTOR(type)
Definition: Debug.h:65
const TypeDescription * get_type_description(Core::Basis::ConstantBasis< T > *)
Definition: Constant.h:209
void interpolate(Core::Geometry::Point &pt, const VECTOR &coords, typename Elem::index_type idx) const
Definition: LatVolMesh.h:726
Definition: LatVolMesh.h:466
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, typename Elem::index_type &elem, const Core::Geometry::Point &p) const
Definition: LatVolMesh.h:997