HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GAS_Limit.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: GAS_Limit.h ( GAS Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GAS_Limit__
12 #define __GAS_Limit__
13 
14 #include "GAS_API.h"
15 
17 #include <UT/UT_VoxelArray.h>
18 #include <GU/GU_Detail.h>
19 
20 #include <SIM/SIM_RawField.h>
21 
22 #include "GAS_SubSolver.h"
23 #include "GAS_Utils.h"
24 
25 class GU_Detail;
26 
28 {
29 public:
30  bool shouldMultiThread(const UT_VoxelArrayF *field) const
31  { return field->numTiles() > 1; }
32 
33  GET_DATA_FUNC_S(GAS_NAME_STENCIL, StencilName);
34  GET_DATA_FUNC_I("minchoice", MinChoice);
35  GET_DATA_FUNC_I("maxchoice", MaxChoice);
36  GET_DATA_FUNC_I("revertchoice", RevertChoice);
37  GET_DATA_FUNC_V3("minvalue", MinValue);
38  GET_DATA_FUNC_V3("maxvalue", MaxValue);
39  GET_DATA_FUNC_V3("revertvalue", RevertValue);
40  GET_DATA_FUNC_F("blendwidth", Blendwidth);
41 
42  struct gas_limitsrc
43  {
45  float val;
46  bool usefield;
47  };
48 
49 protected:
50  explicit GAS_Limit(const SIM_DataFactory *factory);
51  ~GAS_Limit() override;
52 
53  /// Limits scalar fields by moving along curvature or performing
54  /// relaxation steps.
55  bool solveGasSubclass(SIM_Engine &engine,
56  SIM_Object *obj,
57  SIM_Time time,
58  SIM_Time timestep) override;
59 
60  THREADED_METHOD6_CONST(GAS_Limit, shouldMultiThread(dstfield->field()),
61  limit,
62  SIM_RawField *, dstfield,
63  const SIM_RawField *, stencil,
64  const gas_limitsrc &, minsrc,
65  const gas_limitsrc &, maxsrc,
66  const gas_limitsrc &, revertsrc,
67  float, blendwidth);
68  void limitPartial(SIM_RawField *dstfield,
69  const SIM_RawField *stencil,
70  const gas_limitsrc &minsrc,
71  const gas_limitsrc &maxsrc,
72  const gas_limitsrc &revertsrc,
73  float blendwidth,
74  const UT_JobInfo &jobinfo) const;
75 
76  /// Does the actual work for limitPartial(), taking into account which parts
77  /// of the limiting operation are applicable.
78  template<bool HAS_MIN, bool HAS_MAX, bool HAS_REVERT>
79  void limitPartialHelper(SIM_RawField *dstfield,
80  const SIM_RawField *stencil,
81  const gas_limitsrc &minsrc,
82  const gas_limitsrc &maxsrc,
83  const gas_limitsrc &revertsrc,
84  float blendwidth,
85  const UT_JobInfo &jobinfo) const;
86 
87  gas_limitsrc buildLimitSrc(SIM_Object *obj, int i, int j,
88  int choice,
89  const char *parmname,
90  UT_Vector3 val);
91 private:
92  static const SIM_DopDescription *getDopDescription();
93 
97  "Gas Limit",
98  getDopDescription());
99 };
100 
101 /// This class works as a functor to clamp/revert values.
102 template<bool HAS_MIN, bool HAS_MAX, bool HAS_REVERT>
104 {
105 public:
106  /// Blend widths below this amount get clamped to 0.
107  static constexpr float MINBLEND = 1e-3;
108 
109  GAS_RevertOperation(bool useMinField, float minValue, bool useMaxField,
110  float maxValue, bool useRevertField, float revertValue,
111  float blendwidth)
112  {
113  myUseMinField = useMinField;
114  myMin = minValue;
115  myUseMaxField = useMaxField;
116  myMax = maxValue;
117  myUseRevertField = useRevertField;
118  myRevert = revertValue;
119 
120  myBlendwidth = blendwidth;
121  }
122 
123  /// Returns the limited/reverted value. v is the current voxel value, mv is
124  /// the voxel value of the minimum field, Mv is the voxel value of the maximum
125  /// field, rv is the voxel value of the revert field.
126  /// Depending on the template instantiations and parameters passed to the
127  /// constructor, some of these operations may be skipped or their voxel values
128  /// replaced by constant bounds.
129  inline float operator()(float v, float mv, float Mv, float rv) const
130  {
131  bool clamped = clampBelow(v, mv) || clampAbove(v, Mv);
132  if(HAS_REVERT && clamped)
133  v = myUseRevertField ? rv : myRevert;
134  if(!clamped && myBlendwidth >= MINBLEND)
135  v = limitBlend(v, mv, Mv, rv);
136 
137  return v;
138  }
139 
140 private:
141  bool myUseMinField, myUseMaxField, myUseRevertField;
142  float myMin, myMax, myRevert;
143  float myBlendwidth;
144 
145 private:
146  /// Sets mv to the constant floor value if the field is not to be used.
147  /// Clamps v0 if it is less than mv. Returns true if clamping was performed.
148  inline bool clampBelow(float& v0, float& mv) const
149  {
150  if(HAS_MIN)
151  {
152  if(!myUseMinField)
153  mv = myMin;
154  if(v0 < mv)
155  {
156  v0 = mv;
157  return true;
158  }
159  }
160  return false;
161  }
162 
163  /// Sets Mv to the constant ceiling value if the field is not to be used.
164  /// Clamps v0 if it is greater than Mv. Returns true if clamping was performed.
165  inline bool clampAbove(float& v0, float& Mv) const
166  {
167  if(HAS_MAX)
168  {
169  if(!myUseMaxField)
170  Mv = myMax;
171  if(v0 > Mv)
172  {
173  v0 = Mv;
174  return true;
175  }
176  }
177  return false;
178  }
179 
180  /// Blends v with the appropriate clamping value.
181  inline float limitBlend(float v, float mv, float Mv, float rv) const
182  {
183  float d;
184  // If there is no revert value, it is set to the closest clamping value.
185  if(HAS_MIN && HAS_MAX)
186  {
187  // If there is minimum and maximum, blendwidth has to be adjusted using the
188  // interval length.
189  float bw = myBlendwidth * (Mv - mv);
190  d = SYSsmooth(mv, mv + bw, v) * (1 - SYSsmooth(Mv - bw, Mv, v));
191  if(!HAS_REVERT)
192  rv = (v - mv < Mv - v) ? mv : Mv;
193  }
194  else if(HAS_MIN)
195  {
196  d = SYSsmooth(mv, mv + myBlendwidth, v);
197  if(!HAS_REVERT)
198  rv = mv;
199  }
200  else // Only other option: only clamp above.
201  {
202  d = SYSsmooth(Mv - myBlendwidth, Mv, v);
203  if(!HAS_REVERT)
204  rv = Mv;
205  }
206 
207  if(HAS_REVERT && !myUseRevertField)
208  rv = myRevert;
209  return d * v + (1 - d) * rv;
210  }
211 };
212 
213 #endif
float operator()(float v, float mv, float Mv, float rv) const
Definition: GAS_Limit.h:129
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:50
#define GET_DATA_FUNC_V3(DataName, FuncName)
GT_API const UT_StringHolder time
const GLdouble * v
Definition: glcorearb.h:837
#define GAS_API
Definition: GAS_API.h:10
virtual bool solveGasSubclass(SIM_Engine &engine, SIM_Object *obj, SIM_Time time, SIM_Time timestep)=0
static constexpr float MINBLEND
Blend widths below this amount get clamped to 0.
Definition: GAS_Limit.h:107
#define DECLARE_DATAFACTORY(DataClass, SuperClass, Description, DopParms)
Definition: SIM_DataUtils.h:63
bool shouldMultiThread(const UT_VoxelArrayF *field) const
Definition: GAS_Limit.h:30
#define GET_DATA_FUNC_I(DataName, FuncName)
const SIM_RawField * field
Definition: GAS_Limit.h:44
int numTiles() const
GLfloat v0
Definition: glcorearb.h:816
GLint j
Definition: glad.h:2733
GAS_RevertOperation(bool useMinField, float minValue, bool useMaxField, float maxValue, bool useRevertField, float revertValue, float blendwidth)
Definition: GAS_Limit.h:109
THREADED_METHOD6_CONST(GAS_SubSolver, gdp->getNumPoints() > 2048, applyForces, GU_Detail *, gdp, const GA_PointGroup *, ptgrp, SIM_Time, timestep, bool, densityscale, bool, doorient, bool, updatepos) void applyForcesPartial(GU_Detail *gdp
#define GET_DATA_FUNC_F(DataName, FuncName)
GLuint GLfloat * val
Definition: glcorearb.h:1608
GLint GLfloat GLint stencil
Definition: glcorearb.h:1278
#define GET_DATA_FUNC_S(DataName, FuncName)
This class works as a functor to clamp/revert values.
Definition: GAS_Limit.h:103
#define GAS_NAME_STENCIL
Definition: GAS_Utils.h:19