1 /*=========================================================================
2 
3  Program:   Visualization Toolkit
4  Module:    vtkAMRResampleFilter.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE.  See the above copyright notice for more information.
13 
14  =========================================================================*/
15 /**
16  * @class   vtkAMRResampleFilter
17  *
18  *
19  *  This filter is a concrete instance of vtkMultiBlockDataSetAlgorithm and
20  *  provides functionality for extracting portion of the AMR dataset, specified
21  *  by a bounding box, in a uniform grid of the desired level of resolution.
22  *  The resulting uniform grid is stored in a vtkMultiBlockDataSet where the
23  *  number of blocks correspond to the number of processors utilized for the
24  *  operation.
25  *
26  * @warning
27  *  Data of the input AMR dataset is assumed to be cell-centered.
28  *
29  * @sa
30  *  vtkOverlappingAMR, vtkUniformGrid
31  */
32 
33 #ifndef vtkAMRResampleFilter_h
34 #define vtkAMRResampleFilter_h
35 
36 #include "vtkFiltersAMRModule.h" // For export macro
37 #include "vtkMultiBlockDataSetAlgorithm.h"
38 #include <vector> // For STL vector
39 
40 class vtkInformation;
41 class vtkInformationVector;
42 class vtkUniformGrid;
43 class vtkOverlappingAMR;
44 class vtkMultiBlockDataSet;
45 class vtkMultiProcessController;
46 class vtkFieldData;
47 class vtkCellData;
48 class vtkPointData;
49 class vtkIndent;
50 
51 class vtkAMRBox;
52 class VTKFILTERSAMR_EXPORT vtkAMRResampleFilter : public vtkMultiBlockDataSetAlgorithm
53 {
54 public:
55   static vtkAMRResampleFilter* New();
56   vtkTypeMacro(vtkAMRResampleFilter, vtkMultiBlockDataSetAlgorithm);
57   void PrintSelf(ostream& oss, vtkIndent indent) override;
58 
59   ///@{
60   /**
61    * Set & Get macro for the number of samples (cells) in each dimension.
62    * Nominal value for the number of samples is 10x10x10.
63    */
64   vtkSetVector3Macro(NumberOfSamples, int);
65   vtkGetVector3Macro(NumberOfSamples, int);
66   ///@}
67 
68   ///@{
69   /**
70    * Set & Get macro for the TransferToNodes flag
71    */
72   vtkSetMacro(TransferToNodes, int);
73   vtkGetMacro(TransferToNodes, int);
74   ///@}
75 
76   ///@{
77   /**
78    * Set & Get macro to allow the filter to operate in both demand-driven
79    * and standard modes
80    */
81   vtkSetMacro(DemandDrivenMode, int);
82   vtkGetMacro(DemandDrivenMode, int);
83   ///@}
84 
85   ///@{
86   /**
87    * Set & Get macro for the number of subdivisions
88    */
89   vtkSetMacro(NumberOfPartitions, int);
90   vtkGetMacro(NumberOfPartitions, int);
91   ///@}
92 
93   ///@{
94   /**
95    * Set and Get the min corner
96    */
97   vtkSetVector3Macro(Min, double);
98   vtkGetVector3Macro(Min, double);
99   ///@}
100 
101   ///@{
102   /**
103    * Set and Get the max corner
104    */
105   vtkSetVector3Macro(Max, double);
106   vtkGetVector3Macro(Max, double);
107   ///@}
108 
109   ///@{
110   /**
111    * Set & Get macro for the number of subdivisions
112    */
113   vtkSetMacro(UseBiasVector, bool);
114   vtkGetMacro(UseBiasVector, bool);
115   ///@}
116 
117   ///@{
118   /**
119    * Set and Get the bias vector.  If UseBiasVector is true
120    * then the largest component of this vector can not have
121    * the max number of samples
122    */
123   vtkSetVector3Macro(BiasVector, double);
124   vtkGetVector3Macro(BiasVector, double);
125   ///@}
126 
127   ///@{
128   /**
129    * Set & Get macro for the multi-process controller
130    */
131   vtkSetMacro(Controller, vtkMultiProcessController*);
132   vtkGetMacro(Controller, vtkMultiProcessController*);
133   ///@}
134 
135   // Standard pipeline routines
136 
137   /**
138    * Gets the metadata from upstream module and determines which blocks
139    * should be loaded by this instance.
140    */
141   int RequestInformation(vtkInformation* rqst, vtkInformationVector** inputVector,
142     vtkInformationVector* outputVector) override;
143 
144   int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
145   int FillInputPortInformation(int port, vtkInformation* info) override;
146   int FillOutputPortInformation(int port, vtkInformation* info) override;
147 
148   /**
149    * Performs upstream requests to the reader
150    */
151   int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
152 
153 protected:
154   vtkAMRResampleFilter();
155   ~vtkAMRResampleFilter() override;
156 
157   vtkOverlappingAMR* AMRMetaData;
158   vtkMultiBlockDataSet* ROI; // Pointer to the region of interest.
159   int NumberOfSamples[3];
160   int GridNumberOfSamples[3];
161   double Min[3];
162   double Max[3];
163   double GridMin[3];
164   double GridMax[3];
165   int LevelOfResolution;
166   int NumberOfPartitions;
167   int TransferToNodes;
168   int DemandDrivenMode;
169   vtkMultiProcessController* Controller;
170   bool UseBiasVector;
171   double BiasVector[3];
172 
173   // Debugging Stuff
174   int NumberOfBlocksTestedForLevel;
175   int NumberOfBlocksTested;
176   int NumberOfBlocksVisSkipped;
177   int NumberOfTimesFoundOnDonorLevel;
178   int NumberOfTimesLevelUp;
179   int NumberOfTimesLevelDown;
180   int NumberOfFailedPoints;
181   double AverageLevel;
182 
183   std::vector<int> BlocksToLoad; // Holds the ids of the blocks to load.
184 
185   /**
186    * Checks if this filter instance is running on more than one processes
187    */
188   bool IsParallel();
189 
190   /**
191    * Given the Region ID this function returns whether or not the region
192    * belongs to this process or not.
193    */
194   bool IsRegionMine(const int regionIdx);
195 
196   /**
197    * Given the Region ID, this method computes the corresponding process ID
198    * that owns the region based on static block-cyclic distribution.
199    */
200   int GetRegionProcessId(const int regionIdx);
201 
202   /**
203    * Given a cell index and a grid, this method computes the cell centroid.
204    */
205   void ComputeCellCentroid(vtkUniformGrid* g, const vtkIdType cellIdx, double c[3]);
206 
207   /**
208    * Given the source cell data of an AMR grid, this method initializes the
209    * field values, i.e., the number of arrays with the prescribed size. Note,
210    * the size must correspond to the number of points if node-centered or the
211    * the number of cells if cell-centered.
212    */
213   void InitializeFields(vtkFieldData* f, vtkIdType size, vtkCellData* src);
214 
215   /**
216    * Copies the data to the target from the given source.
217    */
218   void CopyData(vtkFieldData* target, vtkIdType targetIdx, vtkCellData* src, vtkIdType srcIdx);
219 
220   /**
221    * Given a query point q and a candidate donor grid, this method checks for
222    * the corresponding donor cell containing the point in the given grid.
223    */
224   bool FoundDonor(double q[3], vtkUniformGrid*& donorGrid, int& cellIdx);
225 
226   /**
227    * Given a query point q and a target level, this method finds a suitable
228    * grid at the given level that contains the point if one exists. If a grid
229    * is not found, donorGrid is set to nullptr.
230    */
231   bool SearchForDonorGridAtLevel(double q[3], vtkOverlappingAMR* amrds, unsigned int level,
232     unsigned int& gridId, int& donorCellIdx);
233 
234   /**
235    * Finds the AMR grid that contains the point q. If donorGrid points to a
236    * valid AMR grid in the hierarchy, the algorithm will search this grid
237    * first. The method returns the ID of the cell w.r.t. the donorGrid that
238    * contains the probe point q.
239    */
240   int ProbeGridPointInAMR(double q[3], unsigned int& donorLevel, unsigned int& donorGridId,
241     vtkOverlappingAMR* amrds, unsigned int maxLevel, bool hadDonorGrid);
242 
243   /**
244    * Finds the AMR grid that contains the point q. If donorGrid points to a
245    * valid AMR grid in the hierarchy, the algorithm will search this grid
246    * first. The method returns the ID of the cell w.r.t. the donorGrid that
247    * contains the probe point q. - Makes use of Parent/Child Info
248    */
249   int ProbeGridPointInAMRGraph(double q[3], unsigned int& donorLevel, unsigned int& donorGridId,
250     vtkOverlappingAMR* amrds, unsigned int maxLevel, bool useCached);
251 
252   /**
253    * Transfers the solution from the AMR dataset to the cell-centers of
254    * the given uniform grid.
255    */
256   void TransferToCellCenters(vtkUniformGrid* g, vtkOverlappingAMR* amrds);
257 
258   /**
259    * Transfer the solution from the AMR dataset to the nodes of the
260    * given uniform grid.
261    */
262   void TransferToGridNodes(vtkUniformGrid* g, vtkOverlappingAMR* amrds);
263 
264   /**
265    * Transfers the solution
266    */
267   void TransferSolution(vtkUniformGrid* g, vtkOverlappingAMR* amrds);
268 
269   /**
270    * Extract the region (as a multiblock) from the given AMR dataset.
271    */
272   void ExtractRegion(
273     vtkOverlappingAMR* amrds, vtkMultiBlockDataSet* mbds, vtkOverlappingAMR* metadata);
274 
275   /**
276    * Checks if the AMR block, described by a uniform grid, is within the
277    * bounds of the ROI perscribed by the user.
278    */
279   bool IsBlockWithinBounds(double* grd);
280 
281   /**
282    * Given a user-supplied region of interest and the metadata by a module
283    * upstream, this method generates the list of linear AMR block indices
284    * that need to be loaded.
285    */
286   void ComputeAMRBlocksToLoad(vtkOverlappingAMR* metadata);
287 
288   /**
289    * Computes the region parameters
290    */
291   void ComputeRegionParameters(
292     vtkOverlappingAMR* amrds, int N[3], double min[3], double max[3], double h[3]);
293 
294   /**
295    * This method accesses the domain boundaries
296    */
297   void GetDomainParameters(vtkOverlappingAMR* amr, double domainMin[3], double domainMax[3],
298     double h[3], int dims[3], double& rf);
299 
300   /**
301    * Checks if the domain and requested region intersect.
302    */
303   bool RegionIntersectsWithAMR(
304     double domainMin[3], double domainMax[3], double regionMin[3], double regionMax[3]);
305 
306   /**
307    * This method adjust the numbers of samples in the region, N, if the
308    * requested region falls outside, but, intersects the domain.
309    */
310   void AdjustNumberOfSamplesInRegion(const double Rh[3], const bool outside[6], int N[3]);
311 
312   /**
313    * This method computes the level of resolution based on the number of
314    * samples requested, N, the root level spacing h0, the length of the box,
315    * L (actual length after snapping) and the refinement ratio.
316    */
317   void ComputeLevelOfResolution(
318     const int N[3], const double h0[3], const double L[3], const double rf);
319 
320   /**
321    * This method snaps the bounds s.t. they are within the interior of the
322    * domain described the root level uniform grid with h0, domainMin and
323    * domain Max. The method computes and returns the new min/max bounds and
324    * the corresponding ijkmin/ijkmax coordinates w.r.t. the root level.
325    */
326   void SnapBounds(const double h0[3], const double domainMin[3], const double domainMax[3],
327     const int dims[3], bool outside[6]);
328 
329   /**
330    * This method computes and adjusts the region parameters s.t. the requested
331    * region always fall within the AMR region and the number of samples is
332    * adjusted if the region of interest moves outsided the domain.
333    */
334   void ComputeAndAdjustRegionParameters(vtkOverlappingAMR* amrds, double h[3]);
335 
336   /**
337    * This method gets the region of interest as perscribed by the user.
338    */
339   void GetRegion(double h[3]);
340 
341   /**
342    * Checks if two uniform grids intersect.
343    */
344   bool GridsIntersect(double* g1, double* g2);
345 
346   /**
347    * Returns a reference grid from the amrdataset.
348    */
349   vtkUniformGrid* GetReferenceGrid(vtkOverlappingAMR* amrds);
350 
351   /**
352    * Writes a uniform grid to a file. Used for debugging purposes.
353    * void WriteUniformGrid( vtkUniformGrid *g, std::string prefix );
354    * void WriteUniformGrid(
355    * double origin[3], int dims[3], double h[3],
356    * std::string prefix );
357    */
358 
359   /**
360    * Find a descendant of the specified grid that contains the point.
361    * If none is found then the original grid information is returned.
362    * The search is limited to levels < maxLevel
363    */
364   void SearchGridDecendants(double q[3], vtkOverlappingAMR* amrds, unsigned int maxLevel,
365     unsigned int& level, unsigned int& gridId, int& id);
366 
367   /**
368    * Find an ancestor of the specified grid that contains the point.
369    * If none is found then the original grid information is returned
370    */
371   bool SearchGridAncestors(
372     double q[3], vtkOverlappingAMR* amrds, unsigned int& level, unsigned int& gridId, int& id);
373 
374 private:
375   vtkAMRResampleFilter(const vtkAMRResampleFilter&) = delete;
376   void operator=(const vtkAMRResampleFilter&) = delete;
377 };
378 
379 #endif /* vtkAMRResampleFilter_h */
380