HDK
SIM_DerScalar.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  */
7
8 #ifndef __SIM_DerScalar_h__
9 #define __SIM_DerScalar_h__
10
11 #include "SIM_API.h"
12 #include <UT/UT_Vector3.h>
13
14 class SIM_DerVector3;
15
16 /// This class defines a scalar and its derivative w.r.t. a 3D vector.
17 /// It uses automatic differentiation to maintain the dependency
18 /// upon the derivative vector as arithmetic operations are performed.
19 ///
20 /// By performing a sequence of arithmetic operations on this
21 /// class after initializing its derivative appropriately, you can
22 /// easily keep track of the effect of those operations on the derivative.
23 /// Independent variables can be included in an equation using the
24 /// conventional UT_Vector3 and fpreal types, and dependent variables can
25 /// use the SIM_DerVector3 and SIM_DerScalar types.
26 ///
27 /// It is inspired by Eitan Grinspun's class for the same purpose,
28 /// described in his 2003 SCA paper on Discrete Shells.
30 {
31 public:
33  /// Initialize to a constant vector, with no derivative.
34  explicit SIM_DerScalar(fpreal v) : myV(v), myD(0.f, 0.f, 0.f)
35  { }
36  /// Initialize to a vector with a derivative. This is particularly
37  /// useful for initializing the variables themselves, where D=I.
39  : myV(v), myD(D)
40  { }
41
42  // Default copy constructor is fine.
43  //SIM_DerScalar(const SIM_DerScalar &rhs);
44
45  // The scalar v.
46  fpreal v() const
47  { return myV; }
48  // The derivative, dv/dx = [ dv/dx1 dv/dx2 dv/dx3 ]^T
49  const UT_Vector3&D() const
50  { return myD; }
51
52  // Default assignment operator is fine.
53  // SIM_DerScalar operator=(const SIM_DerScalar &rhs);
55  { return operator=(SIM_DerScalar(rhs)); }
56
58  {
59  // d(-v)/dx = -dv/dx
60  return SIM_DerScalar(-v(), -D());
61  }
63  {
64  // d(v1+v2)/dx = dv1/dx + dv2/dx
65  return SIM_DerScalar(v() + rhs.v(), D() + rhs.D());
66  }
68  {
69  return SIM_DerScalar(v() + rhs, D());
70  }
72  {
73  // d(v1-v2)/dx = dv1/dx - dv2/dx
74  return SIM_DerScalar(v() - rhs.v(), D() - rhs.D());
75  }
77  {
78  return SIM_DerScalar(v() - rhs, D());
79  }
81  {
82  // d(v1*v2)/dx = v1 * dv2/dx + v2 * dv1/dx
83  return SIM_DerScalar(v() * rhs.v(),
84  v() * rhs.D() + rhs.v() * D());
85  }
87  {
88  // d(v1*v2)/dx = v1 * dv2/dx + v2 * dv1/dx
89  return SIM_DerScalar(v() * rhs, rhs * D());
90  }
92  {
93  return SIM_DerScalar(v() * v(), (2 * v()) * D());
94  }
96  { return operator*(rhs.inverse()); }
98  { return operator*(1/rhs); }
100  { return operator=(*this + rhs); }
102  { return operator=(*this + rhs); }
104  { return operator=(*this - rhs); }
106  { return operator=(*this - rhs); }
108  { return operator=(*this * rhs); }
110  { return operator=(*this * rhs); }
112  { return operator=(*this / rhs); }
114  { return operator=(*this * (1/rhs)); }
116  {
117  // d(v^-1)/dx = -dv/dx * v^-2
118  UT_ASSERT_P(v() == v());
119  UT_ASSERT_P(D() == D());
120  return SIM_DerScalar(1/v(), D() / (-v() * v()));
121  }
122  // The derivative for this is tricky near zero. It's discontinuous at
123  // zero (switches from real to imaginary), and approaches infinity as
124  // we get close to zero.
125  // I approximate it as being equal to zero within a tolerance of the
126  // origin.
128  {
129  const fpreal tol = 1e-5;
130  // d(sqrt(v))/dx = .5 / sqrt(v) * dv/dx
131  UT_ASSERT_P(v() == v());
132  UT_ASSERT_P(D() == D());
133
134  UT_ASSERT_P(v() > -tol);
135  fpreal newVal = SYSsqrt(SYSmax(0.f, v()));
136  if( newVal < tol )
137  {
138  return SIM_DerScalar(newVal);
139  }
140  else
141  {
142  return SIM_DerScalar(newVal, D() / (2*newVal));
143  }
144  }
145
146 private:
147  fpreal myV;
148  UT_Vector3 myD;
149 };
150
151 inline SIM_DerScalar operator+(fpreal lhs, const SIM_DerScalar &rhs);
152 inline SIM_DerScalar operator-(fpreal lhs, const SIM_DerScalar &rhs);
153 inline SIM_DerScalar operator*(fpreal lhs, const SIM_DerScalar &rhs);
154 inline SIM_DerScalar operator/(fpreal lhs, const SIM_DerScalar &rhs);
155
156 inline SIM_DerScalar
158 {
159  return rhs + lhs;
160 }
161
162 inline SIM_DerScalar
164 {
165  return SIM_DerScalar(lhs - rhs.v(), -rhs.D());
166 }
167
168 inline SIM_DerScalar
170 {
171  return rhs * lhs;
172 }
173
174 inline SIM_DerScalar
176 {
177  return lhs * rhs.inverse();
178 }
179 #endif
#define SYSmax(a, b)
Definition: SYS_Math.h:1367
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Multiply each element of the given matrix by scalar and return the result.
Definition: Mat3.h:609
SIM_DerScalar & operator=(fpreal rhs)
Definition: SIM_DerScalar.h:54
SIM_DerScalar(fpreal v)
Initialize to a constant vector, with no derivative.
Definition: SIM_DerScalar.h:34
SIM_DerScalar operator*=(fpreal rhs)
SIM_DerScalar sqrt() const
const GLdouble * v
Definition: glcorearb.h:836
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:625
SIM_DerScalar operator/=(fpreal rhs)
SIM_DerScalar inverse() const
SIM_DerScalar(fpreal v, const UT_Vector3 &D)
Definition: SIM_DerScalar.h:38
SIM_DerScalar operator-=(const SIM_DerScalar &rhs)
SIM_DerScalar operator+(const SIM_DerScalar &rhs) const
Definition: SIM_DerScalar.h:62
GLfloat f
Definition: glcorearb.h:1925
SIM_DerScalar sqr() const
Definition: SIM_DerScalar.h:91
SIM_DerScalar operator-() const
Definition: SIM_DerScalar.h:57
SIM_DerScalar operator-(fpreal rhs) const
Definition: SIM_DerScalar.h:76
fpreal v() const
Definition: SIM_DerScalar.h:46
SIM_DerScalar operator*(const SIM_DerScalar &rhs) const
Definition: SIM_DerScalar.h:80
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:635
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:125
SIM_DerScalar operator*(fpreal rhs) const
Definition: SIM_DerScalar.h:86
SIM_DerScalar operator*(fpreal lhs, const SIM_DerScalar &rhs)
SIM_DerScalar operator+(fpreal rhs) const
Definition: SIM_DerScalar.h:67
SIM_DerScalar operator/(fpreal rhs) const
Definition: SIM_DerScalar.h:97
SIM_DerScalar operator*=(const SIM_DerScalar &rhs)
const UT_Vector3 & D() const
Definition: SIM_DerScalar.h:49
double fpreal
Definition: SYS_Types.h:270
SIM_DerScalar operator/=(const SIM_DerScalar &rhs)
SIM_DerScalar operator/(fpreal lhs, const SIM_DerScalar &rhs)
SIM_DerScalar operator-(const SIM_DerScalar &rhs) const
Definition: SIM_DerScalar.h:71
#define SIM_API
Definition: SIM_API.h:10
SIM_DerScalar operator/(const SIM_DerScalar &rhs) const
Definition: SIM_DerScalar.h:95
SIM_DerScalar operator+=(fpreal rhs)
SIM_DerScalar operator+=(const SIM_DerScalar &rhs)
Definition: SIM_DerScalar.h:99
SIM_DerScalar operator-=(fpreal rhs)