HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CE_Multigrid.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: CE_Multigrid.h ( CE Library, C++)
7  *
8  * COMMENTS: Compute Engine Multigrid solver
9  */
10 
11 #ifndef __CE_Multigrid__
12 #define __CE_Multigrid__
13 
14 #include "CE_Grid.h"
15 
16 #include <UT/UT_Vector3.h>
17 
18 /// This class provides a specializaion of CE_Grid that can solve the 2D or
19 /// 3D Poisson equation using the multigrid algorithm, running on an OpenCL
20 /// device. It's interface closely matches that of UT_MultigridArray.
22 {
23 public:
24  CE_Multigrid();
25  ~CE_Multigrid() override;
26 
27  CE_Multigrid(const CE_Multigrid &) = default;
28  CE_Multigrid &operator=(const CE_Multigrid &) = default;
29 
30  /// Initialize array to given size, spacing, and boundary conditions.
31  void init( const UT_Vector3I &res,
32  const UT_Vector3 &spacing,
33  const UT_Vector3I &boundaries_neg,
34  const UT_Vector3I &boundaries_pos,
35  int level = 0,
36  UT_Vector3I odd_coarsenings = UT_Vector3I(0, 0, 0));
37 
38  /// Initializes this grid from the provided UT_VoxelArray, assuming the
39  /// provided grid spacing.
40  void initFromVoxels(const UT_VoxelArrayF &f,
41  const UT_Vector3 &spacing,
42  const UT_Vector3I &boundaries_neg,
43  const UT_Vector3I &boundaries_pos);
44 
45  /// Update the grid's ghost cells with values that enforce the boundary
46  /// conditions at its particular level in the multigrid hierarchy.
47  /// If struts is true, ghost cells that are outside two or more of the axes
48  /// are also updated (like + in the following diagram, where * represent the
49  /// ghost cells that are filled in regardless of the value of struts).
50  /// +*************+
51  /// * *
52  /// * ACTUAL GRID *
53  /// * *
54  /// +*************+
55  void updateBoundaryConditions(bool struts = false) const;
56 
57  /// Calculates the maximum coarse grid elements in the coarsest grid, based
58  /// on the min_per_axis parameter.
59  int getMaxCoarse(int min_per_axis) const;
60 
61  /// Returns a grid's level within the multigrid hierarchy.
62  int getLevel() const { return myLevel; }
63 
64  /// Returns a vector containing the odd/even parity for each axis.
66  {
67  UT_Vector3I parity;
68  for (int i = 0; i < 3; i++)
69  parity[i] = getRes(i) % 2;
70  return parity;
71  }
72 
73  /// Initializes this to be the same dimensions, boundary conditions,
74  /// etc, of the given grid.
75  void match(const CE_Multigrid &src);
76 
77  /// Computes rhe residual r = b - A * x, where b == *this
78  void subtractApplyLaplacian(CE_Multigrid& x, CE_Multigrid &r) const;
79 
80 
81  /// Computes the inf and 2-norm of the residual r = b - A * x,
82  /// where b == *this.
83  void computeResidualNorms(const CE_Multigrid &x,
84  fpreal64 &norminf, fpreal64 &norm2) const;
85 
86  /// Performs red-black Gauss-Seidel smoothing, where b
87  /// == *this, and the implicit matrix is the Laplacian operator. If
88  /// use_small is true, this use callsmoothLaplacianGaussSeidelSmall() if
89  /// possible.
90  void smoothLaplacianGaussSeidel(CE_Multigrid &x, int iterations = 1,
91  bool use_small=true) const;
92 
93  /// Performs red-black Gauss-Seidel smoothing, using a kernel that only
94  /// works when the entire grid can fit in one workgroup on the OpenCL
95  /// device. Returns false if the criteria to run are not met.
96  bool smoothLaplacianGaussSeidelSmall(CE_Multigrid &x,
97  int iterations = 1) const;
98 
99  /// Directly solve the Poisson equation that this grid represents. This
100  /// function should only be called for small grids. At the moment this
101  /// always calls smoothLaplacianGaussSeidelSmall() with a large
102  /// number of iterations.
103  void directSolve(CE_Multigrid &x) const;
104 
105  /// Performs coarsening using full-weighting along one axis.
106  /// On output @code uh.getReas(axis) == getRes(axis) / 2 @endcode
107  void coarsenAlongAxis(CE_Multigrid& uh, int axis) const;
108 
109  /// Coarsen this grid into a lower resolution version of the grid.
110  UT_Vector3I coarsen(int min_per_axis, CE_Multigrid &uh) const;
111 
112  /// Interpolate this array into u using inverse of full-weighting along one
113  /// axis. On output
114  /// @code u.getRes(axis) == getRes(axis) * 2 + parity[axis] @endcode
115  void interpolateAlongAxis(CE_Multigrid& u, int axis) const;
116 
117 
118  /// Interpolate this grid into a fine version of the grid.
119  /// coarsen_axis is a vector of booleans specifying which axes to
120  /// interpolate
121  /// Where interpolate_axis[axis] is true, ensure that
122  /// @code u[axis] = getRes(axis) * 2 + parity[axis] @endcode
123  void interpolate(const UT_Vector3I &interpolate_axis,
124  const UT_Vector3I &parity,
125  CE_Multigrid &u) const;
126 
127  /// Perform recursive V-cycle for multigrid algorithm, until reaching
128  /// numElements() < maxcoarse,
129  /// at which point a direct solve is done using directSolve.. At
130  /// each level, n_smooth_down and n_smooth_up iterations of Gauss-Seidel
131  /// smoothing are done, unless smooth_top_level_down is false, in which
132  /// case no smoothing is done for the top-level grid on the down-cycle. This
133  /// can be used as an optimization when calling vcycle iteratively; the
134  /// previous vcycle call will have smoothed the top-level grid as its last
135  /// step, so you can often skip smoothing that same grid on the next vcycle
136  /// without loss of convergence.
137  void vcycle(int min_per_axis, int n_smooth_down, int n_smooth_up,
138  CE_Multigrid &x, bool smooth_top_level_down = true) const;
139 
140  /// Performs recursive Full Multigrid to generate an initial guess for the
141  /// solution of the Poisson equation represented by this array. At
142  /// each level, n_smooth_down and n_smooth_up iterations of smoothing are
143  /// done.
144  void fullMultigrid(int min_per_axis, int n_smooth_down,
145  int n_smooth_up, CE_Multigrid &x) const;
146 
147  /// Iteratively solve the Poisson equation, assuming *this is the right
148  /// hand side. This function will do at least miniter iterations, then
149  /// continue to iterate until the 2-norm of the residual has
150  /// been reduced by reltol, the inf-norm of the residual is below abstol,
151  /// or maxiters is reached.
152  /// The optional resnorm0 and resnorm2 parameters will contain the
153  /// 0- and 2-norms of the residuals for each iteration.
154  /// If start_fmg is true, the first iteration will be full-multigrid;
155  /// otherwise, only v-cycles are used.
156  int solvePoisson(fpreal64 abstol, fpreal64 reltol, int miniter, int maxiter,
157  CE_Multigrid &x,
158  UT_ValArray<fpreal64> *resnorminf,
159  UT_ValArray<fpreal64> *resnorm2,
160  bool finish_between_iters = false,
161  bool start_fmg = true) const;
162 
163 protected:
164  /// Coarsen this grid into a lower resolution version of the grid, by explicitly
165  /// coarsening each axis sequentially.
166  UT_Vector3I coarsenByAxis(int min_per_axis, CE_Multigrid &uh) const;
167  /// Interpolate this grid into a fine version of the grid. This version explicitly
168  /// interpolates each axis sequentially.
169  void interpolateByAxis(const UT_Vector3I &interpolate_axis,
170  const UT_Vector3I &parity,
171  CE_Multigrid &u) const;
172 
173 protected:
174  void initLaplacian();
175 
176  fpreal32 myDiag, myOmega;
178  UT_Vector3I myBoundariesNeg, myBoundariesPos;
179  UT_Vector3 myBoundModNeg, myBoundModPos;
180  UT_Vector3 myBoundAdjModNeg, myBoundAdjModPos;
181  UT_Vector3 myDiagModNeg, myDiagModPos;
182  int myLevel;
183  bool myAllOpen, myAllClosed;
185 };
186 
187 
188 
189 #endif
#define CE_API
Definition: CE_API.h:13
UT_Vector3 myBoundModPos
Definition: CE_Multigrid.h:179
GLint level
Definition: glcorearb.h:108
void match(const CE_Grid &src)
Match the src CE_Grid in terms of size and border conditions.
fpreal32 myOmega
Definition: CE_Multigrid.h:176
UT_Vector3I getParity() const
Returns a vector containing the odd/even parity for each axis.
Definition: CE_Multigrid.h:65
UT_Vector3T< int64 > UT_Vector3I
float fpreal32
Definition: SYS_Types.h:200
double fpreal64
Definition: SYS_Types.h:201
int getLevel() const
Returns a grid's level within the multigrid hierarchy.
Definition: CE_Multigrid.h:62
GLfloat f
Definition: glcorearb.h:1926
UT_Vector3I myOddCoarsenings
Definition: CE_Multigrid.h:184
CE_Grid & operator=(const CE_Grid &src)
Assign to this, equivalent to match(src), followed by copyData(src).
UT_Vector3 myDiagModPos
Definition: CE_Multigrid.h:181
UT_Vector3I myBoundariesPos
Definition: CE_Multigrid.h:178
GLint GLenum GLint x
Definition: glcorearb.h:409
UT_Vector3 mySpacing
Definition: CE_Multigrid.h:177
UT_Vector3 myBoundAdjModPos
Definition: CE_Multigrid.h:180
void initFromVoxels(const UT_VoxelArrayF &src, int xghost=1, int yghost=1, int zghost=1, int xpad=1, int ypad=1, int zpad=1)
GLboolean r
Definition: glcorearb.h:1222
UT_Vector3I getRes() const
Definition: CE_Grid.h:106
GLenum src
Definition: glcorearb.h:1793