HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GAS_SubSolver.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_SubSolver.h ( GAS Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GAS_SubSolver__
12 #define __GAS_SubSolver__
13 
14 #include "GAS_API.h"
15 
16 #include <PRM/PRM_Name.h>
17 #include <PRM/PRM_ChoiceList.h>
18 
19 #include <UT/UT_StringArray.h>
20 #include <SIM/SIM_Data.h>
21 #include <SIM/SIM_DataUtils.h>
22 #include <SIM/SIM_Utils.h>
23 #include <SIM/SIM_OptionsUser.h>
24 #include <SIM/SIM_Solver.h>
25 #include <SIM/SIM_Time.h>
26 #include <SIM/SIM_RawField.h>
27 
28 #include "GAS_Utils.h"
29 
30 class SIM_Engine;
31 class SIM_Object;
32 class SIM_Geometry;
33 class SIM_Position;
34 class SIM_GeometryCopy;
35 class SIM_ScalarField;
36 class SIM_VectorField;
37 class SIM_MatrixField;
38 class SIM_IndexField;
39 class SIM_RawIndexField;
40 class GU_SDF;
41 class GAS_SPH;
42 class GOP_Manager;
43 
44 ///
45 /// Captures all OCL errors during the life of this object.
46 /// When it is done, dumps any reported to the specified solver/object.
47 ///
48 class GAS_SubSolver;
49 
50 GAS_API void
51 GASfillRelationshipMenu(void *, PRM_Name *names, int size,
52  const PRM_SpareData *, const PRM_Parm *);
53 
55 {
56 public:
59 
60  void addError(const char *msg,
62 
63 private:
64  SIM_Object *myObj;
65  GAS_SubSolver *mySolver;
66  UT_StringArray myErrors;
67  UT_Array<UT_ErrorSeverity> mySeverities;
68 };
69 
71  public SIM_OptionsUser
72 {
73 public:
74  /// Merely calls solve on each object.
76  SIM_ObjectArray &objects,
77  SIM_ObjectArray &newobjects,
78  SIM_ObjectArray &feedbacktoobjects,
79  const SIM_Time &timestep) override;
80 
81  /// Merely calls postSolve on each object.
83  SIM_ObjectArray &objects,
84  SIM_ObjectArray &newobjects,
85  SIM_ObjectArray &feedbacktoobjects,
86  const SIM_Time &timestep) override;
87 
88  /// Adds the flags to the description suitable for microsolvers.
89  /// pure apply data, bypass data is a multisolver, and unique
90  /// datanames.
91  static void setGasDescription(SIM_DopDescription &descr);
92 
93  /// Applies this subsolver for a single timestep.
94  /// Returns true on success
95  virtual bool solveGas(SIM_Engine &engine,
96  SIM_Object *obj,
97  SIM_Time time,
98  SIM_Time timestep);
99 
100  /// Retrieves the SIM_DATA specified by the
101  /// *option* given by the name. Ie, look up in our options,
102  /// find the data name, look up a data matching the name,
103  /// return resulting data
104  /// Reports message if a field is missing unless silent is set.
105  const SIM_Geometry *getGeometry(const SIM_Object *obj, const char *name, bool silent=false);
106  SIM_Geometry *getGeometryNonConst(SIM_Object *obj, const char *name, bool silent=false);
107 
108  const GA_PointGroup *getPointGroup(const GU_Detail *gdp, GOP_Manager &mgr, const char *parmname = GAS_NAME_PTGROUP);
109  SIM_GeometryCopy *getGeometryCopy(SIM_Object *obj, const char *name, bool silent=false);
110  SIM_GeometryCopy *getGeometryCopyByDataName(SIM_Object *obj, const char *dataname, bool silent=false);
111  SIM_ScalarField *getScalarField(SIM_Object *obj, const char *name, bool silent=false);
112  SIM_VectorField *getVectorField(SIM_Object *obj, const char *name, bool silent=false);
113  SIM_MatrixField *getMatrixField(SIM_Object *obj, const char *name, bool silent=false);
114  SIM_IndexField *getIndexField(SIM_Object *obj, const char *name, bool silent=false);
115  const SIM_ScalarField *getConstScalarField(const SIM_Object *obj, const char *name, bool silent=false);
116  const SIM_VectorField *getConstVectorField(const SIM_Object *obj, const char *name, bool silent=false);
117  const SIM_MatrixField *getConstMatrixField(const SIM_Object *obj, const char *name, bool silent=false);
118  const SIM_IndexField *getConstIndexField(const SIM_Object *obj, const char *name, bool silent=false);
119 
120  const SIM_Position *getConstPosFromField(const SIM_Object *obj, const char *name);
121 
122  /// Builds the transform mapping world -> geo
123  void getWorldToGeometry(UT_DMatrix4 &xform, SIM_Object *obj, const char *geopath);
124  /// Builds the transform mapping geo -> world
125  void getGeometryToWorld(UT_DMatrix4 &xform, SIM_Object *obj, const char *geopath);
126 
127  /// Returns the matching SIM_Data. If it doesn't exist,
128  /// creates a new one.
129  /// The resulting data is not guaranteed to exist - a bad name
130  /// could end up prohibitting creation.
131  SIM_GeometryCopy *getOrCreateGeometry(SIM_Object *obj, const char *name);
132  SIM_ScalarField *getOrCreateScalarField(SIM_Object *obj, const char *name);
133  SIM_VectorField *getOrCreateVectorField(SIM_Object *obj, const char *name);
134  SIM_MatrixField *getOrCreateMatrixField(SIM_Object *obj, const char *name);
135  SIM_IndexField *getOrCreateIndexField(SIM_Object *obj, const char *name);
136 
137  /// Retrieves all of the SIM_DATAs that match the pattern stored
138  /// in the option given by name.
139  void getMatchingData(SIM_DataArray &data,
140  SIM_Object *obj, const char *name, bool silent=false);
141  void getMatchingData(SIM_DataArray &data,
142  UT_StringArray &datanames,
143  SIM_Object *obj, const char *name, bool silent=false);
144  void getMatchingDataByName(SIM_DataArray &data,
145  SIM_Object *obj, const char *name, bool silent=false);
146  void getMatchingDataByName(SIM_DataArray &data,
147  UT_StringArray &datanames,
148  SIM_Object *obj, const char *name, bool silent=false);
149  void getMatchingConstData(SIM_ConstDataArray &data,
150  UT_StringArray &datanames,
151  SIM_Object *obj, const char *name, bool silent=false);
152 
153  /// Fetches matching data, but promotes any SIM_Geometry into
154  /// SIM_GeometryCopy
155  void getMatchingGeoCopy(SIM_DataArray &data,
156  SIM_Object *obj, const char *name, bool silent=false);
157  void getMatchingGeoCopyByName(SIM_DataArray &data,
158  SIM_Object *obj, const char *name, bool silent=false);
159 
160 
161  /// Makes the given field match the reference field in terms of
162  /// bounding box & voxel count.
163  /// A no-op if reffield or field is null.
164  void matchField(SIM_ScalarField *field, const SIM_ScalarField *reffield);
165  void matchField(SIM_VectorField *field, const SIM_ScalarField *reffield);
166  void matchField(SIM_MatrixField *field, const SIM_ScalarField *reffield);
167  void matchField(SIM_IndexField *field, const SIM_ScalarField *reffield);
168 
169  /// Builds a relationship field, storing distance to each object
170  /// in the destination field, along with the OBJID and object velocity
171  /// in the optional index and vector fields. If a stencil is provided,
172  /// the mask is built only where this field is greater than 0.5.
173  /// The negate flag controls the sign of the generated fields,
174  /// collision have "inside object" as negative so have a negate of true.
175  /// Mask should already be initialized as we only write to
176  /// new values that are more-in the relevant object.
177  /// To trigger a bandwidth, initialize mask to the max dist you
178  /// want to write.
179  /// The given fields must all be aligned.
180  /// Bandwidth is how many voxels to border particles by for our
181  /// lookup.
182  /// The wind parameter is the ambient wind velocity that's not written to
183  /// the velocity fields. To get the world-space motion from velocity fields,
184  /// the wind must thus be added. Since the collider velocities ARE in world
185  /// space, the wind value must be subtracted from them to ensure that we end
186  /// up with correct values down the line (when the wind is added back in).
187  void buildRelationshipField(
189  SIM_VectorField *vel,
191  const SIM_ScalarField *stencil,
192  UT_DMatrix4 masktoworld,
193  const SIM_Object *srcobj,
194  bool usepoint, bool usesdf,
195  bool allownonsdf,
196  bool negate,
197  fpreal particlebandwidth,
198  fpreal bandwidth,
199  fpreal velscale = 1,
200  const UT_Vector3& wind = UT_Vector3(0.0f));
201 
202  /// Looks up the data referred to by the parameter (parameter name,
203  /// NOT data name here!) and finds its bounding box. Handles
204  /// fields and geometry. xform is set to the toworld transform
205  /// of the box, the box is in local space.
206  /// Returns false if no reference found. The size & center
207  /// will be left alone in that case.
208  /// The groupparmname will be referenced if it isn't null and
209  /// it is a geometry - then it will be a point group to use
210  /// for the limiting.
211  bool findReferenceBBox(
212  const SIM_Object *,
213  const char *parmname,
214  const char *groupparmname,
216  UT_Vector3 &size,
217  UT_DMatrix4 &xform);
218 
219  void reportCLError(SIM_Object *obj, int err, const char *msg) const;
220 
221 protected:
222  explicit GAS_SubSolver(const SIM_DataFactory *factory);
223  ~GAS_SubSolver() override;
224 
225  /// Applies this subsolver for a single timestep.
226  /// Returns true on success
227  virtual bool solveGasSubclass(SIM_Engine &engine,
228  SIM_Object *obj,
229  SIM_Time time,
230  SIM_Time timestep) = 0;
231 
232  // Applies postSolve tasks if exists
233  virtual bool postSolveGasSubclass(SIM_Engine &engine,
234  SIM_Object *obj,
235  SIM_Time time,
236  SIM_Time timestep){ return true; };
237 
238  /// Get a property value by looking at the Physical Parms of an object.
239  fpreal getPropertyFromState(const SIM_Object &object,
240  const SIM_Property &property) const;
241 
242  /// Evaluates property at a given position
244  const UT_Vector3 &worldspacepos,
245  const SIM_Property &property) const override;
247  int ptnum, const SIM_Property &property
248  ) const override;
249 
251  const SIM_Property &property) const override;
252 
253  /// Determines the appropriate timestep dependent on the velocity
254  /// field. If provided, maxvel will contain the maximum velocity on output.
255  fpreal calculateTimestep(SIM_Engine &engine,
256  const SIM_VectorField *velocity,
257  fpreal cflcond,
258  UT_Vector3 *maxvel = 0) const;
259 
260  /// Determines the appropriate timestep dependent on the geometry
261  /// data. The size of the particles is used as the limitting factor
262  /// for CFL condition.
263  /// If no particle scale or velocity exists, returns infinite.
264  /// If provided, maxspeed and minradius will contain the maximum speed
265  /// and minimum radius on output.
266  fpreal calculateTimestep(GU_ConstDetailHandle gdh,
267  fpreal cflcond,
268  fpreal *maxspeed = 0,
269  fpreal *minradius = 0) const;
270 
272  {
279 
281  bool isdensity;
287  const GU_Detail *gdp;
288  const GU_SDF *sdf;
289 
292  bool negate;
296 
298  };
299  /// Builds a relationship field after most stuff has been setup
300  THREADED_METHOD1(GAS_SubSolver, parms.mask->shouldMultiThread(),
301  buildRelationshipFieldInternal,
302  const RelationshipParms &, parms)
303  void buildRelationshipFieldInternalPartial(
304  const RelationshipParms &parms,
305  const UT_JobInfo &info);
306 
307 public:
308  enum MIX_NAMES {
317  NUM_MIX
318  };
319 
321  {
328  NUM_TIMESCALE
329  };
330 
332  {
337  NUM_LENGTHSCALE
338  };
339 
340  /// Performs the requires mixing.
342  float d, float s)
343  {
344  switch (mixtype)
345  {
346  case MIX_COPY:
347  d = s;
348  break;
349  case MIX_ADD:
350  d += s;
351  break;
352  case MIX_SUB:
353  d -= s;
354  break;
355  case MIX_MUL:
356  d *= s;
357  break;
358  case MIX_DIV:
359  d = SYSsafediv(d, s);
360  break;
361  case MIX_MAX:
362  d = SYSmax(d, s);
363  break;
364  case MIX_MIN:
365  d = SYSmin(d, s);
366  break;
367  case MIX_AVERAGE:
368  d = d + s;
369  d *= 0.5f;
370  break;
371  case NUM_MIX:
372  UT_ASSERT(!"Invalid mix value");
373  break;
374  }
375 
376  return d;
377  }
378 
379  /// Scales value exponentially for timestep t.
380  /// v' = e ^ (ln(v) * t)
381  static float applyTimeScalePow(float value, float t);
382 
383  /// Applies the effect of TIMESCALE_NAMES to the additive
384  /// and multiplicative values.
385  static void applyTimeScale(float &add, float &mul,
386  float timestep, int timescale);
387 
388  /// Applies the effect of the given LENGTHSCALE_NAMES to
389  /// the quantitity given
390  static float applyLengthScale(float val, float width,
391  int scaletype);
392 
393 
394  /// Zeros out the force and optionaly torque attributes.
395  void clearForces(GU_Detail *gdp, bool cleartorque = false) const;
396  void clearForces(GU_Detail *gdp, const GA_PointGroup *grp, bool cleartorque) const;
397 
398 
399  /// Integrates the force into the velocity/angvel. Optionally
400  /// also adjusts the position by the effect of the acceleration
401  /// (*not* the effect of the velocity!)
403  applyForces,
404  GU_Detail *, gdp,
405  const GA_PointGroup *, ptgrp,
406  SIM_Time, timestep,
407  bool, densityscale,
408  bool, doorient,
409  bool, updatepos)
410  void applyForcesPartial(GU_Detail *gdp,
411  const GA_PointGroup *ptgrp,
412  SIM_Time timestep,
413  bool densityscale,
414  bool doorient,
415  bool updatepos,
416  const UT_JobInfo &info) const;
417 
418 
419  /// Builds the GAS_SPH data structure, either directly
420  /// from the given SIM_Geometry or by using any SIM_PointNeighbourList
421  /// attached as NeighbourList.
422  /// The object version looks for Geometry/NeighbourList
423  /// Returns false if failed, either due to null geometry or missing
424  /// vital attributes.
425  bool buildSPH(GAS_SPH &sph, const SIM_Geometry *geo) const;
426  bool buildSPH(GAS_SPH &sph, const SIM_Object *obj) const;
427 
428 protected:
429 
430  /// Holds the parm names for our mix methods.
431  static PRM_Name ourMixMethods[NUM_MIX+1];
433 
434  static PRM_Name ourTimeScaleMethods[NUM_TIMESCALE+1];
436 
437  static PRM_Name ourLengthScaleMethods[NUM_LENGTHSCALE+1];
439 
440 private:
443 };
444 
445 #endif
446 
#define SYSmax(a, b)
Definition: SYS_Math.h:1570
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:50
#define DECLARE_CLASSNAME(DataClass, SuperClass)
Definition: SIM_DataUtils.h:20
#define THREADED_METHOD6_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6)
GAS_API void GASfillRelationshipMenu(void *, PRM_Name *names, int size, const PRM_SpareData *, const PRM_Parm *)
virtual SIM_PropertyResolver * getPropertyResolverSubclass(const SIM_Object &object, const SIM_Property &property) const
Builds a resolver for evaluating properties swiftly.
GT_API const UT_StringHolder time
#define THREADED_METHOD1(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1)
#define GAS_API
Definition: GAS_API.h:10
SIM_PropertyResolver * vel_lookup
static PRM_ChoiceList ourTimeScaleMenu
UT_Vector3T< float > UT_Vector3
GLdouble s
Definition: glad.h:3009
UT_ErrorSeverity
Definition: UT_Error.h:25
This class holds a three dimensional scalar field.
Definition: GU_SDF.h:302
static PRM_ChoiceList ourLengthScaleMenu
const SIM_RawField * stencil
GLfloat f
Definition: glcorearb.h:1926
Holds pointers to a number of SIM_Object objects.
GLint GLuint mask
Definition: glcorearb.h:124
long long int64
Definition: SYS_Types.h:116
#define SYS_STATIC_FORCE_INLINE
Definition: SYS_Inline.h:48
static PRM_ChoiceList ourMixMethodMenu
GLenum GLenum severity
Definition: glcorearb.h:2539
GLuint const GLchar * name
Definition: glcorearb.h:786
This class holds a three dimensional tensor field.
virtual SIM_Result solveObjectsSubclass(SIM_Engine &engine, SIM_ObjectArray &objects, SIM_ObjectArray &newobjects, SIM_ObjectArray &feedbacktoobjects, const SIM_Time &timestep)=0
virtual fpreal getPropertyAtPositionSubclass(const SIM_Object &object, const UT_Vector3 &worldpos, const SIM_Property &property) const
GLdouble t
Definition: glad.h:2397
const GEO_PrimVolume * volume
GLsizeiptr size
Definition: glcorearb.h:664
virtual SIM_Result postSolveObjectsSubclass(SIM_Engine &engine, SIM_ObjectArray &objects, SIM_ObjectArray &newobjects, SIM_ObjectArray &feedbacktoobjects, const SIM_Time &timestep)
Definition: SIM_Solver.h:176
fpreal64 fpreal
Definition: SYS_Types.h:277
GLuint index
Definition: glcorearb.h:786
GLuint GLfloat * val
Definition: glcorearb.h:1608
This class holds a three dimensional scalar field.
#define GAS_NAME_PTGROUP
Definition: GAS_Utils.h:34
virtual bool postSolveGasSubclass(SIM_Engine &engine, SIM_Object *obj, SIM_Time time, SIM_Time timestep)
GLint GLsizei width
Definition: glcorearb.h:103
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLint GLfloat GLint stencil
Definition: glcorearb.h:1278
#define SYSmin(a, b)
Definition: SYS_Math.h:1571
This class holds a three dimensional vector field.
const SIM_RawField * surface
SYS_STATIC_FORCE_INLINE float mixValues(MIX_NAMES mixtype, float d, float s)
Performs the requires mixing.
SIM_Property
Definition: format.h:895
virtual fpreal getPropertyAtPointSubclass(const SIM_Object &object, int ptnum, const SIM_Property &property) const
ImageBuf OIIO_API mul(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
SYS_FORCE_INLINE GA_Size getNumPoints() const
Return the number of points.
Definition: GA_Detail.h:334
This implements a SIM_Geometry that copies the source geometry.