SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HexVolMesh.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_HEXVOLMESH
31 #define CORE_DATATYPES_HEXVOLMESH 1
32 
33 /// Include what kind of support we want to have
34 /// Need to fix this and couple it sci-defs
36 
38 
46 
47 #include <Core/Basis/Locate.h>
51 
57 
60 
61 #include <Core/Thread/Mutex.h>
63 #include <boost/thread.hpp>
64 
65 #include <set>
66 
67 /// Include needed for Windows: declares SCISHARE
69 
70 namespace SCIRun {
71 
72 /////////////////////////////////////////////////////
73 // Declarations for virtual interface
74 
75 /// Functions for creating the virtual interface
76 /// Declare the functions that instantiate the virtual interface
77 template <class Basis> class HexVolMesh;
78 
79 /// make sure any other mesh other than the preinstantiate ones
80 /// returns no virtual interface. Altering this behavior will allow
81 /// for dynamically compiling the interface if needed.
82 template<class MESH>
83 VMesh* CreateVHexVolMesh(MESH*) { return (0); }
84 
85 /// These declarations are needed for a combined dynamic compilation as
86 /// as well as virtual functions solution.
87 /// Declare that these can be found in a library that is already
88 /// precompiled. So dynamic compilation will not instantiate them again.
89 
90 #if (SCIRUN_HEXVOL_SUPPORT > 0)
91 
92 SCISHARE VMesh* CreateVHexVolMesh(HexVolMesh<Core::Basis::HexTrilinearLgn<Core::Geometry::Point> >* mesh);
93 #if (SCIRUN_QUADRATIC_SUPPORT > 0)
94 SCISHARE VMesh* CreateVHexVolMesh(HexVolMesh<Core::Basis::HexTriquadraticLgn<Core::Geometry::Point> >* mesh);
95 #endif
96 #if (SCIRUN_CUBIC_SUPPORT > 0)
97 SCISHARE VMesh* CreateVHexVolMesh(HexVolMesh<Core::Basis::HexTricubicHmt<Core::Geometry::Point> >* mesh);
98 #endif
99 
100 #endif
101 /////////////////////////////////////////////////////
102 
103 static const int
104 HexVolEdgePerNodeTable[8][6] = {{3,0, 0,1, 0,4},
105  {0,1, 1,2, 5,1},
106  {1,2, 2,3, 2,6},
107  {2,3, 3,0, 3,2},
108  {4,5, 0,4, 7,4},
109  {5,1, 4,5, 5,6},
110  {2,6, 5,6, 6,7},
111  {7,3, 6,7, 7,4}};
112 
113 static const int
114 HexVolFacePerNodeTable[8][12] = {{0,1,2,3, 0,4,5,1, 3,7,4,0},
115  {0,1,2,3, 0,4,5,1, 1,5,6,2},
116  {0,1,2,3, 2,6,7,3, 1,5,6,2},
117  {0,1,2,3, 2,6,7,3, 3,7,4,0},
118  {0,4,5,1, 3,7,4,0, 7,6,5,4},
119  {0,4,5,1, 1,5,6,2, 7,6,5,4},
120  {2,6,7,3, 1,5,6,2, 7,6,5,4},
121  {2,6,7,3, 3,7,4,0, 7,6,5,4}};
122 
123 static const int
124 HexVolFacePerEdgeTable[12][8] = {{0, 1, 2, 3, 0, 4, 5, 1},
125  {0, 1, 2, 3, 1, 5, 6, 2},
126  {0, 1, 2, 3, 2, 6, 7, 3},
127  {0, 1, 2, 3, 3, 7, 4, 0},
128  {7, 6, 5, 4, 0, 4, 5, 1},
129  {7, 6, 5, 4, 1, 5, 6, 2},
130  {7, 6, 5, 4, 2, 6, 7, 3},
131  {7, 6, 5, 4, 3, 7, 4, 0},
132  {0, 4, 5, 1, 3, 7, 4, 0},
133  {0, 4, 5, 1, 1, 5, 6, 2},
134  {2, 6, 7, 3, 1, 5, 6, 2},
135  {2, 6, 7, 3, 3, 7, 4, 0}};
136 
137 static const int
138 HexVolEdgePerFaceTable[6][8] = {{0,1, 1,2, 2,3, 3,0},
139  {6,7, 5,6, 4,5, 7,4},
140  {0,4, 4,5, 5,1, 0,1},
141  {2,6, 6,7, 7,3, 2,3},
142  {7,3, 7,4, 0,4, 3,0},
143  {5,1, 5,6, 2,6, 1,2}};
144 
145 static const int
146 HexVolEdgeTable[12][2] = {{0,1},{1,2},{2,3},{3,0},
147  {4,5},{5,6},{6,7},{7,4},
148  {0,4},{5,1},{2,6},{7,3}};
149 
150 static const int
151 HexVolFaceTable[6][4] = { {0,1,2,3},{7,6,5,4},{0,4,5,1},
152  {2,6,7,3},{3,7,4,0},{1,5,6,2}};
153 
154 /////////////////////////////////////////////////////
155 // Declarations for HexVolMesh class
156 
157 template <class Basis>
158 class HexVolMesh : public Mesh
159 {
160  /// Make sure the virtual interface has access
161  template <class MESH> friend class VHexVolMesh;
162  template <class MESH> friend class VMeshShared;
163  template <class MESH> friend class VUnstructuredMesh;
164 
165 public:
166  // Types that change depending on 32 or 64bits
171 
172  typedef boost::shared_ptr<HexVolMesh<Basis> > handle_type;
173  typedef Basis basis_type;
174 
175  /// Index and Iterator types required for Mesh Concept.
176  struct Node {
181  };
182 
183  struct Edge {
187  typedef std::vector<index_type> array_type;
188  };
189 
190  struct Face {
194  typedef std::vector<index_type> array_type;
195  };
196 
197  struct Cell {
201  typedef std::vector<index_type> array_type;
202  };
203 
204  /// Elem refers to the most complex topological object
205  /// DElem refers to object just below Elem in the topological hierarchy
206 
207  typedef Cell Elem;
208  typedef Face DElem;
209 
210  /// Somehow the information of how to interpolate inside an element
211  /// ended up in a separate class, as they need to share information
212  /// this construction was created to transfer data.
213  /// Hopefully in the future this class will disappear again.
214  friend class ElemData;
215 
216  class ElemData
217  {
218  public:
220 
221  ElemData(const HexVolMesh<Basis>& msh, const index_type ind) :
222  mesh_(msh),
223  index_(ind)
224  {
225  //Linear and Constant Basis never use edges_
226  if (basis_type::polynomial_order() > 1)
227  {
228  mesh_.get_edges_from_cell(edges_, index_);
229  }
230  }
231 
232  // the following designed to coordinate with ::get_nodes
233  inline
235  return mesh_.cells_[index_ * 8];
236  }
237  inline
239  return mesh_.cells_[index_ * 8 + 1];
240  }
241  inline
243  return mesh_.cells_[index_ * 8 + 2];
244  }
245  inline
247  return mesh_.cells_[index_ * 8 + 3];
248  }
249  inline
251  return mesh_.cells_[index_ * 8 + 4];
252  }
253  inline
255  return mesh_.cells_[index_ * 8 + 5];
256  }
257  inline
259  return mesh_.cells_[index_ * 8 + 6];
260  }
261  inline
263  return mesh_.cells_[index_ * 8 + 7];
264  }
265 
266  /// the following designed to coordinate with ::get_edges
267  inline
269  return edges_[0];
270  }
271  inline
273  return edges_[1];
274  }
275  inline
277  return edges_[2];
278  }
279  inline
281  return edges_[3];
282  }
283  inline
285  return edges_[4];
286  }
287  inline
289  return edges_[5];
290  }
291  inline
293  return edges_[6];
294  }
295  inline
297  return edges_[7];
298  }
299  inline
301  return edges_[8];
302  }
303  inline
305  return edges_[9];
306  }
307  inline
309  return edges_[10];
310  }
311  inline
313  return edges_[11];
314  }
315 
316  inline
317  const Core::Geometry::Point &node0() const {
318  return mesh_.points_[node0_index()];
319  }
320  inline
321  const Core::Geometry::Point &node1() const {
322  return mesh_.points_[node1_index()];
323  }
324  inline
325  const Core::Geometry::Point &node2() const {
326  return mesh_.points_[node2_index()];
327  }
328  inline
329  const Core::Geometry::Point &node3() const {
330  return mesh_.points_[node3_index()];
331  }
332  inline
333  const Core::Geometry::Point &node4() const {
334  return mesh_.points_[node4_index()];
335  }
336  inline
337  const Core::Geometry::Point &node5() const {
338  return mesh_.points_[node5_index()];
339  }
340  inline
341  const Core::Geometry::Point &node6() const {
342  return mesh_.points_[node6_index()];
343  }
344  inline
345  const Core::Geometry::Point &node7() const {
346  return mesh_.points_[node7_index()];
347  }
348 
349  private:
350  /// reference of the mesh
351  const HexVolMesh<Basis> &mesh_;
352  /// copy of index
353  const index_type index_;
354  /// need edges for quadratic meshes
355  typename Edge::array_type edges_;
356  };
357 
358  friend class Synchronize;
359 
360  class Synchronize //: public Runnable
361  {
362  public:
364  mesh_(mesh), sync_(sync) {}
365 
366  void operator()() { run(); }
367  void run()
368  {
369  mesh_.synchronize_lock_.lock();
370  // block out all the tables that are already synchronized
371  sync_ &= ~(mesh_.synchronized_);
372  // block out all the tables that are already being computed
373  sync_ &= ~(mesh_.synchronizing_);
374  // Now sync_ contains what this thread will synchronize
375  // Denote what this thread will synchronize
376  mesh_.synchronizing_ |= sync_;
377  // Other threads now know what this tread will be doing
378  mesh_.synchronize_lock_.unlock();
379 
380  // Sync node neighbors
381  if (sync_ & Mesh::NODE_NEIGHBORS_E) mesh_.compute_node_neighbors();
382  if (sync_ & Mesh::EDGES_E) mesh_.compute_edges();
383  if (sync_ & Mesh::FACES_E) mesh_.compute_faces();
384  if (sync_ & Mesh::BOUNDING_BOX_E) mesh_.compute_bounding_box();
385 
386  // These depend on the bounding box being synchronized
388  {
389  {
390  Core::Thread::UniqueLock lock(mesh_.synchronize_lock_.get());
391  while(!(mesh_.synchronized_&Mesh::BOUNDING_BOX_E))
392  mesh_.synchronize_cond_.wait(lock);
393  }
394  if (sync_ & Mesh::NODE_LOCATE_E) mesh_.compute_node_grid();
395  if (sync_ & Mesh::ELEM_LOCATE_E) mesh_.compute_elem_grid();
396  }
397 
398  mesh_.synchronize_lock_.lock();
399  // Mark the ones that were just synchronized
400  mesh_.synchronized_ |= sync_;
401  // Unmark the the ones that were done
402  mesh_.synchronizing_ &= ~(sync_);
403  /// Tell other threads we are done
404  mesh_.synchronize_cond_.conditionBroadcast();
405  mesh_.synchronize_lock_.unlock();
406  }
407 
408  private:
409  HexVolMesh<Basis>& mesh_;
410  mask_type sync_;
411  };
412 
413  //////////////////////////////////////////////////////////////////
414 
415  /// Construct a new mesh
416  HexVolMesh();
417 
418  /// Copy a mesh, needed for detaching the mesh from a field
419  HexVolMesh(const HexVolMesh &copy);
420 
421  /// Clone function for detaching the mesh and automatically generating
422  /// a new version if needed.
423  virtual HexVolMesh *clone() const { return new HexVolMesh(*this); }
424 
425  /// Destructor
426  virtual ~HexVolMesh();
427 
428  /// Access point to virtual interface
429  virtual VMesh* vmesh() { return (vmesh_.get()); }
430 
432  {
433  return boost::make_shared<Core::Datatypes::VirtualMeshFacade<VMesh>>(vmesh_);
434  }
435 
436  /// This one should go at some point, should be reroute through the
437  /// virtual interface
438  virtual int basis_order() { return (basis_.polynomial_order()); }
439 
440  /// Topological dimension
441  virtual int dimensionality() const { return 3; }
442 
443  /// What kind of mesh is this
444  /// structured = no connectivity data
445  /// regular = no node location data
446  virtual int topology_geometry() const
447  { return (Mesh::UNSTRUCTURED | Mesh::IRREGULAR); }
448 
449  /// Get the bounding box of the field
450  virtual Core::Geometry::BBox get_bounding_box() const;
451 
452  /// Return the transformation that takes a 0-1 space bounding box
453  /// to the current bounding box of this mesh.
454  virtual void get_canonical_transform(Core::Geometry::Transform &t) const;
455 
456  /// Transform a field (transform all nodes using this transformation matrix)
457  virtual void transform(const Core::Geometry::Transform &t);
458 
459  /// Check whether mesh can be altered by adding nodes or elements
460  virtual bool is_editable() const { return (true); }
461 
462  /// Has this mesh normals.
463  virtual bool has_normals() const { return (false); }
464 
465  /// Has this mesh face normals
466  virtual bool has_face_normals() const { return (true); }
467 
468  double get_epsilon() const { return (epsilon_); }
469 
470  /// Compute tables for doing topology, these need to be synchronized
471  /// before doing a lot of operations.
472  virtual bool synchronize(mask_type mask);
473  virtual bool unsynchronize(mask_type sync);
474  bool clear_synchronization();
475 
476  /// Get the basis class.
477  Basis& get_basis() { return basis_; }
478 
479  /// begin/end iterators
480  void begin(typename Node::iterator &) const;
481  void begin(typename Edge::iterator &) const;
482  void begin(typename Face::iterator &) const;
483  void begin(typename Cell::iterator &) const;
484 
485  void end(typename Node::iterator &) const;
486  void end(typename Edge::iterator &) const;
487  void end(typename Face::iterator &) const;
488  void end(typename Cell::iterator &) const;
489 
490  /// Get the iteration sizes
491  void size(typename Node::size_type &) const;
492  void size(typename Edge::size_type &) const;
493  void size(typename Face::size_type &) const;
494  void size(typename Cell::size_type &) const;
495 
496  /// These are here to convert indices to unsigned int
497  /// counters. Some how the decision was made to use multi
498  /// dimensional indices in some fields, these functions
499  /// should deal with different pointer types.
500  /// Use the virtual interface to avoid all this non sense.
501  void to_index(typename Node::index_type &index, index_type i) const
502  { index = i; }
503  void to_index(typename Edge::index_type &index, index_type i) const
504  { index = i; }
505  void to_index(typename Face::index_type &index, index_type i) const
506  { index = i; }
507  void to_index(typename Cell::index_type &index, index_type i) const
508  { index = i; }
509 
510  /// Get the child topology elements of the given topology
511  void get_nodes(typename Node::array_type &array,
512  typename Node::index_type idx) const
513  { array.resize(1); array[0]= idx; }
514  void get_nodes(typename Node::array_type &array,
515  typename Edge::index_type idx) const
516  { get_nodes_from_edge(array,idx); }
517  void get_nodes(typename Node::array_type &array,
518  typename Face::index_type idx) const
519  { get_nodes_from_face(array,idx); }
520  void get_nodes(typename Node::array_type &array,
521  typename Cell::index_type idx) const
522  { get_nodes_from_cell(array,idx); }
523 
524  void get_edges(typename Edge::array_type &array,
525  typename Node::index_type idx) const
526  { get_edges_from_node(array,idx); }
527  void get_edges(typename Edge::array_type &array,
528  typename Edge::index_type idx) const
529  { array.resize(1); array[0]= idx; }
530  void get_edges(typename Edge::array_type &array,
531  typename Face::index_type idx) const
532  { get_edges_from_face(array,idx); }
533  void get_edges(typename Edge::array_type &array,
534  typename Cell::index_type idx) const
535  { get_edges_from_cell(array,idx); }
536 
537  void get_faces(typename Face::array_type &array,
538  typename Node::index_type idx) const
539  { get_faces_from_node(array,idx); }
540  void get_faces(typename Face::array_type &array,
541  typename Edge::index_type idx) const
542  { get_faces_from_edge(array,idx); }
543 
544  void get_faces(typename Face::array_type &array,
545  typename Face::index_type idx) const
546  { array.resize(1); array[0]= idx; }
547  void get_faces(typename Face::array_type &array,
548  typename Cell::index_type idx) const
549  { get_faces_from_cell(array,idx); }
550 
551  void get_cells(typename Cell::array_type &array,
552  typename Node::index_type idx) const
553  { get_cells_from_node(array,idx); }
554  void get_cells(typename Cell::array_type &array,
555  typename Edge::index_type idx) const
556  { get_cells_from_edge(array,idx); }
557  void get_cells(typename Cell::array_type &array,
558  typename Face::index_type idx) const
559  { get_cells_from_face(array,idx); }
560  void get_cells(typename Cell::array_type &array,
561  typename Cell::index_type idx) const
562  { array.resize(1); array[0]= idx; }
563 
564  void get_elems(typename Elem::array_type &array,
565  typename Node::index_type idx) const
566  { get_cells_from_node(array,idx); }
567  void get_elems(typename Elem::array_type &array,
568  typename Edge::index_type idx) const
569  { get_cells_from_edge(array,idx); }
570  void get_elems(typename Elem::array_type &array,
571  typename Face::index_type idx) const
572  { get_cells_from_face(array,idx); }
573  void get_elems(typename Elem::array_type &array,
574  typename Cell::index_type idx) const
575  { array.resize(1); array[0]= idx; }
576 
577  void get_delems(typename DElem::array_type &array,
578  typename Node::index_type idx) const
579  { get_faces_from_node(array,idx); }
580  void get_delems(typename DElem::array_type &array,
581  typename Edge::index_type idx) const
582  { get_faces_from_edge(array,idx); }
583  void get_delems(typename DElem::array_type &array,
584  typename Face::index_type idx) const
585  { array.resize(1); array[0]= idx; }
586  void get_delems(typename DElem::array_type &array,
587  typename Cell::index_type idx) const
588  { get_faces_from_cell(array,idx); }
589 
590 
591  /// Generate the list of points that make up a sufficiently accurate
592  /// piecewise linear approximation of an edge.
593  template<class VECTOR, class INDEX>
594  void pwl_approx_edge(std::vector<VECTOR > &coords,
595  INDEX ci,
596  unsigned int which_edge,
597  unsigned int div_per_unit) const
598  {
599  basis_.approx_edge(which_edge, div_per_unit, coords);
600  }
601 
602  /// Generate the list of points that make up a sufficiently accurate
603  /// piecewise linear approximation of an face.
604  template<class VECTOR, class INDEX>
605  void pwl_approx_face(std::vector<std::vector<VECTOR > > &coords,
606  INDEX ci,
607  unsigned int which_face,
608  unsigned int div_per_unit) const
609  {
610  basis_.approx_face(which_face, div_per_unit, coords);
611  }
612 
613  /// get the center point (in object space) of an element
614  void get_center(Core::Geometry::Point &result, typename Node::index_type idx) const
615  { get_node_center(result,idx); }
616  void get_center(Core::Geometry::Point &result, typename Edge::index_type idx) const
617  { get_edge_center(result,idx); }
618  void get_center(Core::Geometry::Point &result, typename Face::index_type idx) const
619  { get_face_center(result,idx); }
620  void get_center(Core::Geometry::Point &result, typename Cell::index_type idx) const
621  { get_cell_center(result,idx); }
622 
623  /// Get the size of an element (length, area, volume)
624  double get_size(typename Node::index_type /*idx*/) const
625  { return 0.0; }
626 
627  double get_size(typename Edge::index_type idx) const
628  {
629  typename Node::array_type arr;
630  get_nodes(arr, idx);
631  Core::Geometry::Point p0, p1;
632  get_center(p0, arr[0]);
633  get_center(p1, arr[1]);
634  return ((p1 - p0).length());
635  }
636 
637  double get_size(typename Face::index_type idx) const
638  {
639  /// @todo: This code is incorrect need to create a better call in basis functions
640  // for doing this
641  typename Node::array_type ra;
642  get_nodes(ra,idx);
643  Core::Geometry::Point p0,p1,p2,p3;
644  get_point(p0,ra[0]);
645  get_point(p1,ra[1]);
646  get_point(p2,ra[2]);
647  get_point(p3,ra[3]);
648  return ((Cross(p0-p1,p2-p0)).length()+(Cross(p2-p3,p0-p2)).length())*0.5;
649  }
650 
651  double get_size(typename Cell::index_type idx) const
652  {
653  ElemData ed(*this,idx);
654  return (basis_.get_volume(ed));
655  }
656 
657  /// More specific names for get_size
658  double get_length(typename Edge::index_type idx) const
659  { return get_size(idx); };
660  double get_area(typename Face::index_type idx) const
661  { return get_size(idx); };
662  double get_volume(typename Cell::index_type idx) const
663  { return get_size(idx); };
664 
665  /// Get neighbors of an element or a node
666 
667  /// THIS ONE IS FLAWED AS IN 3D SPACE FOR AND ELEMENT TYPE THAT
668  /// IS NOT A VOLUME. HENCE IT WORKS HERE, BUT GENERALLY IT IS FLAWED
669  /// AS IT ASSUMES ONLY ONE NEIGHBOR, WHEREAS FOR ANYTHING ELSE THAN
670  /// A FACE THERE CAN BE MULTIPLE
671  bool get_neighbor(typename Elem::index_type &neighbor,
672  typename Elem::index_type elem,
673  typename DElem::index_type delem) const
674  { return(get_elem_neighbor(neighbor,elem,delem)); }
675 
676  /// These are more general neighbor functions
677  void get_neighbors(std::vector<typename Node::index_type> &array,
678  typename Node::index_type node) const
679  { get_node_neighbors(array,node); }
680  bool get_neighbors(std::vector<typename Elem::index_type> &array,
681  typename Elem::index_type elem,
682  typename DElem::index_type delem) const
683  { return(get_elem_neighbors(array,elem,delem)); }
684  void get_neighbors(typename Elem::array_type &array,
685  typename Elem::index_type elem) const
686  { get_elem_neighbors(array,elem); }
687 
688  /// Locate a point in a mesh, find which is the closest node
689  bool locate(typename Node::index_type &idx, const Core::Geometry::Point &p) const
690  { return (locate_node(idx,p)); }
691  bool locate(typename Edge::index_type &idx, const Core::Geometry::Point &p) const
692  { return (locate_edge(idx,p)); }
693  bool locate(typename Face::index_type &idx, const Core::Geometry::Point &p) const
694  { return (locate_face(idx,p)); }
695  bool locate(typename Cell::index_type &idx, const Core::Geometry::Point &p) const
696  { return (locate_elem(idx,p)); }
697 
698  bool locate(typename Elem::index_type &elem,
699  std::vector<double>& coords,
700  const Core::Geometry::Point &p) const
701  { return (locate_elem(elem,coords,p)); }
702 
703  /// These should become obsolete soon, they do not follow the concept
704  /// of the basis functions....
705  int get_weights(const Core::Geometry::Point &p, typename Node::array_type &l, double *w) const;
706  int get_weights(const Core::Geometry::Point&, typename Edge::array_type&, double* ) const
707  { ASSERTFAIL("HexVolMesh: get_weights for edges isn't supported"); }
708  int get_weights(const Core::Geometry::Point&, typename Face::array_type&, double* ) const
709  { ASSERTFAIL("HexVolMesh: get_weights for faces isn't supported"); }
710  int get_weights(const Core::Geometry::Point &p, typename Cell::array_type &l, double *w) const;
711 
712  /// Access the nodes of the mesh
713  void get_point(Core::Geometry::Point &result, typename Node::index_type index) const
714  { result = points_[index]; }
716  { points_[index] = point; }
717  void get_random_point(Core::Geometry::Point &p, typename Elem::index_type i, FieldRNG &r) const;
718 
719  /// Normals for visualizations
720  void get_normal(Core::Geometry::Vector& /*result*/, typename Node::index_type /*index*/) const
721  { ASSERTFAIL("HexVolMesh: this mesh type does not have node normals."); }
722 
723  /// Get the normals at the outside of the element
724  template<class VECTOR, class INDEX1, class INDEX2>
725  void get_normal(Core::Geometry::Vector &result, VECTOR &coords,
726  INDEX1 eidx, INDEX2 fidx) const
727  {
728  // Improved algorithm, which should be faster as it is fully
729  // on the stack.
730  unsigned int fmap[] = {0, 5, 1, 3, 4, 2};
731  unsigned int face = fmap[fidx];
732 
733  // Obtain the inverse jacobian
734  double Ji[9];
735  inverse_jacobian(coords,eidx,Ji);
736 
737  // Get the normal in local coordinates
738  const double un0 = basis_.unit_face_normals[face][0];
739  const double un1 = basis_.unit_face_normals[face][1];
740  const double un2 = basis_.unit_face_normals[face][2];
741  // Do the matrix multiplication: should result in a vector
742  // in the global coordinate space
743  result.x(Ji[0]*un0+Ji[1]*un1+Ji[2]*un2);
744  result.y(Ji[3]*un0+Ji[4]*un1+Ji[5]*un2);
745  result.z(Ji[6]*un0+Ji[7]*un1+Ji[8]*un2);
746 
747  // normalize vector
748  result.normalize();
749  }
750 
751  /// Add a new node to the mesh
754  { return(add_point(p)); }
755 
756  /// Add a new element to the mesh
757  template<class ARRAY>
758  typename Elem::index_type add_elem(ARRAY a)
759  {
760  ASSERTMSG(a.size() == 8, "Tried to add non-hex element.");
761 
762  return add_hex( static_cast<typename Node::index_type>(a[0]),
763  static_cast<typename Node::index_type>(a[1]),
764  static_cast<typename Node::index_type>(a[2]),
765  static_cast<typename Node::index_type>(a[3]),
766  static_cast<typename Node::index_type>(a[4]),
767  static_cast<typename Node::index_type>(a[5]),
768  static_cast<typename Node::index_type>(a[6]),
769  static_cast<typename Node::index_type>(a[7]) );
770  }
771 
772  /// Functions to improve memory management. Often one knows how many
773  /// nodes/elements one needs, prereserving memory is often possible.
775  void elem_reserve(size_type s) { cells_.reserve(static_cast<std::vector<index_type>::size_type>(s*8)); }
777  void resize_elems(size_type s) { cells_.resize(static_cast<std::vector<index_type>::size_type>(s*8)); }
778 
779  /// Get the local coordinates for a certain point within an element
780  /// This function uses a couple of newton iterations to find the local
781  /// coordinate of a point
782  template<class VECTOR, class INDEX>
783  bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, INDEX idx) const
784  {
785  ElemData ed(*this, idx);
786  return basis_.get_coords(coords, p, ed);
787  }
788 
789  /// Find the location in the global coordinate system for a local coordinate
790  /// This function is the opposite of get_coords.
791  template<class VECTOR, class INDEX>
792  void interpolate(Core::Geometry::Point &pt, const VECTOR &coords, INDEX idx) const
793  {
794  ElemData ed(*this, idx);
795  pt = basis_.interpolate(coords, ed);
796  }
797 
798  /// Interpolate the derivate of the function, This infact will return the
799  /// jacobian of the local to global coordinate transformation. This function
800  /// is mainly intended for the non linear elements
801  template<class VECTOR1, class INDEX, class VECTOR2>
802  void derivate(const VECTOR1 &coords, INDEX idx, VECTOR2 &J) const
803  {
804  ElemData ed(*this, idx);
805  basis_.derivate(coords, ed, J);
806  }
807 
808  /// Get the determinant of the jacobian, which is the local volume of an element
809  /// and is intended to help with the integration of functions over an element.
810  template<class VECTOR, class INDEX>
811  double det_jacobian(const VECTOR& coords, INDEX idx) const
812  {
814  ElemData ed(*this,idx);
815  basis_.derivate(coords,ed,Jv);
816  return (DetMatrix3P(Jv));
817  }
818 
819  /// Get the jacobian of the transformation. In case one wants the non inverted
820  /// version of this matrix. This is currentl here for completeness of the
821  /// interface
822  template<class VECTOR, class INDEX>
823  void jacobian(const VECTOR& coords, INDEX idx, double* J) const
824  {
826  ElemData ed(*this,idx);
827  basis_.derivate(coords,ed,Jv);
828  J[0] = Jv[0].x();
829  J[1] = Jv[0].y();
830  J[2] = Jv[0].z();
831  J[3] = Jv[1].x();
832  J[4] = Jv[1].y();
833  J[5] = Jv[1].z();
834  J[6] = Jv[2].x();
835  J[7] = Jv[2].y();
836  J[8] = Jv[2].z();
837  }
838 
839  /// Get the inverse jacobian of the transformation. This one is needed to
840  /// translate local gradients into global gradients. Hence it is crucial for
841  /// calculating gradients of fields, or constructing finite elements.
842  template<class VECTOR, class INDEX>
843  double inverse_jacobian(const VECTOR& coords, INDEX idx, double* Ji) const
844  {
846  ElemData ed(*this,idx);
847  basis_.derivate(coords,ed,Jv);
848  return (InverseMatrix3P(Jv,Ji));
849  }
850 
851  template<class INDEX>
852  double scaled_jacobian_metric(INDEX idx) const
853  {
855  ElemData ed(*this,idx);
856 
857  double temp;
858 
859  basis_.derivate(basis_.unit_center,ed,Jv);
860  double min_jacobian = ScaledDetMatrix3P(Jv);
861 
862  size_type num_vertices = static_cast<size_type>(basis_.number_of_vertices());
863  for (size_type j=0;j < num_vertices;j++)
864  {
865  basis_.derivate(basis_.unit_vertices[j],ed,Jv);
866  temp = ScaledDetMatrix3P(Jv);
867  if(temp < min_jacobian) min_jacobian = temp;
868  }
869 
870  return (min_jacobian);
871  }
872 
873  template<class INDEX>
874  double jacobian_metric(INDEX idx) const
875  {
877  ElemData ed(*this,idx);
878 
879  double temp;
880 
881  basis_.derivate(basis_.unit_center,ed,Jv);
882  double min_jacobian = DetMatrix3P(Jv);
883 
884  size_type num_vertices = static_cast<size_type>(basis_.number_of_vertices());
885  for (size_type j=0;j < num_vertices;j++)
886  {
887  basis_.derivate(basis_.unit_vertices[j],ed,Jv);
888  temp = DetMatrix3P(Jv);
889  if(temp < min_jacobian) min_jacobian = temp;
890  }
891 
892  return (min_jacobian);
893  }
894 
895  template <class INDEX>
896  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
897  INDEX &node, const Core::Geometry::Point &p) const
898  {
899  return (find_closest_node(pdist,result,node,p,-1.0));
900  }
901 
902  template <class INDEX>
903  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
904  INDEX &node, const Core::Geometry::Point &p, double maxdist) const
905  {
906  if (maxdist < 0.0) maxdist = DBL_MAX; else maxdist = maxdist*maxdist;
907  typename Node::size_type sz; size(sz);
908 
909  /// If there are no nodes we cannot find the closest one
910  if (sz == 0) return (false);
911 
912  if (node >= 0 && node < sz)
913  {
915  double dist = (point-p).length2();
916 
917  if ( dist < epsilon2_ )
918  {
919  result = point;
920  pdist = sqrt(dist);
921  return (true);
922  }
923  }
924 
926  "HexVolMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
927 
928  // get grid sizes
929  const size_type ni = node_grid_->get_ni()-1;
930  const size_type nj = node_grid_->get_nj()-1;
931  const size_type nk = node_grid_->get_nk()-1;
932 
933  // Convert to grid coordinates.
934  index_type bi, bj, bk, ei, ej, ek;
935  node_grid_->unsafe_locate(bi, bj, bk, p);
936 
937  // Clamp to closest point on the grid.
938  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
939  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
940  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
941 
942  ei = bi; ej = bj; ek = bk;
943 
944  double dmin = maxdist;
945  bool found_one = false;
946  bool found = true;
947  do
948  {
949  found = true;
950  /// We need to do a full shell without any elements that are closer
951  /// to make sure there no closer elements in neighboring searchgrid cells
952 
953  for (index_type i = bi; i <= ei; i++)
954  {
955  if (i < 0 || i > ni) continue;
956  for (index_type j = bj; j <= ej; j++)
957  {
958  if (j < 0 || j > nj) continue;
959  for (index_type k = bk; k <= ek; k++)
960  {
961  if (k < 0 || k > nk) continue;
962  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
963  {
964  if (node_grid_->min_distance_squared(p, i, j, k) < dmin)
965  {
966  typename SearchGridT<index_type>::iterator it, eit;
967  found = false;
968  node_grid_->lookup_ijk(it,eit, i, j, k);
969 
970  while (it != eit)
971  {
972  const Core::Geometry::Point point = points_[*it];
973  const double dist = (p-point).length2();
974 
975  if (dist < dmin)
976  {
977  found_one = true;
978  result = point;
979  node = INDEX(*it);
980  dmin = dist;
981  /// If we are closer than eps^2 we found a node close enough
982  if (dmin < epsilon2_)
983  {
984  pdist = sqrt(dmin);
985  return (true);
986  }
987  }
988  ++it;
989  }
990  }
991  }
992  }
993  }
994  }
995  bi--;ei++;
996  bj--;ej++;
997  bk--;ek++;
998  }
999  while (!found) ;
1000 
1001  if (!found_one) return (false);
1002 
1003  pdist = sqrt(dmin);
1004  return (true);
1005  }
1006 
1007  template <class ARRAY>
1008  bool find_closest_nodes(ARRAY &nodes, const Core::Geometry::Point &p, double maxdist) const
1009  {
1010  nodes.clear();
1011 
1013  "HexVolMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
1014 
1015  // get grid sizes
1016  const size_type ni = node_grid_->get_ni()-1;
1017  const size_type nj = node_grid_->get_nj()-1;
1018  const size_type nk = node_grid_->get_nk()-1;
1019 
1020  // Convert to grid coordinates.
1021  index_type bi, bj, bk, ei, ej, ek;
1022 
1023  Core::Geometry::Point max = p+Core::Geometry::Vector(maxdist,maxdist,maxdist);
1024  Core::Geometry::Point min = p+Core::Geometry::Vector(-maxdist,-maxdist,-maxdist);
1025 
1026  node_grid_->unsafe_locate(bi, bj, bk, min);
1027  node_grid_->unsafe_locate(ei, ej, ek, max);
1028 
1029  // Clamp to closest point on the grid.
1030  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
1031  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
1032  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
1033 
1034  if (ei > ni) ei = ni; if (ei < 0) ei = 0;
1035  if (ej > nj) ej = nj; if (ej < 0) ej = 0;
1036  if (ek > nk) ek = nk; if (ek < 0) ek = 0;
1037 
1038  double maxdist2 = maxdist*maxdist;
1039 
1040  for (index_type i = bi; i <= ei; i++)
1041  {
1042  for (index_type j = bj; j <= ej; j++)
1043  {
1044  for (index_type k = bk; k <= ek; k++)
1045  {
1046  if (node_grid_->min_distance_squared(p, i, j, k) < maxdist2)
1047  {
1048  typename SearchGridT<index_type>::iterator it, eit;
1049  node_grid_->lookup_ijk(it, eit, i, j, k);
1050 
1051  while (it != eit)
1052  {
1053  const Core::Geometry::Point point = points_[*it];
1054  const double dist = (p-point).length2();
1055 
1056  if (dist < maxdist2)
1057  {
1058  nodes.push_back(*it);
1059  }
1060  ++it;
1061  }
1062  }
1063  }
1064  }
1065  }
1066 
1067  return(nodes.size() > 0);
1068  }
1069 
1070 
1071  template <class ARRAY1, class ARRAY2>
1072  bool find_closest_nodes(ARRAY1 &distances, ARRAY2 &nodes, const Core::Geometry::Point &p, double maxdist) const
1073  {
1074  nodes.clear();
1075  distances.clear();
1076 
1078  "HexVolMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
1079 
1080  // get grid sizes
1081  const size_type ni = node_grid_->get_ni()-1;
1082  const size_type nj = node_grid_->get_nj()-1;
1083  const size_type nk = node_grid_->get_nk()-1;
1084 
1085  // Convert to grid coordinates.
1086  index_type bi, bj, bk, ei, ej, ek;
1087 
1088  Core::Geometry::Point max = p+Core::Geometry::Vector(maxdist,maxdist,maxdist);
1089  Core::Geometry::Point min = p+Core::Geometry::Vector(-maxdist,-maxdist,-maxdist);
1090 
1091  node_grid_->unsafe_locate(bi, bj, bk, min);
1092  node_grid_->unsafe_locate(ei, ej, ek, max);
1093 
1094  // Clamp to closest point on the grid.
1095  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
1096  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
1097  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
1098 
1099  if (ei > ni) ei = ni; if (ei < 0) ei = 0;
1100  if (ej > nj) ej = nj; if (ej < 0) ej = 0;
1101  if (ek > nk) ek = nk; if (ek < 0) ek = 0;
1102 
1103  double maxdist2 = maxdist*maxdist;
1104 
1105  for (index_type i = bi; i <= ei; i++)
1106  {
1107  for (index_type j = bj; j <= ej; j++)
1108  {
1109  for (index_type k = bk; k <= ek; k++)
1110  {
1111  if (node_grid_->min_distance_squared(p, i, j, k) < maxdist2)
1112  {
1113  typename SearchGridT<index_type>::iterator it, eit;
1114  node_grid_->lookup_ijk(it, eit, i, j, k);
1115 
1116  while (it != eit)
1117  {
1118  const Core::Geometry::Point point = points_[*it];
1119  const double dist = (p-point).length2();
1120 
1121  if (dist < maxdist2)
1122  {
1123  nodes.push_back(*it);
1124  distances.push_back(dist);
1125  }
1126  ++it;
1127  }
1128  }
1129  }
1130  }
1131  }
1132 
1133  return(nodes.size() > 0);
1134  }
1135 
1136 
1137 
1138  /// Find the closest element to a point
1139  template <class INDEX, class ARRAY>
1140  bool find_closest_elem(double& pdist,
1141  Core::Geometry::Point &result,
1142  ARRAY &coords,
1143  INDEX &elem,
1144  const Core::Geometry::Point &p) const
1145  {
1146  return(find_closest_elem(pdist,result,coords,elem,p,-1.0));
1147  }
1148 
1149  /// Find the closest element to a point
1150  template <class INDEX, class ARRAY>
1151  bool find_closest_elem(double& pdist,
1152  Core::Geometry::Point &result,
1153  ARRAY &coords,
1154  INDEX &elem,
1155  const Core::Geometry::Point &p,
1156  double maxdist) const
1157  {
1158  if (maxdist < 0.0) maxdist = DBL_MAX; else maxdist = maxdist*maxdist;
1159  typename Elem::size_type sz; size(sz);
1160 
1161  /// If there are no nodes we cannot find a closest point
1162  if (sz == 0) return (false);
1163 
1164  /// Check whether the estimate given in idx is the point we are looking for
1165  if ((elem > 0)&&(elem < sz))
1166  {
1167  if (inside(elem,p))
1168  {
1169  ElemData ed(*this, elem);
1170  basis_.get_coords(coords, p, ed);
1171  result = p;
1172  pdist = 0.0;
1173  return (true);
1174  }
1175  }
1176 
1178  "HexVolMesh: need to synchronize ELEM_LOCATE_E first");
1180  "HexVolMesh: need to synchronize FACES_E first");
1181 
1182  // First check are we inside an element
1183  typename SearchGridT<index_type>::iterator it, eit;
1184  if (elem_grid_->lookup(it, eit, p))
1185  {
1186  while (it != eit)
1187  {
1188  if (inside(typename Elem::index_type(*it), p))
1189  {
1190  pdist = 0.0;
1191  result = p;
1192  elem = static_cast<INDEX>(*it);
1193  ElemData ed(*this, elem);
1194  basis_.get_coords(coords, p, ed);
1195  return (true);
1196  }
1197  ++it;
1198  }
1199  }
1200 
1201  // If not start searching for the closest outer boundary
1202  // get grid sizes
1203  const size_type ni = elem_grid_->get_ni()-1;
1204  const size_type nj = elem_grid_->get_nj()-1;
1205  const size_type nk = elem_grid_->get_nk()-1;
1206 
1207  // Convert to grid coordinates.
1208  index_type bi, ei, bj, ej, bk, ek;
1209  elem_grid_->unsafe_locate(bi, bj, bk, p);
1210 
1211  // Clamp to closest point on the grid.
1212  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
1213  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
1214  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
1215 
1216  ei = bi; ej = bj; ek = bk;
1217 
1218  double dmin = maxdist;
1219  bool found = true;
1220  bool found_one = false;
1221 
1222  do
1223  {
1224  found = true;
1225  /// We need to do a full shell without any elements that are closer
1226  /// to make sure there no closer elements in neighboring searchgrid cells
1227  for (index_type i = bi; i <= ei; i++)
1228  {
1229  if (i < 0 || i > ni) continue;
1230  for (index_type j = bj; j <= ej; j++)
1231  {
1232  if (j < 0 || j > nj) continue;
1233  for (index_type k = bk; k <= ek; k++)
1234  {
1235  if (k < 0 || k > nk) continue;
1236  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
1237  {
1238  if (elem_grid_->min_distance_squared(p, i, j, k) < dmin)
1239  {
1240  found = false;
1241  typename SearchGridT<index_type>::iterator it, eit;
1242  elem_grid_->lookup_ijk(it,eit, i, j, k);
1243 
1244  while (it != eit)
1245  {
1247  index_type cidx = (*it);
1248  index_type idx = cidx*8;
1249  unsigned char b = boundary_faces_[cidx];
1250  if (b)
1251  {
1252  if (b & 0x1)
1253  {
1255  points_[cells_[idx ]],
1256  points_[cells_[idx+1]],
1257  points_[cells_[idx+2]],
1258  points_[cells_[idx+3]]);
1259  const double dtmp = (p - r).length2();
1260  if (dtmp < dmin)
1261  {
1262  found_one = true;
1263  result = r;
1264  elem = INDEX(cidx);
1265  dmin = dtmp;
1266 
1267  if (dmin < epsilon2_)
1268  {
1269  ElemData ed(*this,elem);
1270  basis_.get_coords(coords,result,ed);
1271 
1272  result = basis_.interpolate(coords,ed);
1273  double dmin = (result-p).length2();
1274  pdist = sqrt(dmin);
1275  return (true);
1276  }
1277  }
1278  }
1279  if (b & 0x2)
1280  {
1282  points_[cells_[idx+7]],
1283  points_[cells_[idx+6]],
1284  points_[cells_[idx+5]],
1285  points_[cells_[idx+4]]);
1286  const double dtmp = (p - r).length2();
1287  if (dtmp < dmin)
1288  {
1289  found_one = true;
1290  result = r;
1291  elem = INDEX(cidx);
1292  dmin = dtmp;
1293 
1294  if (dmin < epsilon2_)
1295  {
1296  ElemData ed(*this,elem);
1297  basis_.get_coords(coords,result,ed);
1298 
1299  result = basis_.interpolate(coords,ed);
1300  double dmin = (result-p).length2();
1301  pdist = sqrt(dmin);
1302  return (true);
1303  }
1304  }
1305  }
1306  if (b & 0x4)
1307  {
1309  points_[cells_[idx ]],
1310  points_[cells_[idx+4]],
1311  points_[cells_[idx+5]],
1312  points_[cells_[idx+1]]);
1313  const double dtmp = (p - r).length2();
1314  if (dtmp < dmin)
1315  {
1316  found_one = true;
1317  result = r;
1318  elem = INDEX(cidx);
1319  dmin = dtmp;
1320 
1321  if (dmin < epsilon2_)
1322  {
1323  ElemData ed(*this,elem);
1324  basis_.get_coords(coords,result,ed);
1325 
1326  result = basis_.interpolate(coords,ed);
1327  double dmin = (result-p).length2();
1328  pdist = sqrt(dmin);
1329  return (true);
1330  }
1331  }
1332  }
1333  if (b & 0x8)
1334  {
1336  points_[cells_[idx+2]],
1337  points_[cells_[idx+6]],
1338  points_[cells_[idx+7]],
1339  points_[cells_[idx+3]]);
1340  const double dtmp = (p - r).length2();
1341  if (dtmp < dmin)
1342  {
1343  found_one = true;
1344  result = r;
1345  elem = INDEX(cidx);
1346  dmin = dtmp;
1347 
1348  if (dmin < epsilon2_)
1349  {
1350  ElemData ed(*this,elem);
1351  basis_.get_coords(coords,result,ed);
1352 
1353  result = basis_.interpolate(coords,ed);
1354  double dmin = (result-p).length2();
1355  pdist = sqrt(dmin);
1356  return (true);
1357  }
1358  }
1359  }
1360  if (b & 0x10)
1361  {
1363  points_[cells_[idx+3]],
1364  points_[cells_[idx+7]],
1365  points_[cells_[idx+4]],
1366  points_[cells_[idx]]);
1367  const double dtmp = (p - r).length2();
1368  if (dtmp < dmin)
1369  {
1370  found_one = true;
1371  result = r;
1372  elem = INDEX(cidx);
1373  dmin = dtmp;
1374 
1375  if (dmin < epsilon2_)
1376  {
1377  ElemData ed(*this,elem);
1378  basis_.get_coords(coords,result,ed);
1379 
1380  result = basis_.interpolate(coords,ed);
1381  double dmin = (result-p).length2();
1382  pdist = sqrt(dmin);
1383  return (true);
1384  }
1385  }
1386  }
1387  if (b & 0x20)
1388  {
1390  points_[cells_[idx+1]],
1391  points_[cells_[idx+5]],
1392  points_[cells_[idx+6]],
1393  points_[cells_[idx+2]]);
1394  const double dtmp = (p - r).length2();
1395  if (dtmp < dmin)
1396  {
1397  found_one = true;
1398  result = r;
1399  elem = INDEX(cidx);
1400  dmin = dtmp;
1401 
1402  if (dmin < epsilon2_)
1403  {
1404  ElemData ed(*this,elem);
1405  basis_.get_coords(coords,result,ed);
1406 
1407  result = basis_.interpolate(coords,ed);
1408  double dmin = (result-p).length2();
1409  pdist = sqrt(dmin);
1410  return (true);
1411  }
1412  }
1413  }
1414 
1415  }
1416  ++it;
1417  }
1418  }
1419  }
1420  }
1421  }
1422  }
1423  bi--;ei++;
1424  bj--;ej++;
1425  bk--;ek++;
1426  }
1427  while (!found) ;
1428 
1429  if (!found_one) return (false);
1430 
1431  ElemData ed(*this,elem);
1432  basis_.get_coords(coords,result,ed);
1433 
1434  result = basis_.interpolate(coords,ed);
1435  dmin = (result-p).length2();
1436  pdist = sqrt(dmin);
1437  return (true);
1438  }
1439 
1440  template <class INDEX>
1441  bool find_closest_elem(double& pdist, Core::Geometry::Point &result,
1442  INDEX &elem, const Core::Geometry::Point &p) const
1443  {
1444  StackVector<double,3> coords;
1445  return(find_closest_elem(pdist,result,coords,elem,p,-1.0));
1446  }
1447 
1448  /// Find the closest elements to a point
1449  template<class ARRAY>
1450  bool find_closest_elems(double& /*pdist*/, Core::Geometry::Point& /*result*/,
1451  ARRAY& /*faces*/, const Core::Geometry::Point& /*p*/) const
1452  {
1453  ASSERTFAIL("HexVolMesh: Find closest element has not yet been implemented.");
1454  return (false);
1455  }
1456 
1457  /// Export this class using the old Pio system
1458  virtual void io(Piostream&);
1459 
1460  ///////////////////////////////////////////////////
1461  // STATIC VARIABLES AND FUNCTIONS
1462 
1463  /// These IDs are created as soon as this class will be instantiated
1465 
1466  /// Core functionality for getting the name of a templated mesh class
1467  static const std::string type_name(int n = -1);
1468  virtual std::string dynamic_type_name() const { return hexvolmesh_typeid.type; }
1469 
1470  /// Type description, used for finding names of the mesh class for
1471  /// dynamic compilation purposes. Some of this should be obsolete
1472  /// Persistent IO
1473  virtual const TypeDescription *get_type_description() const;
1474  static const TypeDescription* node_type_description();
1475  static const TypeDescription* edge_type_description();
1476  static const TypeDescription* face_type_description();
1477  static const TypeDescription* cell_type_description();
1479  { return cell_type_description(); }
1480 
1481  /// This function returns a maker for Pio.
1482  static Persistent* maker() { return new HexVolMesh<Basis>; }
1483  /// This function returns a handle for the virtual interface.
1484  static MeshHandle mesh_maker() { return boost::make_shared<HexVolMesh<Basis>>(); }
1485 
1486  //////////////////////////////////////////////////////////////////
1487  // Mesh specific functions (these are not implemented in every mesh)
1488 
1489  /// Trying figure out which face is made out of 4 nodes (?)
1490  bool get_face(typename Face::index_type &array,
1491  typename Node::index_type n1,
1492  typename Node::index_type n2,
1493  typename Node::index_type n3,
1494  typename Node::index_type n4) const;
1495 
1496  /// Functions for Cubit
1497  /// WE SHOULD MAKE THESE GENERAL AND IN EVERY MESHTYPE
1498  template <class Iter, class Functor>
1499  void fill_points(Iter begin, Iter end, Functor fill_ftor);
1500  template <class Iter, class Functor>
1501  void fill_cells(Iter begin, Iter end, Functor fill_ftor);
1502  template <class Iter, class Functor>
1503  void fill_neighbors(Iter begin, Iter end, Functor fill_ftor);
1504  template <class Iter, class Functor>
1505  void fill_data(Iter begin, Iter end, Functor fill_ftor);
1506 
1507  // THIS FUNCTION NEEDS TO BE REVISED AS IT DOES NOT SCALE PROPERLY
1508  // THE TOLERANCE IS NOT RELATIVE, WHICH IS A PROBLEM.........
1510  double err = 1.0e-6);
1511 
1512  // Short cut for generating an element....
1513  typename Elem::index_type add_hex(typename Node::index_type a, typename Node::index_type b,
1514  typename Node::index_type c, typename Node::index_type d,
1515  typename Node::index_type e, typename Node::index_type f,
1516  typename Node::index_type g, typename Node::index_type h);
1517 
1519  const Core::Geometry::Point &p3, const Core::Geometry::Point &p4, const Core::Geometry::Point &p5,
1520  const Core::Geometry::Point &p6, const Core::Geometry::Point &p7);
1521 
1522  /// must detach, if altering points!
1523  std::vector<Core::Geometry::Point>& get_points() { return points_; }
1524 
1525  int compute_checksum();
1526 
1527 protected:
1528  //////////////////////////////////////////////////////////////
1529  // These functions are templates and are used to define the
1530  // dynamic compilation interface and the virtual interface
1531  // as they both use different datatypes as indices and arrays
1532  // the following functions have been templated and are inlined
1533  // at the places where they are needed.
1534  //
1535  // Secondly these templates allow for the use of the stack vector
1536  // as well as the STL vector. When an algorithm supports non linear
1537  // functions an STL vector is a better choice, in the other cases
1538  // often a StackVector is enough (The latter improves performance).
1539 
1540  template<class ARRAY, class INDEX>
1541  inline void get_nodes_from_edge(ARRAY& array, INDEX idx) const
1542  {
1544  "HexVolMesh: Must call synchronize EDGES_E first");
1545 
1546  if (edges_[idx].cells_.size() == 0)
1547  { array.clear(); return; }
1548 
1549  array.resize(2);
1550 
1551  index_type cell_edge_index = edges_[idx].cells_[0];
1552  index_type cell_index = (cell_edge_index>>4) << 3;
1553  index_type edge_index = (cell_edge_index)&0xF;
1554 
1555  const int *offset = HexVolEdgeTable[edge_index];
1556  array[0] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[0]]);
1557  array[1] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[1]]);
1558  }
1559 
1560  // Always returns nodes in counter-clockwise order
1561  template<class ARRAY, class INDEX>
1562  inline void get_nodes_from_face(ARRAY& array, INDEX idx) const
1563  {
1565  "HexVolMesh: Must call synchronize FACES_E first");
1566 
1567  if (faces_[idx].cells_[0] == MESH_NO_NEIGHBOR)
1568  { array.clear(); return; }
1569 
1570  index_type cell_face_index = faces_[idx].cells_[0];
1571  index_type cell_index = cell_face_index&(~0x7);
1572  index_type face_index = cell_face_index&0x7;
1573 
1574  array.resize(4);
1575 
1576  const int *offset = HexVolFaceTable[face_index];
1577  array[0] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[0]]);
1578  array[1] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[1]]);
1579  array[2] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[2]]);
1580  array[3] = static_cast<typename ARRAY::value_type>(cells_[cell_index+offset[3]]);
1581 
1582  order_face_nodes(array[0],array[1],array[2],array[3]);
1583  }
1584 
1585  template<class ARRAY, class INDEX>
1586  inline void get_nodes_from_cell(ARRAY& array, INDEX idx) const
1587  {
1588  array.resize(8);
1589  const index_type off = idx * 8;
1590  array[0] = static_cast<typename ARRAY::value_type>(cells_[off]);
1591  array[1] = static_cast<typename ARRAY::value_type>(cells_[off + 1]);
1592  array[2] = static_cast<typename ARRAY::value_type>(cells_[off + 2]);
1593  array[3] = static_cast<typename ARRAY::value_type>(cells_[off + 3]);
1594  array[4] = static_cast<typename ARRAY::value_type>(cells_[off + 4]);
1595  array[5] = static_cast<typename ARRAY::value_type>(cells_[off + 5]);
1596  array[6] = static_cast<typename ARRAY::value_type>(cells_[off + 6]);
1597  array[7] = static_cast<typename ARRAY::value_type>(cells_[off + 7]);
1598  }
1599 
1600  template<class ARRAY, class INDEX>
1601  inline void get_nodes_from_elem(ARRAY& array, INDEX idx) const
1602  {
1603  get_nodes_from_cell(array,idx);
1604  }
1605 
1606  template<class ARRAY, class INDEX>
1607  inline void get_edges_from_face(ARRAY& array, INDEX idx) const
1608  {
1610  "HexVolMesh: Must call synchronize FACES_E first");
1612  "HexVolMesh: Must call synchronize EDGES_E first");
1613 
1614 
1615  array.clear();
1616  array.reserve(4);
1617  const PFaceCell &f = faces_[idx];
1618  if (f.cells_[0] == MESH_NO_NEIGHBOR) return;
1619 
1620  index_type cell_index = f.cells_[0]&(~0x7);
1621  int face_index = f.cells_[0]&0x7;
1622  const int* offset = HexVolFaceTable[face_index];
1623 
1624  typename Node::index_type n0 = cells_[cell_index+offset[0]];
1625  typename Node::index_type n1 = cells_[cell_index+offset[1]];
1626  typename Node::index_type n2 = cells_[cell_index+offset[2]];
1627  typename Node::index_type n3 = cells_[cell_index+offset[3]];
1628 
1629  if (n0 != n1)
1630  {
1631  PEdgeNode e(n0, n1);
1632  array.push_back(static_cast<typename ARRAY::value_type>(
1633  (*(edge_table_.find(e))).second));
1634  }
1635  if (n1 != n2)
1636  {
1637  PEdgeNode e(n1, n2);
1638  array.push_back(static_cast<typename ARRAY::value_type>(
1639  (*(edge_table_.find(e))).second));
1640  }
1641  if (n2 != n3)
1642  {
1643  PEdgeNode e(n2, n3);
1644  array.push_back(static_cast<typename ARRAY::value_type>(
1645  (*(edge_table_.find(e))).second));
1646  }
1647  if (n3 != n0)
1648  {
1649  PEdgeNode e(n3, n0);
1650  array.push_back(static_cast<typename ARRAY::value_type>(
1651  (*(edge_table_.find(e))).second));
1652  }
1653  }
1654 
1655  template<class ARRAY, class INDEX>
1656  inline void get_edges_from_cell(ARRAY& array, INDEX idx) const
1657  {
1659  "HexVolMesh: Must call synchronize EDGES_E first");
1660 
1661  array.clear();
1662  //array.reserve(12);
1663  const index_type off = idx * 8;
1664  typename Node::index_type n1,n2;
1665 
1666  int i = 0;
1667  n1 = cells_[off ]; n2 = cells_[off + 1];
1668  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1669  n1 = cells_[off + 1]; n2 = cells_[off + 2];
1670  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1671  n1 = cells_[off + 2]; n2 = cells_[off + 3];
1672  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1673  n1 = cells_[off + 3]; n2 = cells_[off ];
1674  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1675 
1676  n1 = cells_[off + 4]; n2 = cells_[off + 5];
1677  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1678  n1 = cells_[off + 5]; n2 = cells_[off + 6];
1679  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1680  n1 = cells_[off + 6]; n2 = cells_[off + 7];
1681  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1682  n1 = cells_[off + 7]; n2 = cells_[off + 4];
1683  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1684 
1685  n1 = cells_[off ]; n2 = cells_[off + 4];
1686  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1687  n1 = cells_[off + 5]; n2 = cells_[off + 1];
1688  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1689  n1 = cells_[off + 2]; n2 = cells_[off + 6];
1690  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1691  n1 = cells_[off + 7]; n2 = cells_[off + 3];
1692  if (n1 != n2) { PEdgeNode e(n1,n2); array[i++] = static_cast<typename ARRAY::value_type>(edge_table_.find(e)->second); }
1693  }
1694 
1695  template<class ARRAY, class INDEX>
1696  inline void get_edges_from_elem(ARRAY& array, INDEX idx) const
1697  {
1698  get_edges_from_cell(array,idx);
1699  }
1700 
1701  template<class ARRAY, class INDEX>
1702  inline void get_faces_from_cell(ARRAY& array, INDEX idx) const
1703  {
1705  "HexVolMesh: Must call synchronize FACES_E first");
1706 
1707  array.clear();
1708  array.reserve(8);
1709 
1710  const index_type off = idx * 8;
1711  typename Node::index_type n1,n2,n3,n4;
1712 
1713  // Put faces in node ordering from smallest node and then following CW or CCW
1714  // ordering. Test for degenerate elements. Degenerate faces are only added if they
1715  // are valid (only two neighboring nodes are equal)
1716  n1 = cells_[off ]; n2 = cells_[off + 1];
1717  n3 = cells_[off + 2]; n4 = cells_[off + 3];
1718  if (order_face_nodes(n1,n2,n3,n4))
1719  {
1720  PFaceNode f(n1,n2,n3,n4);
1721  array.push_back(static_cast<typename ARRAY::value_type>(
1722  (*(face_table_.find(f))).second));
1723  }
1724  n1 = cells_[off + 7]; n2 = cells_[off + 6];
1725  n3 = cells_[off + 5]; n4 = cells_[off + 4];
1726  if (order_face_nodes(n1,n2,n3,n4))
1727  {
1728  PFaceNode f(n1,n2,n3,n4);
1729  array.push_back(static_cast<typename ARRAY::value_type>(
1730  (*(face_table_.find(f))).second));
1731  }
1732  n1 = cells_[off ]; n2 = cells_[off + 4];
1733  n3 = cells_[off + 5]; n4 = cells_[off + 1];
1734  if (order_face_nodes(n1,n2,n3,n4))
1735  {
1736  PFaceNode f(n1,n2,n3,n4);
1737  array.push_back(static_cast<typename ARRAY::value_type>(
1738  (*(face_table_.find(f))).second));
1739  }
1740  n1 = cells_[off + 2]; n2 = cells_[off + 6];
1741  n3 = cells_[off + 7]; n4 = cells_[off + 3];
1742  if (order_face_nodes(n1,n2,n3,n4))
1743  {
1744  PFaceNode f(n1,n2,n3,n4);
1745  array.push_back(static_cast<typename ARRAY::value_type>(
1746  (*(face_table_.find(f))).second));
1747  }
1748  n1 = cells_[off + 3]; n2 = cells_[off + 7];
1749  n3 = cells_[off + 4]; n4 = cells_[off ];
1750  if (order_face_nodes(n1,n2,n3,n4))
1751  {
1752  PFaceNode f(n1,n2,n3,n4);
1753  array.push_back(static_cast<typename ARRAY::value_type>(
1754  (*(face_table_.find(f))).second));
1755  }
1756  n1 = cells_[off + 1]; n2 = cells_[off + 5];
1757  n3 = cells_[off + 6]; n4 = cells_[off + 2];
1758  if (order_face_nodes(n1,n2,n3,n4))
1759  {
1760  PFaceNode f(n1,n2,n3,n4);
1761  array.push_back(static_cast<typename ARRAY::value_type>(
1762  (*(face_table_.find(f))).second));
1763  }
1764  }
1765 
1766  template<class ARRAY, class INDEX>
1767  inline void get_cells_from_node(ARRAY& array, INDEX idx) const
1768  {
1770  "HexVolMesh: Must call synchronize NODE_NEIGHBORS_E first.");
1771 
1772  array.resize(node_neighbors_[idx].size());
1773  for (size_t i = 0; i < node_neighbors_[idx].size(); ++i)
1774  array[i] = static_cast<typename ARRAY::value_type>(
1775  (node_neighbors_[idx][i])>>3);
1776  }
1777 
1778  template<class ARRAY, class INDEX>
1779  inline void get_edges_from_node(ARRAY& array, INDEX idx) const
1780  {
1782  "HexVolMesh: Must call synchronize NODE_NEIGHBORS_E first");
1784  "HexVolMesh: Must call synchronize EDGES_E first");
1785 
1786  // Get all the nodes that share an edge with this node
1787  const std::vector<typename Cell::index_type>& neighbors = node_neighbors_[idx];
1788 
1789  array.clear();
1790  array.reserve(neighbors.size());
1791  // Iterate through all those edges
1792  for (size_t n = 0; n < neighbors.size(); n++)
1793  {
1794  index_type cell_index = neighbors[n]&(~0x7);
1795  index_type node_index = neighbors[n]&0x7;
1796 
1797  const int *offset = HexVolEdgePerNodeTable[node_index];
1798 
1799  PEdgeNode e(cells_[cell_index+offset[0]],cells_[cell_index+offset[1]]);
1800  typename edge_nt::const_iterator iter = edge_table_.find(e);
1801  if (((edges_[iter->second].cells_[0])&(~0xf))==(cell_index<<1) )
1802  array.push_back(typename ARRAY::value_type(iter->second));
1803 
1804  PEdgeNode e1(cells_[cell_index+offset[2]],cells_[cell_index+offset[3]]);
1805  iter = edge_table_.find(e1);
1806  if (((edges_[iter->second].cells_[0])&(~0xf))==(cell_index<<1) )
1807  array.push_back(typename ARRAY::value_type(iter->second));
1808 
1809  PEdgeNode e2(cells_[cell_index+offset[4]],cells_[cell_index+offset[5]]);
1810  iter = edge_table_.find(e2);
1811  if (((edges_[iter->second].cells_[0])&(~0xf))==(cell_index<<1) )
1812  array.push_back(typename ARRAY::value_type(iter->second));
1813  }
1814  }
1815 
1816  template<class ARRAY, class INDEX>
1817  inline void get_faces_from_edge(ARRAY& array, INDEX idx) const
1818  {
1820  "HexVolMesh: Must call synchronize EDGES_E first");
1822  "HexVolMesh: Must call synchronize FACES_E first");
1823 
1824  array.clear();
1825 
1826  for (size_t c=0; c<edges_[idx].cells_.size();c++)
1827  {
1828  index_type cell_index = ((edges_[idx].cells_[c])>>4)<<3;
1829  index_type face_index = (edges_[idx].cells_[c])&0xF;
1830 
1831  const int* off = HexVolFacePerEdgeTable[face_index];
1832 
1833  typename Node::index_type n1, n2, n3, n4;
1834  typename face_nt::const_iterator fiter;
1835 
1836  n1 = cells_[cell_index+off[0]]; n2 = cells_[cell_index+off[1]];
1837  n3 = cells_[cell_index+off[2]]; n4 = cells_[cell_index+off[3]];
1838 
1839  if (order_face_nodes(n1,n2,n3,n4))
1840  {
1841  fiter = face_table_.find(PFaceNode(n1,n2,n3,n4));
1842  if (((faces_[fiter->second].cells_[0])&(~0x7)) == cell_index)
1843  array.push_back(typename ARRAY::value_type(fiter->second));
1844  }
1845 
1846  n1 = cells_[cell_index+off[4]]; n2 = cells_[cell_index+off[5]];
1847  n3 = cells_[cell_index+off[6]]; n4 = cells_[cell_index+off[7]];
1848 
1849  if (order_face_nodes(n1,n2,n3,n4))
1850  {
1851  fiter = face_table_.find(PFaceNode(n1,n2,n3,n4));
1852  if (((faces_[fiter->second].cells_[0])&(~0x7)) == cell_index)
1853  array.push_back(typename ARRAY::value_type(fiter->second));
1854  }
1855  }
1856  }
1857 
1858  template<class ARRAY, class INDEX>
1859  inline void get_faces_from_node(ARRAY& array, INDEX idx) const
1860  {
1862  "HexVolMesh: Must call synchronize EDGES_E first");
1864  "HexVolMesh: Must call synchronize NODE_NEIGHBORS_E first");
1866  "HexVolMesh: Must call synchronize FACES_E first");
1867 
1868  array.clear();
1869  const std::vector<typename Cell::index_type>& neighbors = node_neighbors_[idx];
1870 
1871  // Iterate through all those edges
1872  for (size_t n = 0; n < neighbors.size(); n++)
1873  {
1874  index_type cell_index = neighbors[n]&(~0x7);
1875  index_type node_index = neighbors[n]&0x7;
1876 
1877  const int *offset = HexVolFacePerNodeTable[node_index];
1878 
1879  typename Node::index_type n1, n2, n3, n4;
1880 
1881  n1 = cells_[cell_index+offset[0]]; n2 = cells_[cell_index+offset[1]];
1882  n3 = cells_[cell_index+offset[2]]; n4 = cells_[cell_index+offset[3]];
1883 
1884  if (order_face_nodes(n1,n2,n3,n4))
1885  {
1886  typename face_nt::const_iterator iter = face_table_.find(PFaceNode(n1,n2,n3,n4));
1887  if (((faces_[iter->second].cells_[0])&(~0x7))==cell_index)
1888  array.push_back(typename ARRAY::value_type(iter->second));
1889  }
1890 
1891  n1 = cells_[cell_index+offset[4]]; n2 = cells_[cell_index+offset[5]];
1892  n3 = cells_[cell_index+offset[6]]; n4 = cells_[cell_index+offset[7]];
1893 
1894  if (order_face_nodes(n1,n2,n3,n4))
1895  {
1896  typename face_nt::const_iterator iter = face_table_.find(PFaceNode(n1,n2,n3,n4));
1897  if (((faces_[iter->second].cells_[0])&(~0x7))==cell_index)
1898  array.push_back(typename ARRAY::value_type(iter->second));
1899  }
1900 
1901  n1 = cells_[cell_index+offset[8]]; n2 = cells_[cell_index+offset[9]];
1902  n3 = cells_[cell_index+offset[10]]; n4 = cells_[cell_index+offset[11]];
1903 
1904  if (order_face_nodes(n1,n2,n3,n4))
1905  {
1906  typename face_nt::const_iterator iter = face_table_.find(PFaceNode(n1,n2,n3,n4));
1907  if (((faces_[iter->second].cells_[0])&(~0x7))==cell_index)
1908  array.push_back(typename ARRAY::value_type(iter->second));
1909  }
1910  }
1911  }
1912 
1913  template<class ARRAY, class INDEX>
1914  inline void get_cells_from_edge(ARRAY& array, INDEX idx) const
1915  {
1917  "HexVolMesh: Must call synchronize EDGES_E first");
1918 
1919  array.resize(edges_[idx].cells_.size());
1920  for (size_t i=0; i<edges_[idx].cells_.size();i++)
1921  array[i] = static_cast<typename ARRAY::value_type>((edges_[idx].cells_[i])>>4);
1922  }
1923 
1924  template<class ARRAY, class INDEX>
1925  inline void get_cells_from_face(ARRAY& array, INDEX idx) const
1926  {
1928  "HexVolMesh: Must call synchronize FACES_E first");
1929 
1930 
1931  if (faces_[idx].cells_[1] == MESH_NO_NEIGHBOR)
1932  {
1933  array.resize(1);
1934  array[0] = static_cast<typename ARRAY::value_type>((faces_[idx].cells_[0])>>3);
1935  }
1936  else
1937  {
1938  array.resize(2);
1939  array[0] = static_cast<typename ARRAY::value_type>((faces_[idx].cells_[0])>>3);
1940  array[1] = static_cast<typename ARRAY::value_type>((faces_[idx].cells_[1])>>3);
1941  }
1942  }
1943 
1944  template<class ARRAY, class INDEX>
1945  inline bool get_cell_from_nodes(INDEX& /*idx*/, ARRAY& /*array*/) const
1946  {
1947  ASSERTFAIL("Get cell from nodes has not yet been implemented");
1948  }
1949 
1950  template<class ARRAY, class INDEX>
1951  inline bool get_face_from_nodes(INDEX& idx, ARRAY& array) const
1952  {
1954  "Must call synchronize FACES_E on HexVolMesh first");
1955 
1956  typename Node::index_type n1(array[0]);
1957  typename Node::index_type n2(array[1]);
1958  typename Node::index_type n3(array[2]);
1959  typename Node::index_type n4(array[3]);
1960 
1961  if(!(order_face_nodes(n1,n2,n3,n4))) return (false);
1962  PFaceNode f(n1, n2, n3, n4);
1963  typename face_nt::const_iterator fiter = face_table_.find(f);
1964  if (fiter == face_table_.end()) {
1965  return (false);
1966  }
1967  idx = INDEX((*fiter).second);
1968  return (true);
1969  }
1970 
1971  template<class ARRAY, class INDEX>
1972  inline bool get_edge_from_nodes(INDEX& idx, ARRAY& array) const
1973  {
1975  "Must call synchronize EDGES_E on HexVolMesh first");
1976 
1977  typename Node::index_type n1(array[0]);
1978  typename Node::index_type n2(array[1]);
1979 
1980  PEdgeNode f(n1, n2);
1981  typename edge_nt::const_iterator fiter = edge_table_.find(f);
1982  if (fiter == edge_table_.end()) {
1983  return (false);
1984  }
1985  idx = INDEX((*fiter).second);
1986  return (true);
1987  }
1988 
1989  template <class ARRAY, class INDEX>
1990  inline void set_nodes_by_elem(ARRAY &array, INDEX idx)
1991  {
1992  for (index_type n = 0; n < 8; ++n)
1993  cells_[idx * 8 + n] = static_cast<index_type>(array[n]);
1994  }
1995 
1996 
1997  template <class INDEX1, class INDEX2>
1998  inline bool get_elem_neighbor(INDEX1 &neighbor, INDEX1 elem, INDEX2 delem) const
1999  {
2001  "Must call synchronize FACES_E on HexVolMesh first");
2002 
2003  const index_type* cells = faces_[delem].cells_;
2004 
2005  if (static_cast<typename Cell::index_type>(elem) == (cells[0]>>3))
2006  {
2007  neighbor = static_cast<INDEX1>((cells[1]>>3));
2008  }
2009  else
2010  {
2011  neighbor = static_cast<INDEX1>((cells[0]>>3));
2012  }
2013  if (neighbor == MESH_NO_NEIGHBOR) return (false);
2014  return (true);
2015  }
2016 
2017  template <class ARRAY,class INDEX1, class INDEX2>
2018  inline bool get_elem_neighbors(ARRAY &array, INDEX1 elem, INDEX2 delem) const
2019  {
2021  "Must call synchronize FACES_E on HexVolMesh first");
2022 
2023  const index_type* cells = faces_[delem].cells_;
2024 
2025  if (elem == static_cast<INDEX1>(cells[0]>>3))
2026  {
2027  array.resize(1);
2028  array[0] = static_cast<typename ARRAY::value_type>(cells[1]>>3);
2029  }
2030  else
2031  {
2032  array.resize(1);
2033  array[0] = static_cast<typename ARRAY::value_type>(cells[0]>>3);
2034  }
2035  if (array[0] == MESH_NO_NEIGHBOR)
2036  {
2037  array.clear();
2038  return (false);
2039  }
2040  return (true);
2041  }
2042 
2043  template <class ARRAY,class INDEX>
2044  inline void get_elem_neighbors(ARRAY &array, INDEX elem) const
2045  {
2046  typename Face::array_type faces;
2047  get_faces_from_cell(faces, elem);
2048 
2049  array.clear();
2050  array.reserve(faces.size());
2051  typename Face::array_type::iterator iter = faces.begin();
2052  while(iter != faces.end())
2053  {
2054  typename ARRAY::value_type nbor;
2055  if (get_elem_neighbor(nbor, elem, *iter))
2056  {
2057  array.push_back(nbor);
2058  }
2059  ++iter;
2060  }
2061  }
2062 
2063  /// We should optimize this function more
2064  template <class ARRAY,class INDEX>
2065  inline void get_node_neighbors(ARRAY &array, INDEX node) const
2066  {
2068  "Must call synchronize NODE_NEIGHBORS_E on HexVolMesh first.");
2069  size_t sz = node_neighbors_[node].size();
2070 
2071  std::set<index_type> inserted;
2072  for (size_t i = 0; i < sz; i++)
2073  {
2074  const index_type base = ((node_neighbors_[node][i])&(~0x7));
2075  for (index_type c = base; c < base+8; ++c)
2076  {
2077  if (cells_[c] != node) inserted.insert(cells_[c]);
2078  }
2079  }
2080 
2081  array.clear();
2082  array.reserve(inserted.size());
2083  array.insert(array.begin(), inserted.begin(), inserted.end());
2084  }
2085 
2086  template <class INDEX>
2087  bool locate_node(INDEX &node, const Core::Geometry::Point &p) const
2088  {
2089  typename Node::size_type sz; size(sz);
2090 
2091  /// If there are no nodes we cannot find a closest point
2092  if (sz == 0) return (false);
2093 
2094  /// Check first guess
2095  if (node >= 0 && node < sz)
2096  {
2097  if ((p - points_[node]).length2() < epsilon2_) return (true);
2098  }
2099 
2101  "HexVolMesh::locate_node requires synchronize(NODE_LOCATE_E).")
2102 
2103  // get grid sizes
2104  const size_type ni = node_grid_->get_ni()-1;
2105  const size_type nj = node_grid_->get_nj()-1;
2106  const size_type nk = node_grid_->get_nk()-1;
2107 
2108  // Convert to grid coordinates.
2109  index_type bi, bj, bk, ei, ej, ek;
2110  node_grid_->unsafe_locate(bi, bj, bk, p);
2111 
2112  // Clamp to l;..;,closest point on the grid.
2113  if (bi > ni) bi =ni; if (bi < 0) bi = 0;
2114  if (bj > nj) bj =nj; if (bj < 0) bj = 0;
2115  if (bk > nk) bk =nk; if (bk < 0) bk = 0;
2116 
2117  ei = bi;
2118  ej = bj;
2119  ek = bk;
2120 
2121  double dmin = DBL_MAX;
2122  bool found;
2123  do
2124  {
2125  found = true;
2126  /// We need to do a full shell without any elements that are closer
2127  /// to make sure there no closer elements in neighboring searchgrid cells
2128 
2129  for (index_type i = bi; i <= ei; i++)
2130  {
2131  if (i < 0 || i > ni) continue;
2132  for (index_type j = bj; j <= ej; j++)
2133  {
2134  if (j < 0 || j > nj) continue;
2135  for (index_type k = bk; k <= ek; k++)
2136  {
2137  if (k < 0 || k > nk) continue;
2138  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
2139  {
2140  if (node_grid_->min_distance_squared(p, i, j, k) < dmin)
2141  {
2142  found = false;
2144  node_grid_->lookup_ijk(it, eit, i, j, k);
2145 
2146  while (it != eit)
2147  {
2148  const Core::Geometry::Point point = points_[*it];
2149  const double dist = (p-point).length2();
2150 
2151  if (dist < dmin)
2152  {
2153  node = INDEX(*it);
2154  dmin = dist;
2155 
2156  if (dist < epsilon2_) return (true);
2157  }
2158  ++it;
2159  }
2160  }
2161  }
2162  }
2163  }
2164  }
2165  bi--;ei++;
2166  bj--;ej++;
2167  bk--;ek++;
2168  }
2169  while ((!found)||(dmin == DBL_MAX)) ;
2170 
2171  return (true);
2172  }
2173 
2174  /// @todo: Fix this function, needs to use search grid
2175  template <class INDEX>
2176  bool locate_edge(INDEX &edge, const Core::Geometry::Point &p) const
2177  {
2179  "Must call synchronize EDGES_E on HexVolMesh first");
2180 
2181  typename Edge::iterator bi, ei;
2182  typename Node::array_type nodes;
2183  begin(bi);
2184  end(ei);
2185 
2186  bool found = false;
2187  double mindist = 0.0;
2188  while (bi != ei)
2189  {
2190  get_nodes(nodes,*bi);
2191  const double dist = distance_to_line2(p, points_[nodes[0]],
2192  points_[nodes[1]],epsilon_);
2193  if (!found || dist < mindist)
2194  {
2195  edge = static_cast<INDEX>(*bi);
2196  mindist = dist;
2197  found = true;
2198  }
2199  ++bi;
2200  }
2201  return (found);
2202  }
2203 
2204  /// @todo: Fix this function, needs to use search grid
2205  template <class INDEX>
2206  bool locate_face(INDEX &face, const Core::Geometry::Point &p) const
2207  {
2209  "Must call synchronize FACES_E on HexVolMesh first");
2210 
2211  bool found = false;
2212  double mindist = DBL_MAX;
2213  typename Face::iterator bi; begin(bi);
2214  typename Face::iterator ei; end(ei);
2215  while (bi != ei)
2216  {
2218  get_center(c, *bi);
2219  const double dist = (p - c).length2();
2220  if (!found || dist < mindist)
2221  {
2222  mindist = dist;
2223  face = static_cast<INDEX>(*bi);
2224  found = true;
2225  }
2226  ++bi;
2227  }
2228  return (found);
2229  }
2230 
2231  template <class INDEX>
2232  bool locate_elem(INDEX &elem, const Core::Geometry::Point &p) const
2233  {
2234  /// @todo: Generate bounding boxes for elements and integrate this into the
2235  // basis function code.
2236  if (basis_.polynomial_order() > 1) return elem_locate(elem, *this, p);
2237 
2238  typename Elem::size_type sz; size(sz);
2239 
2240  /// If there are no nodes we cannot find a closest point
2241  if (sz == 0) return (false);
2242 
2243  /// Check whether the estimate given in idx is the point we are looking for
2244  if ((elem > 0)&&(elem < sz))
2245  {
2246  if (inside(elem,p)) return (true);
2247  }
2248 
2250  "HexVolMesh: need to synchronize ELEM_LOCATE_E first");
2251 
2252  typename SearchGridT<index_type>::iterator it, eit;
2253  if (elem_grid_->lookup(it, eit, p))
2254  {
2255  while (it != eit)
2256  {
2257  if (inside(*it, p))
2258  {
2259  elem = static_cast<INDEX>(*it);
2260  return (true);
2261  }
2262  ++it;
2263  }
2264  }
2265  return (false);
2266  }
2267 
2268  template <class ARRAY>
2269  inline bool locate_elems(ARRAY &array, const Core::Geometry::BBox &b) const
2270  {
2271 
2273  "HexVolMesh::locate_elems requires synchronize(ELEM_LOCATE_E).")
2274 
2275  array.clear();
2276  index_type is,js,ks;
2277  index_type ie,je,ke;
2278  elem_grid_->locate_clamp(is,js,ks,b.min());
2279  elem_grid_->locate_clamp(ie,je,ke,b.max());
2280  for (index_type i=is; i<=ie;i++)
2281  for (index_type j=js; j<je;j++)
2282  for (index_type k=ks; k<ke; k++)
2283  {
2284  typename SearchGridT<index_type>::iterator it, eit;
2285  elem_grid_->lookup_ijk(it, eit, i, j, k);
2286  while (it != eit)
2287  {
2288  size_t p=0;
2289  for (;p<array.size();p++) if (array[p] == typename ARRAY::value_type(*it)) break;
2290  if (p == array.size()) array.push_back(typename ARRAY::value_type(*it));
2291  ++it;
2292  }
2293  }
2294 
2295  return (array.size() > 0);
2296  }
2297 
2298 
2299  template <class INDEX, class ARRAY>
2300  bool locate_elem(INDEX &elem, ARRAY &coords, const Core::Geometry::Point &p) const
2301  {
2302  /// @todo: Generate bounding boxes for elements and integrate this into the
2303  // basis function code.
2304  if (basis_.polynomial_order() > 1) return elem_locate(elem, *this, p);
2305 
2306  typename Elem::size_type sz; size(sz);
2307 
2308  /// If there are no nodes we cannot find a closest point
2309  if (sz == 0) return (false);
2310 
2311  /// Check whether the estimate given in idx is the point we are looking for
2312  if ((elem > 0)&&(elem < sz))
2313  {
2314  if (inside(elem,p))
2315  {
2316  ElemData ed(*this, elem);
2317  basis_.get_coords(coords, p, ed);
2318  return (true);
2319  }
2320  }
2321 
2323  "HexVolMesh: need to synchronize ELEM_LOCATE_E first");
2324 
2325  typename SearchGridT<index_type>::iterator it, eit;
2326  if (elem_grid_->lookup(it, eit, p))
2327  {
2328  while (it != eit)
2329  {
2330  if (inside(*it, p))
2331  {
2332  elem = static_cast<INDEX>(*it);
2333  ElemData ed(*this, elem);
2334  basis_.get_coords(coords, p, ed);
2335  return (true);
2336  }
2337  ++it;
2338  }
2339  }
2340  return (false);
2341  }
2342 
2343  template <class INDEX>
2344  inline void get_node_center(Core::Geometry::Point &p, INDEX idx) const
2345  {
2346  p = points_[idx];
2347  }
2348 
2349  template <class INDEX>
2350  inline void get_edge_center(Core::Geometry::Point &p, INDEX idx) const
2351  {
2352  typename Node::array_type arr;
2353  get_nodes_from_edge(arr, idx);
2355  get_node_center(p, arr[0]);
2356  get_node_center(p1, arr[1]);
2357  p += p1;
2358  p *= 0.5;
2359  }
2360 
2361  template <class INDEX>
2362  inline void get_face_center(Core::Geometry::Point &p, INDEX idx) const
2363  {
2364  /// NEED TO CLEAN UP THIS CODE
2365  /// NEED TO FILTER OUT DEGENERATE FACES
2366  typename Node::array_type nodes;
2367  get_nodes_from_face(nodes, idx);
2368  ASSERT(nodes.size() == 4);
2369  typename Node::array_type::iterator nai = nodes.begin();
2370  get_point(p, *nai);
2371  ++nai;
2373  while (nai != nodes.end())
2374  {
2375  get_point(pp, *nai);
2376  p += pp;
2377  ++nai;
2378  }
2379  p *= 0.25;
2380  }
2381 
2382  template <class INDEX>
2383  inline void get_cell_center(Core::Geometry::Point &p, INDEX idx) const
2384  {
2385  /// NEED TO CLEAN UP THIS CODE
2386  /// NEED TO FILTER OUT DEGENERATE ELEMENTS
2387  typename Node::array_type nodes;
2388  get_nodes_from_cell(nodes, idx);
2389  ASSERT(nodes.size() == 8);
2390  typename Node::array_type::iterator nai = nodes.begin();
2391  get_point(p, *nai);
2392  ++nai;
2394  while (nai != nodes.end())
2395  {
2396  get_point(pp, *nai);
2397  p += pp;
2398  ++nai;
2399  }
2400  p *= 0.125;
2401  }
2402 
2403  //////////////////////////////////////////////////////////////
2404  // Internal functions that the mesh depends on
2405 
2406 protected:
2407 
2408  void compute_node_neighbors();
2409  void compute_edges();
2410  void compute_faces();
2411  void compute_node_grid();
2412  void compute_elem_grid();
2413  void compute_bounding_box();
2414 
2415  void insert_elem_into_grid(typename Elem::index_type ci);
2416  void remove_elem_from_grid(typename Elem::index_type ci);
2417  void insert_node_into_grid(typename Node::index_type ci);
2418  void remove_node_from_grid(typename Node::index_type ci);
2419 
2420  const Core::Geometry::Point &point(typename Node::index_type i) const { return points_[i]; }
2421 
2422  template<class INDEX>
2423  bool inside(INDEX idx, const Core::Geometry::Point &p) const
2424  {
2425  // rewrote this function to more accurately deal with hexes that do not have
2426  // face aligned with the axes of the coordinate system
2427 
2428  // First a fast test to see whether we are inside the bounding box
2429  // (this code could be faster, by testing axis by axis)
2430  // Then if it is inside a tight bounding box compute the local coordinates
2431  // using the Newton search, this way we account for not planar surfaces of
2432  // the hexes.
2433 
2434  typename Node::array_type nodes;
2435  get_nodes_from_elem(nodes,idx);
2436 
2437  Core::Geometry::BBox bbox;
2438  bbox.extend(points_[nodes[0]]);
2439  bbox.extend(points_[nodes[1]]);
2440  bbox.extend(points_[nodes[2]]);
2441  bbox.extend(points_[nodes[3]]);
2442  bbox.extend(points_[nodes[4]]);
2443  bbox.extend(points_[nodes[5]]);
2444  bbox.extend(points_[nodes[6]]);
2445  bbox.extend(points_[nodes[7]]);
2446  bbox.extend(epsilon_);
2447 
2448  if (bbox.inside(p))
2449  {
2450  StackVector<double,3> coords;
2451  ElemData ed(*this, idx);
2452  if(basis_.get_coords(coords, p, ed)) return (true);
2453  }
2454 
2455  return (false);
2456  }
2457 
2458  /// all the nodes.
2459  std::vector<Core::Geometry::Point> points_;
2460  /// each 8 indecies make up a Hex
2461  std::vector<under_type> cells_;
2462 
2463  /// Face information.
2464  class PFaceCell {
2465  public:
2467  {
2468  cells_[0] = MESH_NO_NEIGHBOR;
2469  cells_[1] = MESH_NO_NEIGHBOR;
2470  }
2471 
2472  bool shared() const { return ((cells_[0] != MESH_NO_NEIGHBOR) &&
2473  (cells_[1] != MESH_NO_NEIGHBOR)); }
2474 
2476  };
2477 
2478  struct PFaceNode {
2479  typename Node::index_type nodes_[4]; /// 4 nodes makes a face.
2480 
2482  {
2483  nodes_[0] = MESH_NO_NEIGHBOR;
2484  nodes_[1] = MESH_NO_NEIGHBOR;
2485  nodes_[2] = MESH_NO_NEIGHBOR;
2486  nodes_[3] = MESH_NO_NEIGHBOR;
2487  }
2488 
2489  // snodes_ must be sorted. See Hash Function below.
2490  PFaceNode(typename Node::index_type n1, typename Node::index_type n2,
2491  typename Node::index_type n3, typename Node::index_type n4)
2492  {
2493  nodes_[0] = n1;
2494  nodes_[1] = n2;
2495  nodes_[2] = n3;
2496  nodes_[3] = n4;
2497  }
2498 
2499 
2500  /// true if both have the same nodes (order does not matter)
2501  bool operator==(const PFaceNode &f) const
2502  {
2503  if (nodes_[2] == nodes_[3])
2504  {
2505  return ((nodes_[0] == f.nodes_[0]) &&
2506  (((nodes_[1]==f.nodes_[1])&&(nodes_[2] == f.nodes_[2]))||
2507  ((nodes_[1]==f.nodes_[2])&&(nodes_[2] == f.nodes_[1]))));
2508  }
2509  else
2510  {
2511  return (((nodes_[0] == f.nodes_[0])&&(nodes_[2] == f.nodes_[2])) &&
2512  (((nodes_[1]==f.nodes_[1])&&(nodes_[3] == f.nodes_[3]))||
2513  ((nodes_[1]==f.nodes_[3])&&(nodes_[3] == f.nodes_[1]))));
2514  }
2515  }
2516 
2517  /// Compares each node. When a non equal node is found the <
2518  /// operator is applied.
2519  bool operator<(const PFaceNode &f) const
2520  {
2521  typename Node::index_type t;
2522  typename Node::index_type a0 = nodes_[0];
2523  typename Node::index_type a1 = nodes_[1];
2524  typename Node::index_type a2 = nodes_[2];
2525  typename Node::index_type a3 = nodes_[3];
2526 
2527  if (a2==a3)
2528  {
2529  if (a1>a2) { t = a1; a1 = a2; a2 = t; a3 = a2;}
2530  }
2531  else
2532  {
2533  if (a1>a3) { t = a1; a1 = a3; a3 = t;}
2534  }
2535 
2536  typename Node::index_type b0 = f.nodes_[0];
2537  typename Node::index_type b1 = f.nodes_[1];
2538  typename Node::index_type b2 = f.nodes_[2];
2539  typename Node::index_type b3 = f.nodes_[3];
2540 
2541  if (b2==b3)
2542  {
2543  if (b1>b2) { t = b1; b1 = b2; b2 = t; b3 = b2;}
2544  }
2545  else
2546  {
2547  if (b1>b3) { t = b1; b1 = b3; b3 = t;}
2548  }
2549 
2550  if (a0<b0) return (true);
2551  else if (a0 == b0)
2552  {
2553  if (a1<b1) return (true);
2554  else if (a1 == b1)
2555  {
2556  if (a2<b2) return (true);
2557  else if (a2 == b2)
2558  {
2559  if(a3<b3) return (true);
2560  }
2561  }
2562  }
2563 
2564  return (false);
2565  }
2566  };
2567 
2568  class PFace : public PFaceNode, public PFaceCell
2569  {
2570  public:
2571  PFace(typename Node::index_type n1, typename Node::index_type n2,
2572  typename Node::index_type n3, typename Node::index_type n4) :
2573  PFaceNode(n1,n2,n3,n4) {}
2574  };
2575 
2576  /// Edge information.
2577  class PEdgeNode {
2578  public:
2579  typename Node::index_type nodes_[2]; // 2 nodes makes an edge.
2580 
2582  {
2583  nodes_[0] = MESH_NO_NEIGHBOR;
2584  nodes_[1] = MESH_NO_NEIGHBOR;
2585  }
2586  // node_[0] must be smaller than node_[1]. See Hash Function below.
2588  typename Node::index_type n2)
2589  {
2590  if (n1 < n2)
2591  {
2592  nodes_[0] = n1;
2593  nodes_[1] = n2;
2594  }
2595  else
2596  {
2597  nodes_[0] = n2;
2598  nodes_[1] = n1;
2599  }
2600  }
2601 
2602  /// true if both have the same nodes (order does not matter)
2603  bool operator==(const PEdgeNode &e) const
2604  {
2605  return ((nodes_[0] == e.nodes_[0]) && (nodes_[1] == e.nodes_[1]));
2606  }
2607 
2608  /// Compares each node. When a non equal node is found the <
2609  /// operator is applied.
2610  bool operator<(const PEdgeNode &e) const
2611  {
2612  if (nodes_[0] == e.nodes_[0])
2613  return (nodes_[1] < e.nodes_[1]);
2614  else
2615  return (nodes_[0] < e.nodes_[0]);
2616  }
2617  };
2618 
2619  class PEdgeCell {
2620  public:
2621  /// list of all the cells this edge is in.
2622  //typedef StackBasedVector<index_type,4> cells_type ;
2623  typedef std::vector<index_type> cells_type;
2625 
2626  bool shared() const { return cells_.size() > 1; }
2627  };
2628 
2629  /// Edge information.
2630  class PEdge : public PEdgeNode, public PEdgeCell
2631  {
2632  public:
2633  PEdge(typename Node::index_type n1,typename Node::index_type n2) :
2634  PEdgeNode(n1,n2) {}
2635  };
2636 
2637  /// hash the egde's node_indecies such that edges with the same nodes
2638  /// hash to the same value. nodes are sorted on edge construction.
2639  static const int sz_int = sizeof(int) * 8; // in bits
2640  struct FaceHash
2641  {
2642  /// These are needed by the hash_map particularly
2643  // ANSI C++ allows us to initialize these variables in the
2644  // declaration. However there may be compilers which will complain
2645  // about it.
2646  static const size_t bucket_size = 4;
2647  static const size_t min_buckets = 8;
2648 
2649  /// These are for our own use (making the hash function.
2650  static const int sz_quarter_int = (int)(sz_int / 4);
2651  static const int top4_mask = ((~((int)0)) << sz_quarter_int << sz_quarter_int << sz_quarter_int);
2652  static const int up4_mask = top4_mask ^ (~((int)0) << sz_quarter_int << sz_quarter_int);
2653  static const int mid4_mask = top4_mask ^ (~((int)0) << sz_quarter_int);
2654  static const int low4_mask = ~(top4_mask | mid4_mask);
2655 
2656  /// This is the hash function
2657  template <class PFACE>
2658  size_t operator()(const PFACE &f) const
2659  {
2660  if (f.nodes_[2] == f.nodes_[3])
2661  {
2662  if (f.nodes_[1] < f.nodes_[2])
2663  {
2664  return ((f.nodes_[0] << sz_quarter_int << sz_quarter_int <<sz_quarter_int) |
2665  (up4_mask & (f.nodes_[1] << sz_quarter_int << sz_quarter_int)) |
2666  (mid4_mask & (f.nodes_[2] << sz_quarter_int)) |
2667  (low4_mask & f.nodes_[3]));
2668  }
2669  else
2670  {
2671  return ((f.nodes_[0] << sz_quarter_int << sz_quarter_int <<sz_quarter_int) |
2672  (up4_mask & (f.nodes_[2] << sz_quarter_int << sz_quarter_int)) |
2673  (mid4_mask & (f.nodes_[1] << sz_quarter_int)) |
2674  (low4_mask & f.nodes_[1]));
2675  }
2676  }
2677  else
2678  {
2679  if (f.nodes_[1] < f.nodes_[3] )
2680  {
2681  return ((f.nodes_[0] << sz_quarter_int << sz_quarter_int <<sz_quarter_int) |
2682  (up4_mask & (f.nodes_[1] << sz_quarter_int << sz_quarter_int)) |
2683  (mid4_mask & (f.nodes_[2] << sz_quarter_int)) |
2684  (low4_mask & f.nodes_[3]));
2685  }
2686  else
2687  {
2688  return ((f.nodes_[0] << sz_quarter_int << sz_quarter_int <<sz_quarter_int) |
2689  (up4_mask & (f.nodes_[3] << sz_quarter_int << sz_quarter_int)) |
2690  (mid4_mask & (f.nodes_[2] << sz_quarter_int)) |
2691  (low4_mask & f.nodes_[1]));
2692  }
2693  }
2694  }
2695 
2696  /// This should return less than rather than equal to.
2697  template <class PFACE>
2698  bool operator()(const PFACE &f1, const PFACE& f2) const {
2699  return f1 < f2;
2700  }
2701  };
2702 
2703  /*/ hash the egde's node_indecies such that edges with the same nodes
2704  * hash to the same value. nodes are sorted on edge construction. */
2705  struct EdgeHash {
2706  /// These are needed by the hash_map particularly
2707  // ANSI C++ allows us to initialize these variables in the
2708  // declaration. However there may be compilers which will complain
2709  // about it.
2710  static const size_t bucket_size = 4;
2711  static const size_t min_buckets = 8;
2712 
2713  /// These are for our own use (making the hash function.
2714  static const int sz_int = sizeof(int) * 8; // in bits
2715  static const int sz_half_int = sizeof(int) << 2; // in bits
2716  static const int up_mask = ((~((int)0)) << sz_half_int);
2717  static const int low_mask = (~((int)0) ^ up_mask);
2718 
2719  /// This is the hash function
2720  template<class PEDGE>
2721  size_t operator()(const PEDGE &e) const
2722  {
2723  return (e.nodes_[0] << sz_half_int) |
2724  (low_mask & e.nodes_[1]);
2725  }
2726 
2727  /// This should return less than rather than equal to.
2728  template<class PEDGE>
2729  bool operator()(const PEDGE &e1, const PEDGE &e2) const
2730  {
2731  return e1 < e2;
2732  }
2733  };
2734 
2735 /// Define the hash_map type, as this is not yet an approved type under Windows
2736 /// it is located in stdext
2737 
2738 #ifdef HAVE_HASH_MAP
2739  #if defined(_WIN32)
2740  /// hash_map is in stdext namespace
2741  typedef stdext::hash_map<PFace, typename Face::index_type, FaceHash> face_ht;
2742  typedef stdext::hash_map<PFaceNode, typename Face::index_type, FaceHash> face_nt;
2743  typedef stdext::hash_map<PEdge, typename Edge::index_type, EdgeHash> edge_ht;
2744  typedef stdext::hash_map<PEdgeNode, typename Edge::index_type, EdgeHash> edge_nt;
2745  #else
2746  /// hash_map is in std namespace
2747  typedef hash_map<PFace, typename Face::index_type, FaceHash> face_ht;
2748  typedef hash_map<PFaceNode, typename Face::index_type, FaceHash> face_nt;
2749  typedef hash_map<PEdge, typename Edge::index_type, EdgeHash> edge_ht;
2750  typedef hash_map<PEdgeNode, typename Edge::index_type, EdgeHash> edge_nt;
2751  #endif
2752 #else
2753  typedef std::map<PFace, typename Face::index_type, FaceHash> face_ht;
2754  typedef std::map<PFaceNode, typename Face::index_type, FaceHash> face_nt;
2755  typedef std::map<PEdge, typename Edge::index_type, EdgeHash> edge_ht;
2756  typedef std::map<PEdgeNode, typename Edge::index_type, EdgeHash> edge_nt;
2757 #endif
2758 
2759  typedef std::vector<PFaceCell> face_ct;
2760  typedef std::vector<PEdgeCell> edge_ct;
2761 
2762  /// container for face storage. Must be computed each time
2763  /// nodes or cells change.
2764 
2767  /// container for edge storage. Must be computed each time
2768  /// nodes or cells change.
2771 
2772  inline
2773  void hash_edge(typename Node::index_type n1, typename Node::index_type n2,
2774  index_type combind_index, edge_ht &table) const;
2775 
2776  inline
2777  void hash_face(typename Node::index_type n1, typename Node::index_type n2,
2778  typename Node::index_type n3, typename Node::index_type n4,
2779  index_type combined_index, face_ht &table) const;
2780 
2781  template <class INDEX>
2782  bool order_face_nodes(INDEX& n1, INDEX& n2, INDEX& n3, INDEX& n4) const
2783  {
2784  // Check for degenerate or misformed face
2785  // Opposite faces cannot be equal
2786  if ((n1 == n3)||(n2==n4)) return (false);
2787 
2788  // Face must have three unique identifiers otherwise it was condition
2789  // n1==n3 || n2==n4 would be met.
2790 
2791  if ((n1 < n2)&&(n1 < n3)&&(n1 < n4))
2792  {
2793  }
2794  else if ((n2 < n3)&&(n2 < n4))
2795  {
2796  INDEX t;
2797  // shift one position to left
2798  t = n1; n1 = n2; n2 = n3; n3 = n4; n4 = t;
2799  }
2800  else if (n3 < n4)
2801  {
2802  INDEX t;
2803  // shift two positions to left
2804  t = n1; n1 = n3; n3 = t; t = n2; n2 = n4; n4 = t;
2805  }
2806  else
2807  {
2808  INDEX t;
2809  // shift one positions to right
2810  t = n4; n4 = n3; n3 = n2; n2 = n1; n1 = t;
2811  }
2812 
2813  if (n1==n2)
2814  {
2815  if (n3==n4) return (false); // this is a line not a face
2816  n2 = n3; n3 = n4;
2817  }
2818  else if (n2 == n3)
2819  {
2820  if (n1==n4) return (false); // this is a line not a face
2821  n3 = n4;
2822  }
2823  else if (n4 == n1)
2824  {
2825  n4 = n3;
2826  }
2827  return (true);
2828  }
2829 
2830  /// useful functors
2832  FillNodeNeighbors(std::vector<std::vector<typename Node::index_type> > &n,
2833  const HexVolMesh &m) :
2834  nbor_vec_(n),
2835  mesh_(m)
2836  {}
2837 
2838  void operator()(typename Edge::index_type e) {
2839  nodes_.clear();
2840  mesh_.get_nodes(nodes_, e);
2841  nbor_vec_[nodes_[0]].push_back(nodes_[1]);
2842  nbor_vec_[nodes_[1]].push_back(nodes_[0]);
2843  }
2844 
2845  std::vector<std::vector<typename Node::index_type> > &nbor_vec_;
2848  };
2849 
2850  std::vector<std::vector<typename Cell::index_type> > node_neighbors_;
2851  std::vector<unsigned char> boundary_faces_;
2852 
2853  /// This grid is used as an acceleration structure to expedite calls
2854  /// to locate. For each cell in the grid, we store a list of which
2855  /// tets overlap that grid cell -- to find the tet which contains a
2856  /// point, we simply find which grid cell contains that point, and
2857  /// then search just those tets that overlap that grid cell.
2858  boost::shared_ptr<SearchGridT<index_type> > node_grid_;
2859  boost::shared_ptr<SearchGridT<index_type> > elem_grid_;
2860 
2861  // Lock and Condition Variable for hand shaking
2864 
2865  // Which tables have been computed
2867  // Which tables are currently being computed
2869 
2870  Basis basis_;
2872  double epsilon_;
2873  double epsilon2_;
2874  double epsilon3_;
2875 
2876  /// Pointer to virtual interface
2877  boost::shared_ptr<VMesh> vmesh_;
2878 };
2879 
2880 template <class Basis>
2881 int
2883 {
2884  int sum = 0;
2885  sum += SCIRun::compute_checksum(&points_[0],points_.size());
2886  sum += SCIRun::compute_checksum(&cells_[0],cells_.size());
2887  return (sum);
2888 }
2889 
2890 template <class Basis>
2892  points_(0),
2893  cells_(0),
2894  faces_(0),
2895  face_table_(),
2896  edges_(0),
2897  edge_table_(),
2898  synchronize_lock_("HexVolMesh Lock"),
2899  synchronize_cond_("HexVolMesh condition variable"),
2900  synchronized_(Mesh::NODES_E | Mesh::CELLS_E),
2901  synchronizing_(0),
2902  epsilon_(0.0),
2903  epsilon2_(0.0),
2904  epsilon3_(0.0)
2905 {
2906  DEBUG_CONSTRUCTOR("HexVolMesh")
2907  /// Initialize the virtual interface when the mesh is created
2908  vmesh_.reset(CreateVHexVolMesh(this));
2909 }
2910 
2911 template <class Basis>
2913  Mesh(copy),
2914  points_(0),
2915  cells_(0),
2916  faces_(0),
2917  face_table_(),
2918  edges_(0),
2919  edge_table_(),
2920  synchronize_lock_("HexVolMesh Lock"),
2921  synchronize_cond_("HexVolMesh condition variable"),
2922  synchronized_(Mesh::NODES_E | Mesh::CELLS_E),
2923  synchronizing_(0),
2924  epsilon_(0.0),
2925  epsilon2_(0.0),
2926  epsilon3_(0.0)
2927 {
2928  DEBUG_CONSTRUCTOR("HexVolMesh")
2929  /// Ugly construction circumventing const
2930  HexVolMesh &lcopy = const_cast<HexVolMesh&>(copy);
2931 
2932  /// We need to lock before we can copy these as these
2933  /// structures are generate dynamically when they are
2934  /// needed.
2935  lcopy.synchronize_lock_.lock();
2936 
2937  points_ = copy.points_;
2938  cells_ = copy.cells_;
2939 
2940  // Epsilon does not require much space, hence copy those
2941  synchronized_ |= (copy.synchronized_ & Mesh::BOUNDING_BOX_E);
2942  bbox_ = copy.bbox_;
2943  epsilon_ = copy.epsilon_;
2944  epsilon2_ = copy.epsilon2_;
2945  epsilon3_ = copy.epsilon3_;
2946 
2947  lcopy.synchronize_lock_.unlock();
2948 
2949  /// Create a new virtual interface for this copy
2950  /// all pointers have changed hence create a new
2951  /// virtual interface class
2952  vmesh_.reset(CreateVHexVolMesh(this));
2953 }
2954 
2955 template <class Basis>
2957 {
2958  DEBUG_DESTRUCTOR("HexVolMesh")
2959 }
2960 
2961 template <class Basis>
2962 template <class Iter, class Functor>
2963 void
2964 HexVolMesh<Basis>::fill_points(Iter begin, Iter end, Functor fill_ftor)
2965 {
2966  synchronize_lock_.lock();
2967  Iter iter = begin;
2968  points_.resize(end - begin); // resize to the new size
2969  std::vector<Core::Geometry::Point>::iterator piter = points_.begin();
2970  while (iter != end)
2971  {
2972  *piter = fill_ftor(*iter);
2973  ++piter; ++iter;
2974  }
2975  synchronize_lock_.unlock();
2976 }
2977 
2978 template <class Basis>
2979 template <class Iter, class Functor>
2980 void
2981 HexVolMesh<Basis>::fill_cells(Iter begin, Iter end, Functor fill_ftor)
2982 {
2983  synchronize_lock_.lock();
2984  Iter iter = begin;
2985  cells_.resize((end - begin) * 8); // resize to the new size
2986  std::vector<under_type>::iterator citer = cells_.begin();
2987  while (iter != end)
2988  {
2989  index_type *nodes = fill_ftor(*iter); // returns an array of length 8
2990  *citer = nodes[0];
2991  ++citer;
2992  *citer = nodes[1];
2993  ++citer;
2994  *citer = nodes[2];
2995  ++citer;
2996  *citer = nodes[3];
2997  ++citer; ++iter;
2998  *citer = nodes[4];
2999  ++citer; ++iter;
3000  *citer = nodes[5];
3001  ++citer; ++iter;
3002  *citer = nodes[6];
3003  ++citer; ++iter;
3004  *citer = nodes[7];
3005  ++citer; ++iter;
3006  }
3007  synchronize_lock_.unlock();
3008 }
3009 
3010 template <class Basis>
3014 
3015 template <class Basis>
3016 const std::string
3018 {
3019  ASSERT((n >= -1) && n <= 1);
3020  if (n == -1)
3021  {
3022  static const std::string name = TypeNameGenerator::make_template_id(type_name(0), type_name(1));
3023  return name;
3024  }
3025  else if (n == 0)
3026  {
3027  static const std::string nm("HexVolMesh");
3028  return nm;
3029  }
3030  else
3031  {
3032  return find_type_name((Basis *)0);
3033  }
3034 }
3035 
3036 /* To generate a random point inside of a hexrahedron, we generate random
3037  barrycentric coordinates (independent random variables between 0 and
3038  1 that sum to 1) for the point. */
3039 template <class Basis>
3040 void
3042  typename Cell::index_type ei,
3043  FieldRNG &rng) const
3044 {
3045  const Core::Geometry::Point &p0 = points_[cells_[ei*8+0]];
3046  const Core::Geometry::Point &p1 = points_[cells_[ei*8+1]];
3047  const Core::Geometry::Point &p2 = points_[cells_[ei*8+2]];
3048  const Core::Geometry::Point &p3 = points_[cells_[ei*8+3]];
3049  const Core::Geometry::Point &p4 = points_[cells_[ei*8+4]];
3050  const Core::Geometry::Point &p5 = points_[cells_[ei*8+5]];
3051  const Core::Geometry::Point &p6 = points_[cells_[ei*8+6]];
3052  const Core::Geometry::Point &p7 = points_[cells_[ei*8+7]];
3053 
3054  const double a0 = tetrahedra_volume(p0, p1, p2, p5);
3055  const double a1 = tetrahedra_volume(p0, p2, p3, p7);
3056  const double a2 = tetrahedra_volume(p0, p5, p2, p7);
3057  const double a3 = tetrahedra_volume(p0, p5, p7, p4);
3058  const double a4 = tetrahedra_volume(p5, p2, p7, p6);
3059 
3060  const double w = rng() * (a0 + a1 + a2 + a3 + a4);
3061 
3062  double t = rng();
3063  double u = rng();
3064  double v = rng();
3065 
3066  // Fold cube into prism.
3067  if (t + u > 1.0)
3068  {
3069  t = 1.0 - t;
3070  u = 1.0 - u;
3071  }
3072 
3073  // Fold prism into tet.
3074  if (u + v > 1.0)
3075  {
3076  const double tmp = v;
3077  v = 1.0 - t - u;
3078  u = 1.0 - tmp;
3079  }
3080  else if (t + u + v > 1.0)
3081  {
3082  const double tmp = v;
3083  v = t + u + v - 1.0;
3084  t = 1.0 - u - tmp;
3085  }
3086 
3087  // Convert to Barycentric and compute new point.
3088  const double a = 1.0 - t - u - v;
3089 
3090  if (w > (a0 + a1 + a2 + a3))
3091  {
3092  p = Core::Geometry::Point(p5*a + p2*t + p7*u + p6*v);
3093  }
3094  else if (w > (a0 + a1 + a2))
3095  {
3096  p = Core::Geometry::Point(p0*a + p5*t + p7*u + p4*v);
3097  }
3098  else if (w > (a0 + a1))
3099  {
3100  p = Core::Geometry::Point(p0*a + p5*t + p2*u + p7*v);
3101  }
3102  else if (w > a0)
3103  {
3104  p = Core::Geometry::Point(p0*a + p2*t + p3*u + p7*v);
3105  }
3106  else
3107  {
3108  p = Core::Geometry::Point(p0*a + p1*t + p2*u + p5*v);
3109  }
3110 }
3111 
3112 template <class Basis>
3115 {
3116  Core::Geometry::BBox result;
3117 
3118  // Compute bounding box
3119  typename Node::iterator ni, nie;
3120  begin(ni);
3121  end(nie);
3122  while (ni != nie)
3123  {
3124  result.extend(points_[*ni]);
3125  ++ni;
3126  }
3127 
3128  return result;
3129 }
3130 
3131 template <class Basis>
3132 void
3134 {
3135  t.load_identity();
3136  Core::Geometry::BBox bbox = get_bounding_box();
3137  t.pre_scale(bbox.diagonal());
3139 }
3140 
3141 template <class Basis>
3142 void
3144 {
3145  bbox_.reset();
3146 
3147  // Compute bounding box
3148  typename Node::iterator ni, nie;
3149  begin(ni);
3150  end(nie);
3151  while (ni != nie)
3152  {
3153  bbox_.extend(points_[*ni]);
3154  ++ni;
3155  }
3156 
3157  // Compute epsilons associated with the bounding box
3158  epsilon_ = bbox_.diagonal().length()*1e-8;
3159  epsilon2_ = epsilon_*epsilon_;
3160  epsilon3_ = epsilon_*epsilon_*epsilon_;
3161 
3162  synchronize_lock_.lock();
3163  synchronized_ |= Mesh::BOUNDING_BOX_E;
3164  synchronize_lock_.unlock();
3165 }
3166 
3167 template <class Basis>
3168 void
3170 {
3171  synchronize_lock_.lock();
3172 
3173  std::vector<Core::Geometry::Point>::iterator itr = points_.begin();
3174  std::vector<Core::Geometry::Point>::iterator eitr = points_.end();
3175  while (itr != eitr)
3176  {
3177  *itr = t.project(*itr);
3178  ++itr;
3179  }
3180 
3181  if (bbox_.valid())
3182  {
3183  bbox_.reset();
3184 
3185  // Compute bounding box
3186  typename Node::iterator ni, nie;
3187  begin(ni);
3188  end(nie);
3189  while (ni != nie)
3190  {
3191  bbox_.extend(point(*ni));
3192  ++ni;
3193  }
3194 
3195  // Compute epsilons associated with the bounding box
3196  epsilon_ = bbox_.diagonal().length()*1e-8;
3197  epsilon2_ = epsilon_*epsilon_;
3198  epsilon3_ = epsilon_*epsilon_*epsilon_;
3199 
3200  synchronized_ |= Mesh::BOUNDING_BOX_E;
3201  }
3202 
3203  if (node_grid_) { node_grid_->transform(t); }
3204  if (elem_grid_) { elem_grid_->transform(t); }
3205  synchronize_lock_.unlock();
3206 }
3207 
3208 template <class Basis>
3209 void
3211  typename Node::index_type n2,
3212  typename Node::index_type n3,
3213  typename Node::index_type n4,
3214  index_type combined_index,
3215  face_ht &table) const
3216 {
3217  // Reorder nodes while maintaining CCW or CW orientation
3218  // Check for degenerate faces, if faces has degeneracy it
3219  // will be ignored (e.g. nodes on opposite corners are equal,
3220  // or more then two nodes are equal)
3221 
3222  if (!(order_face_nodes(n1,n2,n3,n4))) return;
3223  PFace f(n1, n2, n3, n4);
3224 
3225 
3226  typename face_ht::iterator iter = table.find(f);
3227 
3228  if (iter == table.end())
3229  {
3230  f.cells_[0] = combined_index;
3231  table[f] = 0; // insert for the first time
3232  }
3233  else
3234  {
3235  PFace f = (*iter).first;
3236  if (f.cells_[1] != MESH_NO_NEIGHBOR)
3237  {
3238  std::cerr << "HexVolMesh - This Mesh has problems: Cells #"
3239  << (f.cells_[0]>>3) << ", #" << (f.cells_[1]>>3) << ", and #" << (combined_index>>3)
3240  << " are illegally adjacent." << std::endl;
3241  }
3242  else if ((f.cells_[0]>>3) == (combined_index>>3))
3243  {
3244  std::cerr << "HexVolMesh - This Mesh has problems: Cells #"
3245  << (f.cells_[0]>>3) << ", #" << (f.cells_[1]>>3) << ", and #" << (combined_index>>3)
3246  << " are the same." << std::endl;
3247  }
3248  else
3249  {
3250  f.cells_[1] = combined_index; // add this cell
3251  table.erase(iter);
3252  table[f] = 0;
3253  }
3254  }
3255 }
3256 
3257 template <class Basis>
3258 void
3260 {
3261  face_table_.clear();
3262 
3263  typename Cell::iterator ci, cie;
3264  begin(ci); end(cie);
3265  typename Node::array_type arr(8);
3266 
3267  face_ht table;
3268 
3269  while (ci != cie)
3270  {
3271  get_nodes(arr, *ci);
3272  // 6 faces -- each is entered CCW from outside looking in
3273  index_type cell_index = (*ci)<<3;
3274  hash_face(arr[0], arr[1], arr[2], arr[3], cell_index, table);
3275  hash_face(arr[7], arr[6], arr[5], arr[4], cell_index + 1, table);
3276  hash_face(arr[0], arr[4], arr[5], arr[1], cell_index + 2, table);
3277  hash_face(arr[2], arr[6], arr[7], arr[3], cell_index + 3, table);
3278  hash_face(arr[3], arr[7], arr[4], arr[0], cell_index + 4, table);
3279  hash_face(arr[1], arr[5], arr[6], arr[2], cell_index + 5, table);
3280 
3281  ++ci;
3282  }
3283 
3284  faces_.resize(table.size());
3285  boundary_faces_.resize(cells_.size()>>3);
3286 
3287  typename face_ht::iterator ht_iter = table.begin();
3288  typename face_ht::iterator ht_iter_end = table.end();
3289 
3290  index_type uidx = 0;
3291  while (ht_iter != ht_iter_end)
3292  {
3293  const PFace& pface = (*ht_iter).first;
3294  faces_[uidx].cells_[0] = pface.cells_[0];
3295  faces_[uidx].cells_[1] = pface.cells_[1];
3296  face_table_[PFaceNode(pface.nodes_[0],pface.nodes_[1],pface.nodes_[2],pface.nodes_[3])] = uidx;
3297 
3298  if (pface.cells_[1] == -1)
3299  {
3300  index_type cell = (pface.cells_[0]) >> 3;
3301  index_type face = (pface.cells_[0]) & 0x7;
3302  boundary_faces_[cell] |= 1 << face;
3303  }
3304 
3305  ++ht_iter; uidx++;
3306  }
3307 
3308  synchronize_lock_.lock();
3309  synchronized_ |= Mesh::FACES_E;
3310  synchronize_lock_.unlock();
3311 }
3312 
3313 template <class Basis>
3314 void
3316  typename Node::index_type n2,
3317  index_type combined_index,
3318  edge_ht &table) const
3319 {
3320  if (n1 == n2) return;
3321  PEdge e(n1, n2);
3322  typename edge_ht::iterator iter = table.find(e);
3323  if (iter == table.end())
3324  {
3325  e.cells_.push_back(combined_index); // add this cell
3326  table[e] = 0; // insert for the first time
3327  }
3328  else
3329  {
3330  PEdge e = (*iter).first;
3331  e.cells_.push_back(combined_index); // add this cell
3332  table.erase(iter);
3333  table[e] = 0;
3334  }
3335 }
3336 
3337 template <class Basis>
3338 void
3340 {
3341  typename Cell::iterator ci, cie;
3342  begin(ci); end(cie);
3343  edge_ht table;
3344  typename Node::array_type arr;
3345  while (ci != cie)
3346  {
3347  get_nodes(arr, *ci);
3348  index_type cell_index = (*ci)<<4;
3349  hash_edge(arr[0], arr[1], cell_index , table);
3350  hash_edge(arr[1], arr[2], cell_index+1, table);
3351  hash_edge(arr[2], arr[3], cell_index+2, table);
3352  hash_edge(arr[3], arr[0], cell_index+3, table);
3353 
3354  hash_edge(arr[4], arr[5], cell_index+4, table);
3355  hash_edge(arr[5], arr[6], cell_index+5, table);
3356  hash_edge(arr[6], arr[7], cell_index+6, table);
3357  hash_edge(arr[7], arr[4], cell_index+7, table);
3358 
3359  hash_edge(arr[0], arr[4], cell_index+8, table);
3360  hash_edge(arr[5], arr[1], cell_index+9, table);
3361  hash_edge(arr[2], arr[6], cell_index+10,table);
3362  hash_edge(arr[7], arr[3], cell_index+11,table);
3363  ++ci;
3364  }
3365 
3366  // dump edges into the edges_ container.
3367 
3368  edges_.resize(table.size());
3369 
3370  typename edge_ht::iterator ht_iter = table.begin();
3371  typename edge_ht::iterator ht_iter_end = table.end();
3372 
3373  index_type uidx = 0;
3374  while (ht_iter != ht_iter_end)
3375  {
3376  const PEdge& pedge = (*ht_iter).first;
3377  edges_[uidx].cells_ = pedge.cells_;
3378  edge_table_[PEdgeNode(pedge.nodes_[0],pedge.nodes_[1])] = uidx;
3379  ++ht_iter; uidx++;
3380  }
3381 
3382  synchronize_lock_.lock();
3383  synchronized_ |= Mesh::EDGES_E;
3384  synchronize_lock_.unlock();
3385 }
3386 
3387 template <class Basis>
3388 bool
3390 {
3391  // Conversion table
3392  if (sync & (Mesh::ELEM_NEIGHBORS_E|Mesh::DELEMS_E))
3393  { sync |= Mesh::FACES_E; sync &= ~(Mesh::ELEM_NEIGHBORS_E|Mesh::DELEMS_E); }
3394 
3395  if (sync & Mesh::FIND_CLOSEST_NODE_E)
3396  { sync |= Mesh::NODE_LOCATE_E; sync &= ~(Mesh::FIND_CLOSEST_NODE_E); }
3397 
3398  if (sync & Mesh::FIND_CLOSEST_ELEM_E)
3400 
3402 
3403  // Filter out the only tables available
3404  sync &= (Mesh::EDGES_E|Mesh::FACES_E|
3407 
3408  Core::Thread::UniqueLock lock(synchronize_lock_.get());
3409 
3410  // Only sync was hasn't been synched
3411  sync &= (~synchronized_);
3412 
3413  if (sync == Mesh::EDGES_E)
3414  {
3415  Synchronize Synchronize(*this,sync);
3416  synchronize_lock_.unlock();
3417  Synchronize.run();
3418  synchronize_lock_.lock();
3419  }
3420  else if (sync & Mesh::EDGES_E)
3421  {
3422  mask_type tosync = Mesh::EDGES_E;
3423  Synchronize syncclass(*this,tosync);
3424  boost::thread syncthread(syncclass);
3425  }
3426 
3427  if (sync == Mesh::FACES_E)
3428  {
3429  Synchronize Synchronize(*this,sync);
3430  synchronize_lock_.unlock();
3431  Synchronize.run();
3432  synchronize_lock_.lock();
3433  }
3434  else if (sync & Mesh::FACES_E)
3435  {
3436  mask_type tosync = Mesh::FACES_E;
3437  Synchronize syncclass(*this,tosync);
3438  boost::thread syncthread(syncclass);
3439  }
3440 
3441  if (sync == Mesh::NODE_NEIGHBORS_E)
3442  {
3443  Synchronize Synchronize(*this,sync);
3444  synchronize_lock_.unlock();
3445  Synchronize.run();
3446  synchronize_lock_.lock();
3447  }
3448  else if (sync & Mesh::NODE_NEIGHBORS_E)
3449  {
3451  Synchronize syncclass(*this,tosync);
3452  boost::thread syncthread(syncclass);
3453  }
3454 
3455  if (sync == Mesh::BOUNDING_BOX_E)
3456  {
3457  Synchronize Synchronize(*this,sync);
3458  synchronize_lock_.unlock();
3459  Synchronize.run();
3460  synchronize_lock_.lock();
3461  }
3462  else if (sync & Mesh::BOUNDING_BOX_E)
3463  {
3465  Synchronize syncclass(*this,tosync);
3466  boost::thread syncthread(syncclass);
3467  }
3468 
3469  if (sync == Mesh::NODE_LOCATE_E)
3470  {
3471  Synchronize Synchronize(*this,sync);
3472  synchronize_lock_.unlock();
3473  Synchronize.run();
3474  synchronize_lock_.lock();
3475  }
3476  else if (sync & Mesh::NODE_LOCATE_E)
3477  {
3478  mask_type tosync = Mesh::NODE_LOCATE_E;
3479  Synchronize syncclass(*this,tosync);
3480  boost::thread syncthread(syncclass);
3481  }
3482 
3483  if (sync == Mesh::ELEM_LOCATE_E)
3484  {
3485  Synchronize Synchronize(*this,sync);
3486  synchronize_lock_.unlock();
3487  Synchronize.run();
3488  synchronize_lock_.lock();
3489  }
3490  else if (sync & Mesh::ELEM_LOCATE_E)
3491  {
3492  mask_type tosync = Mesh::ELEM_LOCATE_E;
3493  Synchronize syncclass(*this,tosync);
3494  boost::thread syncthread(syncclass);
3495  }
3496 
3497  // Wait until threads are done
3498  while ((synchronized_ & sync) != sync)
3499  {
3500  synchronize_cond_.wait(lock);
3501  }
3502 
3503  return (true);
3504 }
3505 
3506 template<class Basis>
3507 bool
3509 {
3510  return(true);
3511 }
3512 
3513 template <class Basis>
3514 bool
3516 {
3517  synchronize_lock_.lock();
3518 
3519  // Undo marking the synchronization
3520  synchronized_ = Mesh::NODES_E | Mesh::ELEMS_E | Mesh::CELLS_E;
3521 
3522  // Free memory where possible
3523  node_neighbors_.clear();
3524  edges_.clear();
3525  edge_table_.clear();
3526  faces_.clear();
3527  face_table_.clear();
3528  boundary_faces_.clear();
3529 
3530  node_grid_.reset();
3531  elem_grid_.reset();
3532 
3533  synchronize_lock_.unlock();
3534  return (true);
3535 }
3536 
3537 
3538 template <class Basis>
3539 void
3541 {
3542  ASSERTMSG(synchronized_ & Mesh::NODES_E,
3543  "Must call synchronize NODES_E on HexVolMesh first");
3544  itr = 0;
3545 }
3546 
3547 template <class Basis>
3548 void
3550 {
3551  ASSERTMSG(synchronized_ & Mesh::NODES_E,
3552  "Must call synchronize NODES_E on HexVolMesh first");
3553  itr = static_cast<typename Node::iterator>(points_.size());
3554 }
3555 
3556 template <class Basis>
3557 void
3559 {
3560  ASSERTMSG(synchronized_ & Mesh::NODES_E,
3561  "Must call synchronize NODES_E on HexVolMesh first");
3562  s = static_cast<typename Node::size_type>(points_.size());
3563 }
3564 
3565 template <class Basis>
3566 void
3568 {
3569  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
3570  "Must call synchronize EDGES_E on HexVolMesh first");
3571  itr = 0;
3572 }
3573 
3574 template <class Basis>
3575 void
3577 {
3578  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
3579  "Must call synchronize EDGES_E on HexVolMesh first");
3580  itr = static_cast<typename Edge::iterator>(edges_.size());
3581 }
3582 
3583 template <class Basis>
3584 void
3586 {
3587  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
3588  "Must call synchronize EDGES_E on HexVolMesh first");
3589  s = static_cast<typename Edge::size_type>(edges_.size());
3590 }
3591 
3592 template <class Basis>
3593 void
3595 {
3596  ASSERTMSG(synchronized_ & Mesh::FACES_E,
3597  "Must call synchronize FACES_E on HexVolMesh first");
3598  itr = 0;
3599 }
3600 
3601 template <class Basis>
3602 void
3604 {
3605  ASSERTMSG(synchronized_ & Mesh::FACES_E,
3606  "Must call synchronize FACES_E on HexVolMesh first");
3607  itr = static_cast<typename Face::iterator>(faces_.size());
3608 }
3609 
3610 template <class Basis>
3611 void
3613 {
3614  ASSERTMSG(synchronized_ & Mesh::FACES_E,
3615  "Must call synchronize FACES_E on HexVolMesh first");
3616  s = static_cast<typename Face::size_type>(faces_.size());
3617 }
3618 
3619 template <class Basis>
3620 void
3622 {
3623  ASSERTMSG(synchronized_ & Mesh::CELLS_E,
3624  "Must call synchronize CELLS_E on HexVolMesh first");
3625  itr = 0;
3626 }
3627 
3628 template <class Basis>
3629 void
3631 {
3632  ASSERTMSG(synchronized_ & Mesh::CELLS_E,
3633  "Must call synchronize CELLS_E on HexVolMesh first");
3634  itr = static_cast<typename Cell::iterator>(cells_.size() >> 3);
3635 }
3636 
3637 template <class Basis>
3638 void
3640 {
3641  ASSERTMSG(synchronized_ & Mesh::CELLS_E,
3642  "Must call synchronize CELLS_E on HexVolMesh first");
3643  s = static_cast<typename Cell::size_type>(cells_.size() >> 3);
3644 }
3645 
3646 template <class Basis>
3647 bool
3649  typename Node::index_type n1,
3650  typename Node::index_type n2,
3651  typename Node::index_type n3,
3652  typename Node::index_type n4) const
3653 {
3654  ASSERTMSG(synchronized_ & Mesh::FACES_E,
3655  "Must call synchronize FACES_E on HexVolMesh first");
3656  if(!(order_face_nodes(n1,n2,n3,n4))) return (false);
3657  PFaceNode f(n1, n2, n3, n4);
3658  typename face_nt::const_iterator fiter = face_table_.find(f);
3659  if (fiter == face_table_.end()) {
3660  return false;
3661  }
3662  face = (*fiter).second;
3663  return true;
3664 }
3665 
3666 template <class Basis>
3667 void
3669 {
3670  node_neighbors_.clear();
3671  node_neighbors_.resize(points_.size());
3672  index_type i, num_cells = cells_.size();
3673  for (i = 0; i < num_cells; i++)
3674  {
3675  node_neighbors_[cells_[i]].push_back(i);
3676  }
3677 
3678  synchronize_lock_.lock();
3679  synchronized_ |= Mesh::NODE_NEIGHBORS_E;
3680  synchronize_lock_.unlock();
3681 }
3682 
3683 template <class Basis>
3684 int
3686  double *w) const
3687 {
3688  typename Cell::index_type idx;
3689  if (locate_elem(idx, p))
3690  {
3691  get_nodes(l,idx);
3692  std::vector<double> coords(3);
3693  if (get_coords(coords, p, idx))
3694  {
3695  basis_.get_weights(coords, w);
3696  return basis_.dofs();
3697  }
3698  }
3699  return 0;
3700 }
3701 
3702 template <class Basis>
3703 int
3704 HexVolMesh<Basis>::get_weights(const Core::Geometry::Point &p, typename Cell::array_type &l,
3705  double *w) const
3706 {
3707  typename Cell::index_type idx;
3708  if (locate_elem(idx, p))
3709  {
3710  l.resize(1);
3711  l[0] = idx;
3712  w[0] = 1.0;
3713  return 1;
3714  }
3715  return 0;
3716 }
3717 
3718 template <class Basis>
3719 void
3721 {
3722  /// @todo: This can crash if you insert a new cell outside of the grid.
3723  // Need to recompute grid at that point.
3724 
3725  const index_type idx = ci*8;
3727  box.extend(points_[cells_[idx]]);
3728  box.extend(points_[cells_[idx+1]]);
3729  box.extend(points_[cells_[idx+2]]);
3730  box.extend(points_[cells_[idx+3]]);
3731  box.extend(points_[cells_[idx+4]]);
3732  box.extend(points_[cells_[idx+5]]);
3733  box.extend(points_[cells_[idx+6]]);
3734  box.extend(points_[cells_[idx+7]]);
3735  box.extend(epsilon_);
3736 
3737  elem_grid_->insert(ci, box);
3738 }
3739 
3740 template <class Basis>
3741 void
3743 {
3744  const index_type idx = ci*8;
3746  box.extend(points_[cells_[idx]]);
3747  box.extend(points_[cells_[idx+1]]);
3748  box.extend(points_[cells_[idx+2]]);
3749  box.extend(points_[cells_[idx+3]]);
3750  box.extend(points_[cells_[idx+4]]);
3751  box.extend(points_[cells_[idx+5]]);
3752  box.extend(points_[cells_[idx+6]]);
3753  box.extend(points_[cells_[idx+7]]);
3754  box.extend(epsilon_);
3755  elem_grid_->remove(ci, box);
3756 }
3757 
3758 template <class Basis>
3759 void
3761 {
3762  /// @todo: This can crash if you insert a new cell outside of the grid.
3763  // Need to recompute grid at that point.
3764  node_grid_->insert(ni,points_[ni]);
3765 }
3766 
3767 template <class Basis>
3768 void
3770 {
3771  node_grid_->remove(ni,points_[ni]);
3772 }
3773 
3774 template <class Basis>
3775 void
3777 {
3778  if (bbox_.valid())
3779  {
3780  // Cubed root of number of cells to get a subdivision ballpark.
3781 
3782  typename Elem::size_type esz; size(esz);
3783 
3784  const size_type s =
3785  3*static_cast<size_type>((ceil(pow(static_cast<double>(esz) , (1.0/3.0))))/2.0 + 1.0);
3786 
3787  Core::Geometry::Vector diag = bbox_.diagonal();
3788  double trace = (diag.x()+diag.y()+diag.z());
3789  size_type sx = static_cast<size_type>(ceil(0.5+diag.x()/trace*s));
3790  size_type sy = static_cast<size_type>(ceil(0.5+diag.y()/trace*s));
3791  size_type sz = static_cast<size_type>(ceil(0.5+diag.z()/trace*s));
3792 
3793  Core::Geometry::BBox b = bbox_; b.extend(10*epsilon_);
3794  elem_grid_.reset(new SearchGridT<index_type>(sx, sy, sz, b.min(), b.max()));
3795 
3796  typename Elem::iterator ci, cie;
3797  begin(ci); end(cie);
3798  while(ci != cie)
3799  {
3800  insert_elem_into_grid(*ci);
3801  ++ci;
3802  }
3803  }
3804 
3805  synchronize_lock_.lock();
3806  synchronized_ |= Mesh::ELEM_LOCATE_E;
3807  synchronize_lock_.unlock();
3808 }
3809 
3810 template <class Basis>
3811 void
3813 {
3814  ASSERTMSG(bbox_.valid(),"HexVolMesh BBox not valid");
3815  if (bbox_.valid())
3816  {
3817  // Cubed root of number of cells to get a subdivision ballpark.
3818 
3819  typename Elem::size_type esz; size(esz);
3820 
3821  const size_type s = 3*static_cast<size_type>
3822  ((ceil(pow(static_cast<double>(esz) , (1.0/3.0))))/2.0 + 1.0);
3823 
3824  Core::Geometry::Vector diag = bbox_.diagonal();
3825  double trace = (diag.x()+diag.y()+diag.z());
3826  size_type sx = static_cast<size_type>(ceil(0.5+diag.x()/trace*s));
3827  size_type sy = static_cast<size_type>(ceil(0.5+diag.y()/trace*s));
3828  size_type sz = static_cast<size_type>(ceil(0.5+diag.z()/trace*s));
3829 
3830  Core::Geometry::BBox b = bbox_; b.extend(10*epsilon_);
3831  node_grid_.reset(new SearchGridT<index_type>(sx, sy, sz, b.min(), b.max()));
3832 
3833  typename Node::iterator ni, nie;
3834  begin(ni); end(nie);
3835  while(ni != nie)
3836  {
3837  insert_node_into_grid(*ni);
3838  ++ni;
3839  }
3840  }
3841 
3842  synchronize_lock_.lock();
3843  synchronized_ |= Mesh::NODE_LOCATE_E;
3844  synchronize_lock_.unlock();
3845 }
3846 
3847 template <class Basis>
3850 {
3851  typename Node::index_type i;
3852  if (locate_node(i, p) && ((points_[i] - p).length2() < err))
3853  {
3854  return i;
3855  }
3856  else
3857  {
3858  points_.push_back(p);
3859  return static_cast<typename Node::index_type>(points_.size() - 1);
3860  }
3861 }
3862 
3863 template <class Basis>
3866  typename Node::index_type b,
3867  typename Node::index_type c,
3868  typename Node::index_type d,
3869  typename Node::index_type e,
3870  typename Node::index_type f,
3871  typename Node::index_type g,
3872  typename Node::index_type h)
3873 {
3874  const index_type hex = static_cast<index_type>(cells_.size()) / 8;
3875  cells_.push_back(a);
3876  cells_.push_back(b);
3877  cells_.push_back(c);
3878  cells_.push_back(d);
3879  cells_.push_back(e);
3880  cells_.push_back(f);
3881  cells_.push_back(g);
3882  cells_.push_back(h);
3883  return hex;
3884 }
3885 
3886 template <class Basis>
3889 {
3890  points_.push_back(p);
3891  return static_cast<typename Node::index_type>(points_.size() - 1);
3892 }
3893 
3894 template <class Basis>
3897  const Core::Geometry::Point &p2, const Core::Geometry::Point &p3,
3898  const Core::Geometry::Point &p4, const Core::Geometry::Point &p5,
3899  const Core::Geometry::Point &p6, const Core::Geometry::Point &p7)
3900 {
3901  return add_hex(add_find_point(p0), add_find_point(p1),
3902  add_find_point(p2), add_find_point(p3),
3903  add_find_point(p4), add_find_point(p5),
3904  add_find_point(p6), add_find_point(p7));
3905 }
3906 
3907 #define HEXVOLMESH_VERSION 5
3908 
3909 template <class Basis>
3910 void
3912 {
3913  const int version = stream.begin_class(type_name(-1), HEXVOLMESH_VERSION);
3914  Mesh::io(stream);
3915 
3916  SCIRun::Pio(stream, points_);
3917  SCIRun::Pio_index(stream, cells_);
3918  if (version == 1)
3919  {
3920  // Read this and then purge it
3921  std::vector<under_type> face_neighbors;
3922  SCIRun::Pio_index(stream, face_neighbors);
3923  }
3924 
3925  if (version >= 3)
3926  {
3927  basis_.io(stream);
3928  }
3929 
3930  stream.end_class();
3931 
3932  if (stream.reading())
3933  {
3934  synchronized_ = NODES_E | CELLS_E;
3935 
3936  vmesh_.reset(CreateVHexVolMesh(this));
3937  }
3938 }
3939 
3940 template <class Basis>
3942 {
3943  static TypeDescription *td = 0;
3944  if (!td)
3945  {
3946  const TypeDescription *sub = get_type_description((Basis*)0);
3948  (*subs)[0] = sub;
3949  td = new TypeDescription("HexVolMesh", subs,
3950  std::string(__FILE__),
3951  "SCIRun",
3953  }
3954  return td;
3955 }
3956 
3957 template <class Basis>
3958 const TypeDescription*
3960 {
3962 }
3963 
3964 template <class Basis>
3965 const TypeDescription*
3967 {
3968  static TypeDescription *td = 0;
3969  if (!td)
3970  {
3971  const TypeDescription *me =
3973  td = new TypeDescription(me->get_name() + "::Node",
3974  std::string(__FILE__),
3975  "SCIRun",
3977  }
3978  return td;
3979 }
3980 
3981 template <class Basis>
3982 const TypeDescription*
3984 {
3985  static TypeDescription *td = 0;
3986  if (!td)
3987  {
3988  const TypeDescription *me =
3990  td = new TypeDescription(me->get_name() + "::Edge",
3991  std::string(__FILE__),
3992  "SCIRun",
3994  }
3995  return td;
3996 }
3997 
3998 template <class Basis>
3999 const TypeDescription*
4001 {
4002  static TypeDescription *td = 0;
4003  if (!td)
4004  {
4005  const TypeDescription *me =
4007  td = new TypeDescription(me->get_name() + "::Face",
4008  std::string(__FILE__),
4009  "SCIRun",
4011  }
4012  return td;
4013 }
4014 
4015 template <class Basis>
4016 const TypeDescription*
4018 {
4019  static TypeDescription *td = 0;
4020  if (!td)
4021  {
4022  const TypeDescription *me =
4024  td = new TypeDescription(me->get_name() + "::Cell",
4025  std::string(__FILE__),
4026  "SCIRun",
4028  }
4029  return td;
4030 }
4031 
4032 } // namespace SCIRun
4033 
4034 #endif
FillNodeNeighbors(std::vector< std::vector< typename Node::index_type > > &n, const HexVolMesh &m)
Definition: HexVolMesh.h:2832
void begin(typename Node::iterator &) const
begin/end iterators
Definition: HexVolMesh.h:3540
void get_delems(typename DElem::array_type &array, typename Node::index_type idx) const
Definition: HexVolMesh.h:577
Interface to statically allocated std::vector class.
Definition: VUnstructuredMesh.h:41
bool shared() const
Definition: HexVolMesh.h:2472
void get_neighbors(std::vector< typename Node::index_type > &array, typename Node::index_type node) const
These are more general neighbor functions.
Definition: HexVolMesh.h:677
boost::shared_ptr< HexVolMesh< Basis > > handle_type
Definition: HexVolMesh.h:172
index_type edge0_index() const
the following designed to coordinate with ::get_edges
Definition: HexVolMesh.h:268
Edge information.
Definition: HexVolMesh.h:2577
void get_faces_from_edge(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1817
bool reading() const
Definition: Persistent.h:164
virtual int topology_geometry() const
Definition: HexVolMesh.h:446
EdgeIndex< under_type > size_type
Definition: HexVolMesh.h:186
virtual void io(Piostream &)
Export this class using the old Pio system.
Definition: HexVolMesh.h:3911
void get_center(Core::Geometry::Point &result, typename Node::index_type idx) const
get the center point (in object space) of an element
Definition: HexVolMesh.h:614
Distinct type for node FieldIterator.
Definition: FieldIterator.h:89
void run()
Definition: HexVolMesh.h:367
PEdgeNode(typename Node::index_type n1, typename Node::index_type n2)
Definition: HexVolMesh.h:2587
bool locate(typename Cell::index_type &idx, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:695
bool locate_edge(INDEX &edge, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2176
Synchronize(HexVolMesh< Basis > &mesh, mask_type sync)
Definition: HexVolMesh.h:363
index_type edge10_index() const
Definition: HexVolMesh.h:308
Definition: FieldRNG.h:37
index_type edge5_index() const
Definition: HexVolMesh.h:288
std::string get_name(const std::string &type_sep_start="<", const std::string &type_sep_end="> ") const
Definition: TypeDescription.cc:135
void derivate(const VECTOR1 &coords, INDEX idx, VECTOR2 &J) const
Definition: HexVolMesh.h:802
Distinct type for face Iterator.
Definition: FieldIterator.h:121
static const int up4_mask
Definition: HexVolMesh.h:2652
void get_delems(typename DElem::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:580
void get_center(Core::Geometry::Point &result, typename Edge::index_type idx) const
Definition: HexVolMesh.h:616
Node::index_type nodes_[4]
Definition: HexVolMesh.h:2479
double get_size(typename Cell::index_type idx) const
Definition: HexVolMesh.h:651
void fill_neighbors(Iter begin, Iter end, Functor fill_ftor)
void get_cells_from_face(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1925
static const size_t bucket_size
These are needed by the hash_map particularly.
Definition: HexVolMesh.h:2646
std::vector< unsigned char > boundary_faces_
Definition: HexVolMesh.h:2851
int get_weights(const Core::Geometry::Point &p, typename Node::array_type &l, double *w) const
Definition: HexVolMesh.h:3685
Definition: ConditionVariable.h:45
Vector project(const Vector &p) const
Definition: Transform.cc:425
double get_size(typename Node::index_type) const
Get the size of an element (length, area, volume)
Definition: HexVolMesh.h:624
index_type edge4_index() const
Definition: HexVolMesh.h:284
void get_cell_center(Core::Geometry::Point &p, INDEX idx) const
Definition: HexVolMesh.h:2383
bool locate_elem(INDEX &elem, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2232
Definition: Mesh.h:64
Point max() const
Definition: BBox.h:195
#define ASSERTMSG(condition, message)
Definition: Exception.h:113
SCIRun::mask_type mask_type
Definition: HexVolMesh.h:170
static const int low_mask
Definition: HexVolMesh.h:2717
void end(typename Node::iterator &) const
Definition: HexVolMesh.h:3549
boost::shared_ptr< SearchGridT< index_type > > elem_grid_
Definition: HexVolMesh.h:2859
edge_nt edge_table_
Definition: HexVolMesh.h:2770
PEdge(typename Node::index_type n1, typename Node::index_type n2)
Definition: HexVolMesh.h:2633
int get_weights(const Core::Geometry::Point &, typename Face::array_type &, double *) const
Definition: HexVolMesh.h:708
NodeIterator< under_type > iterator
Definition: HexVolMesh.h:178
void get_faces_from_node(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1859
int get_weights(const Core::Geometry::Point &, typename Edge::array_type &, double *) const
Definition: HexVolMesh.h:706
void get_nodes(typename Node::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:517
Definition: Persistent.h:89
index_type node1_index() const
Definition: HexVolMesh.h:238
void pre_scale(const Vector &)
Definition: Transform.cc:193
void resize_nodes(size_type s)
Definition: HexVolMesh.h:776
void compute_edges()
Definition: HexVolMesh.h:3339
void to_index(typename Edge::index_type &index, index_type i) const
Definition: HexVolMesh.h:503
static const int up_mask
Definition: HexVolMesh.h:2716
PFaceCell()
Definition: HexVolMesh.h:2466
index_type node4_index() const
Definition: HexVolMesh.h:250
const Core::Geometry::Point & point(typename Node::index_type i) const
Definition: HexVolMesh.h:2420
std::map< PFaceNode, typename Face::index_type, FaceHash > face_nt
Definition: HexVolMesh.h:2754
void get_face_center(Core::Geometry::Point &p, INDEX idx) const
Definition: HexVolMesh.h:2362
int compute_checksum(T *data, std::size_t length)
Definition: CheckSum.h:38
boost::shared_ptr< SearchGridT< index_type > > node_grid_
Definition: HexVolMesh.h:2858
void compute_elem_grid()
Definition: HexVolMesh.h:3776
std::vector< PEdgeCell > edge_ct
Definition: HexVolMesh.h:2760
double get_epsilon() const
Definition: HexVolMesh.h:468
index_type edge6_index() const
Definition: HexVolMesh.h:292
bool get_neighbors(std::vector< typename Elem::index_type > &array, typename Elem::index_type elem, typename DElem::index_type delem) const
Definition: HexVolMesh.h:680
double InverseMatrix3P(const PointVector &p, double *q)
Inline templated inverse matrix.
Definition: Locate.h:72
index_type edge8_index() const
Definition: HexVolMesh.h:300
bool get_neighbor(typename Elem::index_type &neighbor, typename Elem::index_type elem, typename DElem::index_type delem) const
Get neighbors of an element or a node.
Definition: HexVolMesh.h:671
Definition: Persistent.h:187
bool find_closest_nodes(ARRAY &nodes, const Core::Geometry::Point &p, double maxdist) const
Definition: HexVolMesh.h:1008
bool operator==(const PFaceNode &f) const
true if both have the same nodes (order does not matter)
Definition: HexVolMesh.h:2501
virtual std::string dynamic_type_name() const
Definition: HexVolMesh.h:1468
const Core::Geometry::Point & node5() const
Definition: HexVolMesh.h:337
void get_cells(typename Cell::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:560
BBox & extend(const Point &p)
Expand the bounding box to include point p.
Definition: BBox.h:98
virtual bool has_normals() const
Has this mesh normals.
Definition: HexVolMesh.h:463
void get_random_point(Core::Geometry::Point &p, typename Elem::index_type i, FieldRNG &r) const
Definition: HexVolMesh.h:3041
bool operator==(const PEdgeNode &e) const
true if both have the same nodes (order does not matter)
Definition: HexVolMesh.h:2603
std::vector< index_type > array_type
Definition: HexVolMesh.h:194
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, INDEX &elem, const Core::Geometry::Point &p, double maxdist) const
Find the closest element to a point.
Definition: HexVolMesh.h:1151
void get_faces(typename Face::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:540
bool order_face_nodes(INDEX &n1, INDEX &n2, INDEX &n3, INDEX &n4) const
Definition: HexVolMesh.h:2782
bool get_elem_neighbors(ARRAY &array, INDEX1 elem, INDEX2 delem) const
Definition: HexVolMesh.h:2018
Definition: TypeDescription.h:50
Definition: HexVolMesh.h:183
FieldHandle mesh()
Definition: BuildTDCSMatrixTests.cc:56
Definition: Mesh.h:84
Definition: Point.h:49
Face DElem
Definition: HexVolMesh.h:208
Definition: TypeDescription.h:45
#define SCISHARE
Definition: share.h:39
std::vector< const TypeDescription * > td_vec
Definition: TypeDescription.h:56
Definition: HexVolMesh.h:2568
Cell Elem
Definition: HexVolMesh.h:207
EdgeIndex< under_type > index_type
Definition: HexVolMesh.h:184
double epsilon3_
Definition: HexVolMesh.h:2874
NodeIndex< under_type > size_type
Definition: HexVolMesh.h:179
double tetrahedra_volume(const Point &p0, const Point &p1, const Point &p2, const Point &p3)
Definition: CompGeom.cc:389
double get_length(typename Edge::index_type idx) const
More specific names for get_size.
Definition: HexVolMesh.h:658
Definition: Mesh.h:45
Core::Thread::ConditionVariable synchronize_cond_
Definition: HexVolMesh.h:2863
bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, INDEX idx) const
Definition: HexVolMesh.h:783
cells_type cells_
Definition: HexVolMesh.h:2624
double det_jacobian(const VECTOR &coords, INDEX idx) const
Definition: HexVolMesh.h:811
Definition: BBox.h:46
void get_elems(typename Elem::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:570
boost::shared_ptr< Mesh > MeshHandle
Definition: DatatypeFwd.h:67
virtual int basis_order()
Definition: HexVolMesh.h:438
Definition: Mutex.h:43
bool operator<(const PFaceNode &f) const
Definition: HexVolMesh.h:2519
#define MESH_NO_NEIGHBOR
Definition: MeshTraits.h:67
Distinct type for cell Iterator.
Definition: FieldIterator.h:134
virtual void transform(const Core::Geometry::Transform &t)
Transform a field (transform all nodes using this transformation matrix)
Definition: HexVolMesh.h:3169
Node::array_type nodes_
Definition: HexVolMesh.h:2847
void get_delems(typename DElem::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:586
unsigned int mask_type
Definition: Types.h:45
bool locate_face(INDEX &face, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2206
bool inside(INDEX idx, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2423
virtual bool is_editable() const
Check whether mesh can be altered by adding nodes or elements.
Definition: HexVolMesh.h:460
#define ASSERT(condition)
Definition: Assert.h:110
void get_cells(typename Cell::array_type &array, typename Node::index_type idx) const
Definition: HexVolMesh.h:551
Core::Geometry::BBox bbox_
Definition: HexVolMesh.h:2871
virtual int begin_class(const std::string &name, int current_version)
Definition: Persistent.cc:143
virtual bool synchronize(mask_type mask)
Definition: HexVolMesh.h:3389
void compute_bounding_box()
Definition: HexVolMesh.h:3143
virtual HexVolMesh * clone() const
Definition: HexVolMesh.h:423
void get_nodes_from_edge(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1541
std::map< PEdge, typename Edge::index_type, EdgeHash > edge_ht
Definition: HexVolMesh.h:2755
const Core::Geometry::Point & node4() const
Definition: HexVolMesh.h:333
Node::index_type add_node(const Core::Geometry::Point &p)
Definition: HexVolMesh.h:753
void get_point(Core::Geometry::Point &result, typename Node::index_type index) const
Access the nodes of the mesh.
Definition: HexVolMesh.h:713
Definition: Vector.h:63
void get_nodes(typename Node::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:514
index_type edge7_index() const
Definition: HexVolMesh.h:296
index_type edge2_index() const
Definition: HexVolMesh.h:276
void set_point(const Core::Geometry::Point &point, typename Node::index_type index)
Definition: HexVolMesh.h:715
boost::unique_lock< boost::mutex > UniqueLock
Definition: ConditionVariable.h:43
double DetMatrix3P(const VectorOfPoints &p)
Inline templated determinant of matrix.
Definition: Locate.h:120
const string find_type_name(float *)
Definition: TypeName.cc:63
virtual Core::Geometry::BBox get_bounding_box() const
Get the bounding box of the field.
Definition: HexVolMesh.h:3114
Definition: Mesh.h:72
void get_node_center(Core::Geometry::Point &p, INDEX idx) const
Definition: HexVolMesh.h:2344
void hash_face(typename Node::index_type n1, typename Node::index_type n2, typename Node::index_type n3, typename Node::index_type n4, index_type combined_index, face_ht &table) const
Definition: HexVolMesh.h:3210
static const TypeDescription * face_type_description()
Definition: HexVolMesh.h:4000
static const int sz_int
These are for our own use (making the hash function.
Definition: HexVolMesh.h:2714
std::map< PFace, typename Face::index_type, FaceHash > face_ht
Definition: HexVolMesh.h:2753
double inverse_jacobian(const VECTOR &coords, INDEX idx, double *Ji) const
Definition: HexVolMesh.h:843
std::vector< index_type > array_type
Definition: HexVolMesh.h:201
bool find_closest_nodes(ARRAY1 &distances, ARRAY2 &nodes, const Core::Geometry::Point &p, double maxdist) const
Definition: HexVolMesh.h:1072
virtual void get_canonical_transform(Core::Geometry::Transform &t) const
Definition: HexVolMesh.h:3133
double get_volume(typename Cell::index_type idx) const
Definition: HexVolMesh.h:662
PFace(typename Node::index_type n1, typename Node::index_type n2, typename Node::index_type n3, typename Node::index_type n4)
Definition: HexVolMesh.h:2571
void get_center(Core::Geometry::Point &result, typename Face::index_type idx) const
Definition: HexVolMesh.h:618
std::map< PEdgeNode, typename Edge::index_type, EdgeHash > edge_nt
Definition: HexVolMesh.h:2756
Definition: HexVolMesh.h:2619
static const int sz_half_int
Definition: HexVolMesh.h:2715
virtual VMesh * vmesh()
Access point to virtual interface.
Definition: HexVolMesh.h:429
static const TypeDescription * edge_type_description()
Definition: HexVolMesh.h:3983
bool locate(typename Edge::index_type &idx, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:691
StackVector< index_type, 8 > array_type
Definition: HexVolMesh.h:180
Definition: HexVolMesh.h:190
bool get_face(typename Face::index_type &array, typename Node::index_type n1, typename Node::index_type n2, typename Node::index_type n3, typename Node::index_type n4) const
Trying figure out which face is made out of 4 nodes (?)
Definition: HexVolMesh.h:3648
void fill_cells(Iter begin, Iter end, Functor fill_ftor)
Definition: HexVolMesh.h:2981
Definition: Mesh.h:87
double scaled_jacobian_metric(INDEX idx) const
Definition: HexVolMesh.h:852
Definition: HexVolMesh.h:360
static const size_t min_buckets
Definition: HexVolMesh.h:2711
Definition: VMeshShared.h:40
void remove_node_from_grid(typename Node::index_type ci)
Definition: HexVolMesh.h:3769
void get_node_neighbors(ARRAY &array, INDEX node) const
We should optimize this function more.
Definition: HexVolMesh.h:2065
Definition: ParallelLinearAlgebraTests.cc:358
static const int top4_mask
Definition: HexVolMesh.h:2651
void get_cells_from_node(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1767
size_t operator()(const PEDGE &e) const
This is the hash function.
Definition: HexVolMesh.h:2721
Definition: SearchGridT.h:47
const char * name[]
Definition: BoostGraphExampleTests.cc:87
Basis basis_type
Definition: HexVolMesh.h:173
virtual bool has_face_normals() const
Has this mesh face normals.
Definition: HexVolMesh.h:466
void fill_points(Iter begin, Iter end, Functor fill_ftor)
Definition: HexVolMesh.h:2964
void get_faces(typename Face::array_type &array, typename Node::index_type idx) const
Definition: HexVolMesh.h:537
void est_closest_point_on_quad(Point &result, const Point &orig, const Point &p0, const Point &p1, const Point &p2, const Point &p3, const double epsilon)
Definition: CompGeom.cc:226
CellIndex< under_type > size_type
Definition: HexVolMesh.h:200
void Pio_index(Piostream &stream, index_type *data, size_type size)
Definition: Persistent.cc:606
long long size_type
Definition: Types.h:40
static const int sz_int
Definition: HexVolMesh.h:2639
std::vector< index_type > cells_type
list of all the cells this edge is in.
Definition: HexVolMesh.h:2623
double jacobian_metric(INDEX idx) const
Definition: HexVolMesh.h:874
void insert_elem_into_grid(typename Elem::index_type ci)
Definition: HexVolMesh.h:3720
Vector Cross(const Vector &v1, const Vector &v2)
Definition: Vector.h:378
index_type edge9_index() const
Definition: HexVolMesh.h:304
double ScaledDetMatrix3P(const VectorOfPoints &p)
Inline templated determinant of matrix.
Definition: Locate.h:132
void get_cells(typename Cell::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:557
Definition: Mesh.h:71
void get_normal(Core::Geometry::Vector &, typename Node::index_type) const
Normals for visualizations.
Definition: HexVolMesh.h:720
static const int mid4_mask
Definition: HexVolMesh.h:2653
Vector diagonal() const
Definition: BBox.h:198
void get_edge_center(Core::Geometry::Point &p, INDEX idx) const
Definition: HexVolMesh.h:2350
Definition: Mesh.h:81
SCIRun::index_type under_type
Definition: HexVolMesh.h:167
MeshFacadeHandle getFacade() const
Definition: HexVolMesh.h:431
void get_nodes(typename Node::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:520
void get_edges(typename Edge::array_type &array, typename Node::index_type idx) const
Definition: HexVolMesh.h:524
Definition: HexVolMesh.h:2478
void resize_elems(size_type s)
Definition: HexVolMesh.h:777
Definition: Mesh.h:74
Persistent i/o for STL containers.
Edge information.
Definition: HexVolMesh.h:2630
void get_edges_from_cell(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1656
std::vector< INDEX >::iterator iterator
Definition: SearchGridT.h:53
std::string type
Definition: Persistent.h:72
void compute_faces()
Definition: HexVolMesh.h:3259
Definition: HexVolMesh.h:216
void pwl_approx_face(std::vector< std::vector< VECTOR > > &coords, INDEX ci, unsigned int which_face, unsigned int div_per_unit) const
Definition: HexVolMesh.h:605
void to_index(typename Node::index_type &index, index_type i) const
Definition: HexVolMesh.h:501
SCIRun::size_type size_type
Definition: HexVolMesh.h:169
void get_edges(typename Edge::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:533
bool locate(typename Node::index_type &idx, const Core::Geometry::Point &p) const
Locate a point in a mesh, find which is the closest node.
Definition: HexVolMesh.h:689
VMesh * CreateVHexVolMesh(MESH *)
Definition: HexVolMesh.h:83
void get_faces(typename Face::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:547
index_type node2_index() const
Definition: HexVolMesh.h:242
Point min() const
Definition: BBox.h:192
Distinct type for face index.
Definition: FieldIndex.h:90
Definition: HexVolMesh.h:2705
Definition: Mesh.h:62
void get_nodes_from_elem(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1601
const Core::Geometry::Point & node0() const
Definition: HexVolMesh.h:317
Definition: Transform.h:53
virtual ~HexVolMesh()
Destructor.
Definition: HexVolMesh.h:2956
face_ct faces_
Definition: HexVolMesh.h:2765
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, INDEX &elem, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:1441
static PersistentTypeID hexvolmesh_typeid
These IDs are created as soon as this class will be instantiated.
Definition: HexVolMesh.h:1464
void x(double)
Definition: Vector.h:175
void insert_node_into_grid(typename Node::index_type ci)
Definition: HexVolMesh.h:3760
edge_ct edges_
Definition: HexVolMesh.h:2769
void get_nodes_from_cell(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1586
Elem::index_type add_hex(typename Node::index_type a, typename Node::index_type b, typename Node::index_type c, typename Node::index_type d, typename Node::index_type e, typename Node::index_type f, typename Node::index_type g, typename Node::index_type h)
Definition: HexVolMesh.h:3865
HexVolMesh< Basis >::index_type index_type
Definition: HexVolMesh.h:219
static Persistent * maker()
This function returns a maker for Pio.
Definition: HexVolMesh.h:1482
const Core::Geometry::Point & node2() const
Definition: HexVolMesh.h:325
index_type node5_index() const
Definition: HexVolMesh.h:254
Definition: Mesh.h:73
virtual bool unsynchronize(mask_type sync)
Definition: HexVolMesh.h:3508
void get_elems(typename Elem::array_type &array, typename Node::index_type idx) const
Definition: HexVolMesh.h:564
static const std::string make_template_id(const std::string &templateName, const std::string &templateParam)
Definition: TypeName.h:62
SCIRun::index_type index_type
Definition: HexVolMesh.h:168
bool inside(const Point &p) const
Definition: BBox.h:205
Core::Thread::Mutex synchronize_lock_
Definition: HexVolMesh.h:2862
v
Definition: readAllFields.py:42
void get_edges(typename Edge::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:530
void jacobian(const VECTOR &coords, INDEX idx, double *J) const
Definition: HexVolMesh.h:823
std::vector< Core::Geometry::Point > points_
all the nodes.
Definition: HexVolMesh.h:2459
virtual const TypeDescription * get_type_description() const
Definition: HexVolMesh.h:3959
void pre_translate(const Vector &)
Definition: Transform.cc:278
double normalize()
Definition: Vector.h:437
void get_elem_neighbors(ARRAY &array, INDEX elem) const
Definition: HexVolMesh.h:2044
Face information.
Definition: HexVolMesh.h:2464
void node_reserve(size_type s)
Definition: HexVolMesh.h:774
index_type edge1_index() const
Definition: HexVolMesh.h:272
void hash_edge(typename Node::index_type n1, typename Node::index_type n2, index_type combind_index, edge_ht &table) const
Definition: HexVolMesh.h:3315
index_type node6_index() const
Definition: HexVolMesh.h:258
void get_nodes_from_face(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1562
void get_edges_from_face(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1607
Basis basis_
Definition: HexVolMesh.h:2870
CellIterator< under_type > iterator
Definition: HexVolMesh.h:199
PEdgeNode()
Definition: HexVolMesh.h:2581
void y(double)
Definition: Vector.h:185
void get_delems(typename DElem::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:583
void interpolate(Core::Geometry::Point &pt, const VECTOR &coords, INDEX idx) const
Definition: HexVolMesh.h:792
double distance_to_line2(const Point &p, const Point &a, const Point &b, const double epsilon)
Definition: CompGeom.cc:53
Definition: HexVolMesh.h:2640
bool locate_node(INDEX &node, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2087
Distinct type for edge Iterator.
Definition: FieldIterator.h:105
mask_type synchronized_
Definition: HexVolMesh.h:2866
bool get_edge_from_nodes(INDEX &idx, ARRAY &array) const
Definition: HexVolMesh.h:1972
void get_edges(typename Edge::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:527
Definition: HexVolMesh.h:197
Definition: Mesh.h:75
void clear()
Definition: StackVector.h:65
index_type edge3_index() const
Definition: HexVolMesh.h:280
#define ASSERTFAIL(string)
Definition: Assert.h:52
static const size_t min_buckets
Definition: HexVolMesh.h:2647
static const std::string type_name(int n=-1)
Core functionality for getting the name of a templated mesh class.
Definition: HexVolMesh.h:3017
Index and Iterator types required for Mesh Concept.
Definition: HexVolMesh.h:176
void Pio(Piostream &stream, Array1< T > &array)
Definition: Array1.h:65
Some convenient simple iterators for fields.
const HexVolMesh & mesh_
Definition: HexVolMesh.h:2846
Basis & get_basis()
Get the basis class.
Definition: HexVolMesh.h:477
void get_faces(typename Face::array_type &array, typename Face::index_type idx) const
Definition: HexVolMesh.h:544
void get_elems(typename Elem::array_type &array, typename Cell::index_type idx) const
Definition: HexVolMesh.h:573
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, INDEX &elem, const Core::Geometry::Point &p) const
Find the closest element to a point.
Definition: HexVolMesh.h:1140
std::vector< Core::Geometry::Point > & get_points()
must detach, if altering points!
Definition: HexVolMesh.h:1523
void compute_node_neighbors()
Definition: HexVolMesh.h:3668
double epsilon_
Definition: HexVolMesh.h:2872
bool find_closest_elems(double &, Core::Geometry::Point &, ARRAY &, const Core::Geometry::Point &) const
Find the closest elements to a point.
Definition: HexVolMesh.h:1450
Definition: Mesh.h:80
virtual void end_class()
Definition: Persistent.cc:178
void elem_reserve(size_type s)
Definition: HexVolMesh.h:775
const Core::Geometry::Point & node1() const
Definition: HexVolMesh.h:321
bool get_face_from_nodes(INDEX &idx, ARRAY &array) const
Definition: HexVolMesh.h:1951
void get_edges_from_elem(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1696
long long index_type
Definition: Types.h:39
std::vector< under_type > cells_
each 8 indecies make up a Hex
Definition: HexVolMesh.h:2461
Definition: Mesh.h:83
double epsilon2_
Definition: HexVolMesh.h:2873
void size(typename Node::size_type &) const
Get the iteration sizes.
Definition: HexVolMesh.h:3558
face_nt face_table_
Definition: HexVolMesh.h:2766
void resize(size_t size, const value_type &val=value_type())
Definition: StackVector.h:61
void get_normal(Core::Geometry::Vector &result, VECTOR &coords, INDEX1 eidx, INDEX2 fidx) const
Get the normals at the outside of the element.
Definition: HexVolMesh.h:725
Definition: Mesh.h:76
std::vector< std::vector< typename Cell::index_type > > node_neighbors_
Definition: HexVolMesh.h:2850
static const TypeDescription * cell_type_description()
Definition: HexVolMesh.h:4017
FaceIndex< under_type > index_type
Definition: HexVolMesh.h:191
bool find_closest_node(double &pdist, Core::Geometry::Point &result, INDEX &node, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:896
HexVolMesh()
Construct a new mesh.
Definition: HexVolMesh.h:2891
void operator()()
Definition: HexVolMesh.h:366
virtual int dimensionality() const
Topological dimension.
Definition: HexVolMesh.h:441
double get_area(typename Face::index_type idx) const
Definition: HexVolMesh.h:660
bool operator()(const PEDGE &e1, const PEDGE &e2) const
This should return less than rather than equal to.
Definition: HexVolMesh.h:2729
void reset()
Definition: BBox.h:95
bool locate(typename Elem::index_type &elem, std::vector< double > &coords, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:698
double get_size(typename Face::index_type idx) const
Definition: HexVolMesh.h:637
Definition: Persistent.h:64
Node::index_type add_point(const Core::Geometry::Point &p)
Add a new node to the mesh.
Definition: HexVolMesh.h:3888
static const size_t bucket_size
These are needed by the hash_map particularly.
Definition: HexVolMesh.h:2710
void get_nodes(typename Node::array_type &array, typename Node::index_type idx) const
Get the child topology elements of the given topology.
Definition: HexVolMesh.h:511
boost::shared_ptr< VMesh > vmesh_
Pointer to virtual interface.
Definition: HexVolMesh.h:2877
useful functors
Definition: HexVolMesh.h:2831
void get_edges_from_node(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1779
#define HEXVOLMESH_VERSION
Definition: HexVolMesh.h:3907
static const int sz_quarter_int
These are for our own use (making the hash function.
Definition: HexVolMesh.h:2650
static const TypeDescription * elem_type_description()
Definition: HexVolMesh.h:1478
bool get_elem_neighbor(INDEX1 &neighbor, INDEX1 elem, INDEX2 delem) const
Definition: HexVolMesh.h:1998
double get_size(typename Edge::index_type idx) const
Definition: HexVolMesh.h:627
CellIndex< under_type > index_type
Definition: HexVolMesh.h:198
Distinct type for edge index.
Definition: FieldIndex.h:81
void operator()(typename Edge::index_type e)
Definition: HexVolMesh.h:2838
bool locate_elem(INDEX &elem, ARRAY &coords, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:2300
void compute_node_grid()
Definition: HexVolMesh.h:3812
friend class VHexVolMesh
Make sure the virtual interface has access.
Definition: HexVolMesh.h:161
int n
Definition: eab.py:9
PFaceNode(typename Node::index_type n1, typename Node::index_type n2, typename Node::index_type n3, typename Node::index_type n4)
Definition: HexVolMesh.h:2490
bool locate_elems(ARRAY &array, const Core::Geometry::BBox &b) const
Definition: HexVolMesh.h:2269
static const TypeDescription * node_type_description()
Definition: HexVolMesh.h:3966
Elem::index_type add_elem(ARRAY a)
Add a new element to the mesh.
Definition: HexVolMesh.h:758
void to_index(typename Cell::index_type &index, index_type i) const
Definition: HexVolMesh.h:507
size_t operator()(const PFACE &f) const
This is the hash function.
Definition: HexVolMesh.h:2658
PFaceNode()
4 nodes makes a face.
Definition: HexVolMesh.h:2481
std::vector< std::vector< typename Node::index_type > > & nbor_vec_
Definition: HexVolMesh.h:2845
FaceIterator< under_type > iterator
Definition: HexVolMesh.h:192
bool locate(typename Face::index_type &idx, const Core::Geometry::Point &p) const
Definition: HexVolMesh.h:693
void get_center(Core::Geometry::Point &result, typename Cell::index_type idx) const
Definition: HexVolMesh.h:620
void get_faces_from_cell(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1702
void fill_data(Iter begin, Iter end, Functor fill_ftor)
#define DEBUG_CONSTRUCTOR(type)
Definition: Debug.h:64
void io(Piostream &stream)
Persistent I/O.
Definition: Mesh.cc:387
bool shared() const
Definition: HexVolMesh.h:2626
NodeIndex< under_type > index_type
Definition: HexVolMesh.h:177
void get_cells(typename Cell::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:554
index_type node0_index() const
Definition: HexVolMesh.h:234
int compute_checksum()
Definition: HexVolMesh.h:2882
bool operator<(const PEdgeNode &e) const
Definition: HexVolMesh.h:2610
void remove_elem_from_grid(typename Elem::index_type ci)
Definition: HexVolMesh.h:3742
index_type cells_[2]
Definition: HexVolMesh.h:2475
bool get_cell_from_nodes(INDEX &, ARRAY &) const
Definition: HexVolMesh.h:1945
void z(double)
Definition: Vector.h:195
bool clear_synchronization()
Definition: HexVolMesh.h:3515
void get_neighbors(typename Elem::array_type &array, typename Elem::index_type elem) const
Definition: HexVolMesh.h:684
boost::shared_ptr< MeshFacade< VMesh > > MeshFacadeHandle
Definition: MeshTraits.h:61
FaceIndex< under_type > size_type
Definition: HexVolMesh.h:193
std::vector< PFaceCell > face_ct
Definition: HexVolMesh.h:2759
Definition: VMesh.h:53
mask_type synchronizing_
Definition: HexVolMesh.h:2868
static const int low4_mask
Definition: HexVolMesh.h:2654
void to_index(typename Face::index_type &index, index_type i) const
Definition: HexVolMesh.h:505
bool find_closest_node(double &pdist, Core::Geometry::Point &result, INDEX &node, const Core::Geometry::Point &p, double maxdist) const
Definition: HexVolMesh.h:903
const Core::Geometry::Point & node3() const
Definition: HexVolMesh.h:329
void set_nodes_by_elem(ARRAY &array, INDEX idx)
Definition: HexVolMesh.h:1990
index_type node7_index() const
Definition: HexVolMesh.h:262
index_type node3_index() const
Definition: HexVolMesh.h:246
const Core::Geometry::Point & node6() const
Definition: HexVolMesh.h:341
Node::index_type add_find_point(const Core::Geometry::Point &p, double err=1.0e-6)
Definition: HexVolMesh.h:3849
Definition: HexVolMesh.h:77
bool operator()(const PFACE &f1, const PFACE &f2) const
This should return less than rather than equal to.
Definition: HexVolMesh.h:2698
EdgeIterator< under_type > iterator
Definition: HexVolMesh.h:185
void get_elems(typename Elem::array_type &array, typename Edge::index_type idx) const
Definition: HexVolMesh.h:567
void pwl_approx_edge(std::vector< VECTOR > &coords, INDEX ci, unsigned int which_edge, unsigned int div_per_unit) const
Definition: HexVolMesh.h:594
int size
Definition: eabLatVolData.py:2
std::vector< index_type > array_type
Definition: HexVolMesh.h:187
static MeshHandle mesh_maker()
This function returns a handle for the virtual interface.
Definition: HexVolMesh.h:1484
Node::index_type nodes_[2]
Definition: HexVolMesh.h:2579
void get_cells_from_edge(ARRAY &array, INDEX idx) const
Definition: HexVolMesh.h:1914
const Core::Geometry::Point & node7() const
Definition: HexVolMesh.h:345
#define DEBUG_DESTRUCTOR(type)
Definition: Debug.h:65
const TypeDescription * get_type_description(Core::Basis::ConstantBasis< T > *)
Definition: Constant.h:209
index_type edge11_index() const
Definition: HexVolMesh.h:312
ElemData(const HexVolMesh< Basis > &msh, const index_type ind)
Definition: HexVolMesh.h:221
bool elem_locate(INDEX &elem, MESH &msh, const Core::Geometry::Point &p)
General case locate, search each elem.
Definition: Mesh.h:188