intersect_boxes.h
Go to the documentation of this file.
1 #ifndef INTERSECT_BOXES_H
2 #define INTERSECT_BOXES_H
3 
4 // ============================================================================
5 
6 #include <cmath>
7 #include <type_traits>
8 #include <vector>
9 
10 #include "wonton/support/CoordinateSystem.h"
11 #include "wonton/support/Point.h"
12 
14 
15 // ============================================================================
16 
17 namespace Portage {
18 
25 
26 template <int D, typename SourceMeshType, typename TargetMeshType,
27  class CoordSys = Wonton::DefaultCoordSys>
29 
30  public:
31 
33  IntersectBoxes() = delete;
34 
36  IntersectBoxes(const SourceMeshType& source_mesh,
37  const TargetMeshType& target_mesh)
38  : sourceMeshWrapper(source_mesh),
39  targetMeshWrapper(target_mesh) {
40  // TODO: The mesh wrappers need to expose the coordinate systems in some
41  // way. Then we can assert that the coordinate systems are the same.
42  // The problem is that some mesh wrappers won't have a coordinate
43  // system, so there would then have to be some way to check that and
44  // then declare that Cartesian is the default.
45  //static_assert(std::is_same<>::value);
46  }
47 
49  IntersectBoxes& operator= (const IntersectBoxes&) = delete;
50 
56  std::vector<Portage::Weights_t> operator() (
57  const int tgt_cell, const std::vector<int>& src_cells) const;
58 
59  private:
60 
62  const SourceMeshType& sourceMeshWrapper;
63 
65  const TargetMeshType& targetMeshWrapper;
66 
67 }; // class IntersectBoxes
68 
69 
70 // ============================================================================
71 // Callable operator
72 template <int D, typename SourceMeshType, typename TargetMeshType,
73  class CoordSys>
74 std::vector<Portage::Weights_t>
76  const int tgt_cell, const std::vector<int>& src_cells) const {
77 
78  // Get bounding box for target box
79  Wonton::Point<D> tlo, thi;
80  targetMeshWrapper.cell_get_bounds(tgt_cell, &tlo, &thi);
81 
82  // Allocate storage for moments
83  int nsrc = src_cells.size();
84  std::vector<Portage::Weights_t> sources_and_weights(nsrc);
85 
86  // Loop over source boxes and compute moments
87  int ninserted = 0;
88  for (int i = 0; i < nsrc; ++i) {
89  int s = src_cells[i];
90 
91  // Get source cell bounding box
92  Wonton::Point<D> slo, shi;
93  sourceMeshWrapper.cell_get_bounds(s, &slo, &shi);
94 
95  // Compute intersection and volume
96  Wonton::Point<D> ilo, ihi; // bounding box of intersection
97  double volume = 1.;
98  for (int d = 0; d < D; ++d) {
99  ilo[d] = std::max(slo[d], tlo[d]);
100  ihi[d] = std::min(shi[d], thi[d]);
101  double delta = std::max(ihi[d] - ilo[d], 0.);
102  volume *= delta;
103  }
104 
105  // If the intersection volume is zero, don't bother computing the moments
106  // because they will also be zero, and don't bother inserting into the list
107  // of actually intersecting boxes.
108  if (volume <= 0.) continue;
109 
110  // At this point the two boxes actually intersect and we need to compute
111  // moments and insert into the list.
112 
113  // Save the source cell ID
114  auto & this_wt = sources_and_weights[ninserted];
115  this_wt.entityID = s;
116 
117  // Compute moments
118  // TODO: How many orders of moments do we need to provide? For first-order
119  // interpolation, we only need zeroth moments; for second-order
120  // interpolation, we need up through first moments; and so on.
121  // Unfortunately, the intersector doesn't currently know what order
122  // of interpolation is needed. So we'll just have to hard-code this
123  // for now, assuming second-order interpolation for lack of a better
124  // choice.
125  Wonton::Point<D> first_moments;
126  for (int d = 0; d < D; ++d) {
127  const auto ibar = 0.5 * (ilo[d] + ihi[d]);
128  first_moments[d] = ibar * volume;
129  }
130 
131  // Correct for coordinate system
132  // -- Instead of calculating extra moments, use the bounding box to
133  // explicitly update the moments. But this only works if your cells are
134  // axis-aligned boxes. In other words: this is an optimization for
135  // intersect_boxes, rather than a general-purpose tool for all
136  // intersectors. Currently only zeroth and first moments have this
137  // optimization, but they could be computed and implemented for
138  // higher-order moments.
139  CoordSys::modify_volume(volume, ilo, ihi);
140  CoordSys::modify_first_moments(first_moments, ilo, ihi);
141 
142  // Save weights (moments)
143  auto & weights = this_wt.weights;
144  weights.resize(1+D);
145  weights[0] = volume;
146  for (int d = 0; d < D; ++d) {
147  weights[1+d] = first_moments[d];
148  }
149 
150  // Increment the count, because we've now inserted a new entry
151  ++ninserted;
152 
153  } // for i
154 
155  // Not all source cells provided necessary actually intersect.
156  sources_and_weights.resize(ninserted);
157 
158  return sources_and_weights;
159 
160 } // operator()
161 
162 
163 } // namespace Portage
164 
165 #endif // INTERSECT_BOXES_H
IntersectBoxes(const SourceMeshType &source_mesh, const TargetMeshType &target_mesh)
Constructor with meshes.
Definition: intersect_boxes.h:36
IntersectBoxes & operator=(const IntersectBoxes &)=delete
Assignment operator (disabled)
std::vector< Portage::Weights_t > operator()(const int tgt_cell, const std::vector< int > &src_cells) const
Intersect control volume of a target box with control volumes of a set of source boxes.
Definition: intersect_boxes.h:75
IntersectBoxes()=delete
Default constructor (disabled)
Definition: coredriver.h:42
Definition: intersect_boxes.h:28