Main Page   Class Hierarchy   Compound List   File List   Compound Members  

simSimulator.cpp

00001 //////////////////////////////////////////////////////////////////////
00002 // Copyright (c) 2002-2003 David Pritchard <drpritch@alumni.uwaterloo.ca>
00003 // 
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either
00007 // version 2 of the License, or (at your option) any later
00008 // version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 #include <freecloth/simulator/simSimulator.h>
00020 #include <freecloth/geom/geVector.h>
00021 #include <freecloth/geom/geMatrix3.h>
00022 #include <freecloth/base/fstream>
00023 #include <freecloth/base/iomanip>
00024 #include <freecloth/base/baMath.h>
00025 #include <freecloth/base/baStringUtil.h>
00026 
00027 #ifdef NDEBUG
00028     #define DO_DEBUG(x)
00029 #else
00030     #define DO_DEBUG(x) x
00031 #endif
00032 
00033 // If set, avoid [BarWit98]'s assumption that stretch always keeps the
00034 // edge lengths to a fixed size. Not very sure that it works...
00035 #define DO_NORM             0
00036 // If set, adjust [BarWit98]'s condition functions to be scale invariant
00037 #define DO_SCALE_INVARIANT  1
00038 
00039 namespace {
00040     using namespace freecloth;
00041 
00042     typedef Float Float_3[3];
00043     typedef Float Float_4[4];
00044     typedef GePoint GePoint_3[3];
00045     typedef GePoint GePoint_4[4];
00046     typedef GeVector GeVector_3[3];
00047     typedef GeVector GeVector_33[3][3];
00048     typedef GeVector GeVector_3333[3][3][3][3];
00049     typedef GeVector GeVector_4[4];
00050     typedef GeVector GeVector_43[4][3];
00051     typedef GeVector GeVector_443[4][4][3];
00052     typedef GeVector GeVector_4433[4][4][3][3];
00053     typedef GeMatrix3 GeMatrix3_33[3][3];
00054     typedef GeMatrix3 GeMatrix3_44[4][4];
00055 
00056     const bool PRINT_STATS = false;
00057 
00058     const bool DEBUG_REWIND = false;
00059     const bool DEBUG_MASS = false;
00060     const bool DEBUG_STEP = false;
00061     const bool DEBUG_COMMON = false;
00062     const bool VERIFY_COMMON = false;
00063     const bool DEBUG_STRETCH = false;
00064     const bool VERIFY_STRETCH = false;
00065     const bool DEBUG_SHEAR = false;
00066     const bool VERIFY_SHEAR = false;
00067     const bool DEBUG_BEND = false;
00068     // Verification - for each derivative da/db calculated, verify the
00069     // calculation by performing (a(b0+db)-a(b0))/db calculation, and asserting
00070     // that this matches the actual derivative calculation.
00071     const bool VERIFY_BEND = false;
00072 
00073     const bool DUMP_DISTS = false;
00074     const bool DUMP_FORCES = false;
00075 
00076 
00077 
00078 
00079 //------------------------------------------------------------------------------
00080 
00081     inline GeVector makeSkewRow( const GeVector& v, UInt32 row )
00082     {
00083         DGFX_ASSERT( row < 3 );
00084 
00085         switch( row ) {
00086             case 0: 
00087                 return GeVector( 0, -v._z, v._y );
00088             case 1:
00089                 return GeVector( v._z, 0, -v._x );
00090             case 2:
00091                 return GeVector( -v._y, v._x, 0 );
00092         }
00093         return GeVector::ZERO;
00094     }
00095 
00096 
00097 //------------------------------------------------------------------------------
00098 
00099     template <class E1>
00100     bool isSymmetric( const E1& A )
00101     {
00102         DGFX_ASSERT( A.nbRows() == A.nbColumns() );
00103         for ( UInt32 i = 0; i < A.nbRows(); ++i ) {
00104             for ( UInt32 j = i + 1; j < A.nbRows(); ++j ) {
00105                 if ( A( i, j ) != A( j, i ).transpose() ) {
00106                     return false;
00107                 }
00108             }
00109         }
00110         return true;
00111     }
00112 }
00113 
00114 FREECLOTH_NAMESPACE_START
00115 
00116 ////////////////////////////////////////////////////////////////////////////////
00117 // CLASS SimSimulator::CommonVars
00118 
00119 /*!
00120  * \class SimSimulator::CommonVars
00121  * \brief Variables common to stretch and shear force computation.
00122  */
00123 class SimSimulator::CommonVars
00124 {
00125 public:
00126     // ----- member functions -----
00127 
00128     void calc( const GePoint_3 p, const GePoint_3 tp );
00129     void debugOutput( std::ostream& os );
00130 
00131     // ----- member variables -----
00132 
00133     Float _du1,_dv1,_du2,_dv2;
00134     Float _a;
00135     GeVector _wu,_wv;
00136     //! Normalised versions of wu and wv ($\frac{wu}{\norm{\wu}}$)
00137     GeVector _whatu,_whatv;
00138     //! Inverse magnitude of wu and wv ($\frac{1}{\norm{\wu}}$)
00139     Float _wuim,_wvim;
00140 
00141     Float_3 _dwux_dxmx, _dwvx_dxmx;
00142 #if DO_NORM
00143     GeVector_33 _dwhatu_dxm, _dwhatv_dxm;
00144     GeVector_3333 _d2whatu_dxmdxn, _d2whatv_dxmdxn;
00145 #endif
00146 };
00147 
00148 ////////////////////////////////////////////////////////////////////////////////
00149 // CLASS SimSimulator::StretchVars
00150 
00151 class SimSimulator::StretchVars {
00152 public:
00153     // ----- member functions -----
00154 
00155     void calc(
00156         const CommonVars& cv,
00157         const GeVector v0[ 3 ],
00158         Float b_u, Float b_v
00159     );
00160     void debugOutput( std::ostream& os );
00161 
00162     // ----- member variables -----
00163     Float _Cu, _Cv;
00164     GeVector_3 _dCu_dxm, _dCv_dxm;
00165     Float _dCu_dt, _dCv_dt;
00166     GeMatrix3_33 _d2Cu_dxmdxn, _d2Cv_dxmdxn;
00167 };
00168 
00169 ////////////////////////////////////////////////////////////////////////////////
00170 // CLASS SimSimulator::ShearVars
00171 
00172 /*!
00173  * \brief Variables used in shear force computation.
00174  */
00175 class SimSimulator::ShearVars {
00176 public:
00177     // ----- member functions -----
00178 
00179     void calc(
00180         const CommonVars& cv,
00181         const GeVector v0[ 3 ]
00182     );
00183     void debugOutput( std::ostream& os );
00184 
00185     // ----- member variables -----
00186     Float _C;
00187     GeVector_3 _dC_dxm;
00188     Float _dC_dt;
00189     GeMatrix3_33 _d2C_dxmdxn;
00190 };
00191 
00192 
00193 ////////////////////////////////////////////////////////////////////////////////
00194 // CLASS SimSimulator::BendVars
00195 
00196 /*!
00197  * \brief Variables used in bend force computation.
00198  */
00199 class SimSimulator::BendVars
00200 {
00201 public:
00202     // ----- member functions -----
00203 
00204     void calc(
00205         const GePoint_4 x,
00206         const GeVector_4 v
00207     );
00208     //! This variant is for use when verifying, especially without DO_NORM.
00209     void calc(
00210         const GePoint_4 x,
00211         const GeVector_4 v,
00212         const BendVars& bv
00213     );
00214     void debugOutput( std::ostream& os );
00215 
00216     // ----- member variables -----
00217     //! Unit vectors
00218     GeVector _nhatA, _nhatB, _ehat;
00219     //! Inverse magnitude of nA, nB, e
00220     Float _nAim, _nBim, _eim;
00221     Float _costh, _sinth;
00222     Float _C;
00223 
00224     GeVector_4 _qA, _qB;
00225     Float_4 _qe;
00226     GeVector_443 _dqAm_dxn, _dqBm_dxn;
00227 
00228     GeVector_43 _dnhatA_dxm, _dnhatB_dxm, _dehat_dxm;
00229     GeVector_4433 _d2nA_dxmdxn, _d2nB_dxmdxn;
00230 #if DO_NORM
00231     GeVector_4433 _d2e_dxmdxn;
00232 #endif
00233 
00234     GeVector_4 _dcosth_dxm, _dsinth_dxm;
00235     GeMatrix3_44 _d2costh_dxmdxn, _d2sinth_dxmdxn;
00236 
00237     GeVector_4 _dC_dxm;
00238     Float _dC_dt;
00239     GeMatrix3_44 _d2C_dxmdxn;
00240 
00241 private:
00242 
00243     // ----- member functions -----
00244     void mainCalc( const GePoint_4 x, const GeVector_4 v );
00245     void calcNE( const GePoint_4 x );
00246     void calcThetas();
00247     void calcQs( const GePoint_4 x );
00248     void calcDqs();
00249     void calcNEderiv();
00250     void calcD2NE();
00251     void calcCosSinDeriv();
00252     void calcD2cossinth();
00253     void calcCderivs();
00254 };
00255 
00256 
00257 ////////////////////////////////////////////////////////////////////////////////
00258 // CLASS SimSimulator
00259 
00260 // LaTeX setup
00261 //
00262 /* $
00263 \newcommand{\pfrac}[2]{
00264     \frac{\partial #1}{\partial #2}
00265 }
00266 \newcommand{\pfractwo}[3]{
00267     \frac{\partial^2 #1}{\partial #2 \partial #3}
00268 }
00269 \newcommand{\cross}{\times}
00270 \newcommand{\I}{{\bf I}}
00271 \newcommand{\Is}{{\bf I}_s}
00272 \newcommand{\x}{{\bf x}}
00273 \newcommand{\xm}{\x_m}
00274 \newcommand{\xms}{\x_{m_s}}
00275 \newcommand{\xmt}{\x_{m_t}}
00276 \newcommand{\xmx}{\x_{m_x}}
00277 \newcommand{\xn}{\x_n}
00278 \newcommand{\xns}{\x_{n_s}}
00279 \newcommand{\xnt}{\x_{n_t}}
00280 \newcommand{\xnx}{\x_{n_x}}
00281 \newcommand{\du}{\Delta u}
00282 \newcommand{\dv}{\Delta v}
00283 \newcommand{\C}{{\bf C}}
00284 \newcommand{\Cu}{C_u}
00285 \newcommand{\Cv}{C_v}
00286 \newcommand{\w}{{\bf w}}
00287 \newcommand{\what}{{\bf {\hat w}}}
00288 \newcommand{\wu}{\w_u}
00289 \newcommand{\wus}{\w_{u_s}}
00290 \newcommand{\wut}{\w_{u_t}}
00291 \newcommand{\wux}{\w_{u_x}}
00292 \newcommand{\whatu}{\what_u}
00293 \newcommand{\whatux}{\what_{u_x}}
00294 \newcommand{\wv}{\w_v}
00295 \newcommand{\wvs}{\w_{v_s}}
00296 \newcommand{\wvt}{\w_{v_t}}
00297 \newcommand{\wvx}{\w_{v_x}}
00298 \newcommand{\whatv}{\what_v}
00299 \newcommand{\whatvx}{\what_{v_x}}
00300 \newcommand{\n}{{\bf n}}
00301 \newcommand{\nhat}{{\bf {\hat n}}}
00302 \newcommand{\e}{{\bf e}}
00303 \newcommand{\ehat}{{\bf {\hat e}}}
00304 \newcommand{\q}{{\bf q}}
00305 $ */
00306 
00307 //------------------------------------------------------------------------------
00308 
00309 SimSimulator::SimSimulator( const GeMesh& initialMesh )
00310   : _initialMesh( new GeMesh( initialMesh ) ),
00311     _rho( .01f ),
00312     _h( .02f ),
00313     _time( 0.f )
00314 {
00315     rewind();
00316     setupMass();
00317     removeAllConstraints();
00318 }
00319 
00320 //------------------------------------------------------------------------------
00321 
00322 void SimSimulator::rewind()
00323 {
00324     _initialMeshWingedEdge = RCShdPtr<GeMeshWingedEdge>(
00325         new GeMeshWingedEdge( _initialMesh )
00326     );
00327     if ( DEBUG_REWIND ) {
00328         std::cout << "winged edges = " << _initialMeshWingedEdge << std::endl;
00329     }
00330     _mesh = RCShdPtr<GeMesh>( new GeMesh( *_initialMesh ) );
00331 
00332     const UInt32 N = _mesh->getNbVertices();
00333     _v0 = SimVector( N );
00334     _f0 = SimVector( N );
00335     _df_dx = SimMatrix( N, N );
00336     _df_dv = SimMatrix( N, N );
00337     _modPCG._b = SimVector( N );
00338     _modPCG._A = SimMatrix( N, N );
00339     UInt32 i;
00340     ForceType ftypes[] = { F_STRETCH, F_SHEAR, F_BEND };
00341     for( i = 0; i < 3; ++i ) {
00342         UInt32 f( ftypes[ i ] );
00343         _f0i[ f ] = SimVector( N );
00344         _d0i[ f ] = SimVector( N );
00345         _df_dxi[ f ] = SimMatrix( N, N );
00346         _dd_dxi[ f ] = SimMatrix( N, N );
00347         _dd_dvi[ f ] = SimMatrix( N, N );
00348 
00349         _fenergy[ i ] = 0;
00350     }
00351     _f0i[ F_GRAVITY ] = SimVector( N );
00352     _f0i[ F_DRAG ] = SimVector( N );
00353 
00354     for( i = 0; i < NB_FORCES; ++i ) {
00355         _trienergy[ i ].resize( _initialMesh->getNbFaces() );
00356     }
00357 
00358     _venergy = 0;
00359     _energy = 0;
00360     _time = 0.f;
00361 }
00362 
00363 //------------------------------------------------------------------------------
00364 
00365 void SimSimulator::setupMass()
00366 {
00367     const UInt32 N = _mesh->getNbVertices();
00368     _M = SimMatrix( N, N );
00369     _totalMass = 0;
00370 
00371     GeMesh::FaceConstIterator fi;
00372     GeMesh::VertexId vid;
00373     for( fi = _initialMesh->beginFace(); fi != _initialMesh->endFace(); ++fi ) {
00374         Float m = _rho * fi->calcArea() / 3;
00375         for ( UInt32 i = 0; i < 3; ++i ) {
00376             vid = fi->getVertexId( i );
00377             // NOTE: taking a reference will *not* work with uBLAS
00378             GeMatrix3 M( _M( vid, vid ) );
00379             M( 0, 0 ) += m;
00380             M( 1, 1 ) += m;
00381             M( 2, 2 ) += m;
00382             _M( vid, vid ) = M;
00383             _totalMass += m;
00384         }
00385     }
00386 
00387     if ( DEBUG_MASS ) {
00388         std::cout << "_M = " << _M << std::endl;
00389         std::cout << "totalMass = " << _totalMass << std::endl;
00390     }
00391 }
00392 
00393 //------------------------------------------------------------------------------
00394 
00395 void SimSimulator::removeAllConstraints()
00396 {
00397     const UInt32 N = _mesh->getNbVertices();
00398     GeMesh::VertexId vid;
00399     _modPCG._S.resize( N );
00400     for( vid = 0; vid < N; ++vid ) {
00401         _modPCG._S[ vid ] = GeMatrix3::IDENTITY;
00402     }
00403     _z0 = SimVector( N );
00404     _z0.clear();
00405 
00406     // This is isn't strictly necessary, but generally gets nicer results
00407     // when the user interactively changes constraints.
00408     _v0.clear();
00409 }
00410 
00411 //------------------------------------------------------------------------------
00412 
00413 void SimSimulator::setPosConstraintPlane(
00414     GeMesh::VertexId vid,
00415     const GeVector& p
00416 ) {
00417     GeVector pu( p.getUnit() );
00418     DGFX_ASSERT( vid < _modPCG._S.size() );
00419     _modPCG._S[ vid ] =
00420         GeMatrix3::IDENTITY - GeMatrix3::outerProduct( pu, pu );
00421 }
00422 
00423 //------------------------------------------------------------------------------
00424 
00425 void SimSimulator::setPosConstraintLine(
00426     GeMesh::VertexId vid,
00427     const GeVector& v
00428 ) {
00429     GeVector vu( v.getUnit() );
00430 
00431     // Construct a vector perpendicular to l.
00432     GeVector p;
00433     if ( !BaMath::isEqual( vu._z, 0 ) ) {
00434         p = GeVector( 1, 1, ( vu._x + vu._y ) / vu._z );
00435     }
00436     else if ( !BaMath::isEqual( vu._y, 0 ) ) {
00437         p = GeVector( 1, ( vu._x + vu._z ) / vu._y, 1 );
00438     }
00439     else {
00440         p = GeVector( ( vu._y + vu._z ) / vu._x, 1, 1 );
00441     }
00442     GeVector pu( p.getUnit() );
00443     GeVector qu( vu.cross( pu ) );
00444 
00445     DGFX_ASSERT( BaMath::isEqual( qu.length(), 1 ) );
00446     DGFX_ASSERT( BaMath::isEqual( pu.dot( vu ), 0 ) );
00447     DGFX_ASSERT( BaMath::isEqual( qu.dot( vu ), 0 ) );
00448     DGFX_ASSERT( BaMath::isEqual( pu.dot( qu ), 0 ) );
00449 
00450     DGFX_ASSERT( vid < _modPCG._S.size() );
00451     _modPCG._S[ vid ] =
00452         GeMatrix3::IDENTITY - GeMatrix3::outerProduct( pu, pu ) -
00453         GeMatrix3::outerProduct( qu, qu );
00454 }
00455 
00456 //------------------------------------------------------------------------------
00457 
00458 void SimSimulator::setPosConstraintFull( GeMesh::VertexId vid )
00459 {
00460     DGFX_ASSERT( vid < _modPCG._S.size() );
00461     _modPCG._S[ vid ] =
00462         GeMatrix3::ZERO;
00463 }
00464 
00465 //------------------------------------------------------------------------------
00466 
00467 void SimSimulator::setVelConstraint( GeMesh::VertexId vid, const GeVector& v )
00468 {
00469     DGFX_ASSERT( vid < _z0.size() );
00470     _z0[ vid ] = v;
00471 }
00472 
00473 //------------------------------------------------------------------------------
00474 
00475 void SimSimulator::step()
00476 {
00477     preSubSteps();
00478     while ( ! subStepsDone() ) {
00479         subStep();
00480     }
00481     postSubSteps();
00482 }
00483 
00484 //------------------------------------------------------------------------------
00485 
00486 void SimSimulator::preSubSteps()
00487 {
00488     UInt32 i;
00489 
00490     if ( PRINT_STATS ) {
00491         std::cout << "****************************************" << std::endl;
00492         std::cout << "Simulating at time " << _time << std::endl;
00493     }
00494 
00495     _fenergy[ F_STRETCH ] = 0;
00496     _fenergy[ F_SHEAR ] = 0;
00497     _fenergy[ F_BEND ] = 0;
00498 
00499     _venergy = .5 * _v0.dot( _M * _v0 );
00500 
00501     // Clear all forces
00502     _f0.clear();
00503 
00504     // *= 0 is better than clear() here - it retains the sparsity pattern
00505     // within the matrix, to avoid unnecessary reallocations after the first
00506     // call to step().
00507     _df_dx *= 0;
00508     _df_dv *= 0;
00509     for( i = 0; i < NB_FORCES; ++i ) {
00510         _f0i[ i ].clear();
00511         _d0i[ i ].clear();
00512         _df_dxi[ i ] *= 0;
00513         _dd_dxi[ i ] *= 0;
00514         _dd_dvi[ i ] *= 0;
00515     }
00516     _modPCG._A *= 0;
00517     _modPCG._b.clear();
00518 
00519     GeMesh::FaceConstIterator fi;
00520     for( fi = _mesh->beginFace(); fi != _mesh->endFace(); ++fi ) {
00521         calcStretchShear( *fi );
00522     }
00523     GeMeshWingedEdge::EdgeIterator ei;
00524 
00525     for(
00526         ei = _initialMeshWingedEdge->beginEdge();
00527         ei != _initialMeshWingedEdge->endEdge();
00528         ++ei
00529     ) {
00530         // Only do edges that aren't on the boundary.
00531         if ( ei->hasTwin() ) {
00532             calcBend( *ei );
00533         }
00534     }
00535 
00536     for( i = 0; i < _mesh->getNbVertices(); ++i ) {
00537         const GeMatrix3& M = _M( i, i );
00538         Float gravity = -M( 2, 2 ) * _params._g;
00539         _f0[ i ]._z += gravity;
00540         DO_DEBUG( _f0i[ F_GRAVITY ][ i ]._z = gravity );
00541     }
00542 
00543     for ( fi = _mesh->beginFace(); fi != _mesh->endFace(); ++fi ) {
00544         Float area( fi->calcArea() );
00545         const GeVector normal( fi->calcNormal() );
00546         GeMesh::FaceVertexId fvid;
00547         for ( fvid = 0; fvid < fi->getNbVertices(); ++fvid ) {
00548             UInt32 vid( fi->getVertexId( fvid ) );
00549             Float vel( _v0[ vid ].dot( normal ) );
00550             const GeVector force( ( -_params._k_drag * vel * area ) * normal );
00551             _f0[ vid ] += force;
00552             DO_DEBUG( _f0i[ F_DRAG ][ vid ] += force );
00553         }
00554     }
00555 
00556     _energy = _venergy + _fenergy[ F_STRETCH ] +
00557         _fenergy[ F_SHEAR ] + _fenergy[ F_BEND ];
00558     if ( DEBUG_STEP ) {
00559         for ( UInt32 i = 0; i < NB_FORCES; ++i ) {
00560             const char* s[] = { "stretch","shear","bend","gravity","drag" };
00561             std::cout << "f0[" << s[i] << "] = " << _f0i[ i ] << std::endl;
00562             std::cout << std::endl;
00563             std::cout << "d0[" << s[i] << "] = " << _d0i[ i ] << std::endl;
00564             std::cout << std::endl;
00565             std::cout << "df_dx[" << s[i] <<"] = " << _df_dxi[ i ] << std::endl;
00566             std::cout << std::endl;
00567             std::cout << "dd_dx[" << s[i] <<"] = " << _dd_dxi[ i ] << std::endl;
00568             std::cout << std::endl;
00569             std::cout << "dd_dv[" << s[i] <<"] = " << _dd_dvi[ i ] << std::endl;
00570             std::cout << std::endl;
00571             std::cout << std::endl;
00572         }
00573     }
00574 
00575     if ( DEBUG_STEP ) {
00576         std::cout << "f0 = " << _f0 << std::endl;
00577         std::cout << "df_dx = " << _df_dx << std::endl;
00578         std::cout << "df_dv = " << _df_dv << std::endl;
00579     }
00580 
00581     // Paper eq. (16)
00582     _modPCG._A = _df_dx * (-_h * _h) + _df_dv * -_h + _M;
00583     _modPCG._b = _h * ( _h * _df_dx * _v0 + _f0 );
00584 
00585     if ( DEBUG_STEP ) {
00586         std::cout << "A = " << _modPCG._A << std::endl;
00587         std::cout << "b = " << _modPCG._b << std::endl;
00588     }
00589 
00590     // Now, we're left with a system Ax=b, where x corresponds to deltav
00591     
00592     _modPCG._z = _h * _z0;
00593     _modPCG.preStep();
00594 }
00595 
00596 //------------------------------------------------------------------------------
00597 
00598 bool SimSimulator::subStepsDone() const
00599 {
00600     return _modPCG.done();
00601 }
00602 
00603 //------------------------------------------------------------------------------
00604 
00605 void SimSimulator::subStep()
00606 {
00607     _modPCG.step();
00608 }
00609 
00610 //------------------------------------------------------------------------------
00611 
00612 void SimSimulator::postSubSteps()
00613 {
00614     const SimVector& x = _modPCG.result();
00615     if ( DEBUG_STEP ) {
00616         std::cout << "deltav = " << x << std::endl;
00617         std::cout << "Ax = " << _modPCG._A * x << std::endl;
00618     }
00619 
00620     _v0 += x;
00621 
00622     GeMesh::VertexIterator vi;
00623     UInt32 i;
00624     for ( vi = _mesh->beginVertex(), i = 0; vi != _mesh->endVertex(); ++vi, ++i ) {
00625         (*vi) += _h * _v0[ i ];
00626     }
00627     _time += _h;
00628     if ( PRINT_STATS ) {
00629         std::cout.precision( 4 );
00630         std::cout.width( 6 );
00631         std::cout.setf( std::ios::fixed );
00632         std::cout << "Total energy: "
00633             << std::setprecision( 5 ) << std::setw( 7 )
00634             << std::setiosflags( std::ios::fixed )
00635             << _energy
00636             << "( stretch: " << _fenergy[ F_STRETCH ]
00637             << " / shear: " << _fenergy[ F_SHEAR ]
00638             << " / bend: " << _fenergy[ F_BEND ]
00639             //<< " / kinetic: " << _venergy
00640             << ")" << std::resetiosflags( std::ios::fixed ) << std::endl;
00641         std::cout << std::endl;
00642     }
00643 
00644     if ( DUMP_DISTS ) {
00645         static std::ofstream* fptr;
00646         if ( fptr == 0 ) {
00647             Float distance( (
00648                 _initialMesh->getVertex( 1 ) - _initialMesh->getVertex( 0 )
00649             ).length() * 3 );
00650             String filename(
00651                 "dists-" + BaStringUtil::fromFloat( distance, 1 ) + ".txt"
00652             );
00653             fptr = new std::ofstream( filename.c_str() );
00654         }
00655         std::ofstream& out = *fptr;
00656         GeMesh::VertexConstIterator vbi = _initialMesh->beginVertex();
00657         GeMesh::VertexConstIterator vi = _mesh->beginVertex();
00658         for ( ; vi != _mesh->endVertex(); ++vi, ++vbi ) {
00659             out << ( *vi - *vbi ).length() << " ";
00660         }
00661         out << std::endl;
00662     }
00663 
00664     if ( DUMP_FORCES ) {
00665         static std::ofstream* fptr;
00666         if ( fptr == 0 ) {
00667             Float distance( (
00668                 _initialMesh->getVertex( 1 ) - _initialMesh->getVertex( 0 )
00669             ).length() * 3 );
00670             String filename(
00671                 "forces-" + BaStringUtil::fromFloat( distance, 2 ) + ".txt"
00672             );
00673             fptr = new std::ofstream( filename.c_str() );
00674         }
00675         std::ofstream& out = *fptr;
00676         for ( UInt32 i = 0; i < _f0i[ F_STRETCH ].size(); ++i ) {
00677             out << _f0i[ F_STRETCH ][ i ].length() << " ";
00678             out << _f0i[ F_SHEAR ][ i ].length() << " ";
00679             out << _f0i[ F_BEND ][ i ].length() << " ";
00680             out << _d0i[ F_STRETCH ][ i ].length() << " ";
00681             out << _d0i[ F_SHEAR ][ i ].length() << " ";
00682             out << _d0i[ F_BEND ][ i ].length() << " ";
00683         }
00684         out << std::endl;
00685     }
00686 }
00687 
00688 //------------------------------------------------------------------------------
00689 
00690 const GeMesh& SimSimulator::getMesh() const
00691 {
00692     return *_mesh;
00693 }
00694 
00695 //------------------------------------------------------------------------------
00696 
00697 const RCShdPtr<GeMesh>& SimSimulator::getMeshPtr() const
00698 {
00699     return _mesh;
00700 }
00701 
00702 //------------------------------------------------------------------------------
00703 
00704 BaTime::Instant SimSimulator::getTime() const
00705 {
00706     return BaTime::floatAsInstant( _time );
00707 }
00708 
00709 //------------------------------------------------------------------------------
00710 
00711 void SimSimulator::setTimestep( Float h )
00712 {
00713     _h = h;
00714 }
00715 
00716 //------------------------------------------------------------------------------
00717 
00718 void SimSimulator::setDensity( Float rho )
00719 {
00720     _rho = rho;
00721     setupMass();
00722 }
00723 
00724 //------------------------------------------------------------------------------
00725 
00726 void SimSimulator::setPCGTolerance( Float tolerance )
00727 {
00728     _modPCG.setTolerance( tolerance );
00729 }
00730 
00731 //------------------------------------------------------------------------------
00732 
00733 void SimSimulator::setParams( const Params& params )
00734 {
00735     _params = params;
00736 }
00737 
00738 //------------------------------------------------------------------------------
00739 
00740 Float SimSimulator::getTimestep() const
00741 {
00742     return _h;
00743 }
00744 
00745 //------------------------------------------------------------------------------
00746 
00747 Float SimSimulator::getDensity() const
00748 {
00749     return _rho;
00750 }
00751 
00752 //------------------------------------------------------------------------------
00753 
00754 Float SimSimulator::getPCGTolerance() const
00755 {
00756     return _modPCG.getTolerance();
00757 }
00758 
00759 //------------------------------------------------------------------------------
00760 
00761 const SimSimulator::Params& SimSimulator::getParams() const
00762 {
00763     return _params;
00764 }
00765 
00766 //------------------------------------------------------------------------------
00767 
00768 GeVector SimSimulator::getVelocity( GeMesh::VertexId vid ) const
00769 {
00770     DGFX_ASSERT( vid < _v0.size() );
00771     return _v0[ vid ];
00772 }
00773 
00774 //------------------------------------------------------------------------------
00775 
00776 GeVector SimSimulator::getForce( GeMesh::VertexId vid ) const
00777 {
00778     DGFX_ASSERT( vid < _f0.size() );
00779     return _f0[ vid ];
00780 }
00781 
00782 //------------------------------------------------------------------------------
00783 
00784 GeVector SimSimulator::getForce( ForceType type, GeMesh::VertexId vid ) const
00785 {
00786     DGFX_ASSERT( type < NB_FORCES );
00787     DGFX_ASSERT( vid < _f0i[ type ].size() );
00788     return _f0i[ type ][ vid ];
00789 }
00790 
00791 //------------------------------------------------------------------------------
00792 
00793 GeVector SimSimulator::getDampingForce(
00794     ForceType type,
00795     GeMesh::VertexId vid
00796 ) const {
00797     DGFX_ASSERT( type < NB_FORCES );
00798     DGFX_ASSERT( vid < _d0i[ type ].size() );
00799     return _d0i[ type ][ vid ];
00800 }
00801 
00802 //------------------------------------------------------------------------------
00803 
00804 Float SimSimulator::getEnergy( ForceType type ) const
00805 {
00806     DGFX_ASSERT( type < NB_FORCES );
00807     return _fenergy[ type ];
00808 }
00809 
00810 //------------------------------------------------------------------------------
00811 
00812 Float SimSimulator::getTriEnergy( ForceType type, GeMesh::FaceId fid ) const
00813 {
00814     DGFX_ASSERT( type < F_GRAVITY );
00815     DGFX_ASSERT( fid < _trienergy[ type ].size() );
00816     return _trienergy[ type ][ fid ];
00817 }
00818 
00819 //------------------------------------------------------------------------------
00820 
00821 void SimSimulator::setMesh( const GeMesh& mesh )
00822 {
00823     DGFX_ASSERT( mesh.getNbVertices() == _initialMesh->getNbVertices() );
00824     DGFX_ASSERT( mesh.getNbFaces() == _initialMesh->getNbFaces() );
00825     _mesh = RCShdPtr<GeMesh>( new GeMesh( mesh ) );
00826 }
00827 
00828 
00829 
00830 //------------------------------------------------------------------------------
00831 
00832 void SimSimulator::calcStretchShear(
00833     const GeMesh::FaceWrapper& face
00834 ) {
00835     UInt32 m;
00836 
00837     // My x[0],x[1],x[2] are equivalent to [BarWit98]'s xi,xj,xk.
00838     GeMesh::VertexType x[3];
00839     GeMesh::TextureVertexType tp[3];
00840     for( m = 0; m < 3; ++m ) {
00841         x[ m ] = face.getVertex( m );
00842         tp[ m ] = _initialMesh->getTextureVertex( face.getVertexId( m ) );
00843     }
00844     if ( DEBUG_COMMON ) {
00845         std::cout << "x0 = " << x[0] << " x1 = " << x[1]
00846             << " x2 = " << x[2] << std::endl;
00847     }
00848 
00849     GeVector v0[ 3 ];
00850     for( m = 0; m < 3; ++m ) {
00851         UInt32 vid = face.getVertexId( m );
00852         v0[ m ] = _v0[ vid ];
00853     }
00854 
00855     CommonVars cv;
00856     cv.calc( x, tp );
00857     if ( DEBUG_COMMON ) {
00858         cv.debugOutput( std::cout );
00859     }
00860 
00861     calcStretch( face, cv, x, tp, v0 );
00862     calcShear( face, cv, x, tp, v0 );
00863 
00864     if ( VERIFY_COMMON ) {
00865 #if DO_NORM
00866         const Float MAX_VERIFY_ERROR = .01; // maximum allowed
00867         const Float MAX_VERIFY_ERROR_M = MAX_VERIFY_ERROR * 3; // for matrices
00868         const Float VERIFY_STEP = .001;     // db
00869         CommonVars ver_cv[3][3];
00870         for( m = 0; m < 3; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
00871             GePoint testx[3] = { x[0], x[1], x[2] };
00872             testx[ m ][ s ] += VERIFY_STEP;
00873             ver_cv[ m ][ s ].calc( testx, tp );
00874         }
00875 
00876         bool DISPLAY;
00877 
00878         UInt32 n,s,t;
00879         DISPLAY = false;
00880         for( m = 0; m < 3; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
00881             const CommonVars& testcv = ver_cv[m][s];
00882 
00883             GeVector test_dwhatu_dxm = ( testcv._whatu - cv._whatu ) / VERIFY_STEP;
00884             GeVector test_dwhatv_dxm = ( testcv._whatv - cv._whatv ) / VERIFY_STEP;
00885 
00886             Float err;
00887 
00888             if ( DISPLAY ) {
00889                 std::cout << "test_dwhatu_dxm[ " << m << " ][ " << s << " ] = "
00890                     << test_dwhatu_dxm << std::endl;
00891             }
00892             err = ( test_dwhatu_dxm - cv._dwhatu_dxm[m][s] ).infinityNorm();
00893             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
00894 
00895             if ( DISPLAY ) {
00896                 std::cout << "test_dwhatv_dxm[ " << m << " ][ " << s << " ] = "
00897                     << test_dwhatv_dxm << std::endl;
00898             }
00899             err = ( test_dwhatv_dxm - cv._dwhatv_dxm[m][s] ).infinityNorm();
00900             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
00901         }
00902 
00903         DISPLAY = false;
00904         for ( n = 0; n < 3; ++n ) for( m = 0; m < 3; ++m ) {
00905             for( s = 0; s < 3; ++s ) for( t = 0; t < 3; ++t ) {
00906                 const CommonVars& testcv = ver_cv[n][t];
00907                 GeVector test_d2whatu_dxmdxn =
00908                     (testcv._dwhatu_dxm[m][s] - cv._dwhatu_dxm[m][s]) / VERIFY_STEP;
00909                 GeVector test_d2whatv_dxmdxn =
00910                     (testcv._dwhatv_dxm[m][s] - cv._dwhatv_dxm[m][s]) / VERIFY_STEP;
00911 
00912                 Float err;
00913 
00914                 if ( DISPLAY ) {
00915                     std::cout << "test_d2whatu_dxmdxn[" << m << "][" << n << "]["
00916                         << s << "][" << t << "] = "
00917                         << test_d2whatu_dxmdxn << std::endl;
00918                 }
00919                 err = (
00920                     test_d2whatu_dxmdxn - cv._d2whatu_dxmdxn[m][n][s][t]
00921                 ).infinityNorm();
00922                 DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
00923 
00924                 if ( DISPLAY ) {
00925                     std::cout << "test_d2whatv_dxmdxn[" << m << "][" << n << "]["
00926                         << s << "][" << t << "] = "
00927                         << test_d2whatv_dxmdxn << std::endl;
00928                 }
00929                 err = (
00930                     test_d2whatv_dxmdxn - cv._d2whatv_dxmdxn[m][n][s][t]
00931                 ).infinityNorm();
00932                 DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
00933             }
00934         }
00935 #endif
00936 
00937     }
00938 }
00939 
00940 
00941 //------------------------------------------------------------------------------
00942 
00943 void SimSimulator::calcStretch(
00944     const GeMesh::FaceWrapper& face,
00945     const CommonVars &cv,
00946     const GePoint x[3],
00947     const GePoint tp[3],
00948     const GeVector v0[ 3 ]
00949 ) {
00950     const Float MAX_VERIFY_ERROR = .01f; // maximum allowed
00951     const Float MAX_VERIFY_ERROR_M = MAX_VERIFY_ERROR * 3; // for matrices
00952     const Float VERIFY_STEP = .001f;     // db
00953     UInt32 m,n,s,t;
00954 
00955     StretchVars stv;
00956     stv.calc( cv, v0, _params._b_u, _params._b_v );
00957 
00958     if ( DEBUG_STRETCH ) {
00959         stv.debugOutput( std::cout );
00960     }
00961 
00962     for ( m = 0; m < 3; ++m ) {
00963         UInt32 vid = face.getVertexId( m );
00964         GeVector val;
00965 
00966         // As per [BarWit98] eq. (7)
00967         val = -_params._k_stretch * (
00968             stv._dCu_dxm[ m ] * stv._Cu + stv._dCv_dxm[ m ] * stv._Cv
00969         );
00970         _f0[ vid ] += val;
00971         DO_DEBUG( _f0i[ F_STRETCH ][ vid ] += val );
00972         if ( DEBUG_STRETCH ) {
00973             std::cout << "f0[stretch][ " << m << " ] = " << val << std::endl;
00974         }
00975 
00976         val = -_params._k_damp * _params._k_stretch * (
00977             stv._dCu_dxm[ m ] * stv._dCu_dt
00978             + stv._dCv_dxm[ m ] * stv._dCv_dt
00979         );
00980         _f0[ vid ] += val;
00981 
00982         DO_DEBUG( _d0i[ F_STRETCH ][ vid ] += val );
00983         if ( DEBUG_STRETCH ) {
00984             std::cout << "d0[stretch][ " << m << " ] = " << val << std::endl;
00985         }
00986     }
00987     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
00988         UInt32 vidm = face.getVertexId( m );
00989         UInt32 vidn = face.getVertexId( n );
00990         GeMatrix3 val;
00991 
00992         // As per [BarWit98] eq. (8)
00993         val = -_params._k_stretch * (
00994             GeMatrix3::outerProduct( stv._dCu_dxm[ m ], stv._dCu_dxm[ n ] )
00995             + GeMatrix3::outerProduct( stv._dCv_dxm[ m ], stv._dCv_dxm[ n ] )
00996             + stv._d2Cu_dxmdxn[ m ][ n ] * stv._Cu
00997             + stv._d2Cv_dxmdxn[ m ][ n ] * stv._Cv
00998         );
00999         _df_dx[ vidn ][ vidm ] += val;
01000         if ( DEBUG_STRETCH ) {
01001             _df_dxi[ F_STRETCH ][ vidn ][ vidm ] += val;
01002             std::cout << "df_dx[stretch][ " << m << " ][ " << n << " ] = "
01003                 << val << std::endl;
01004         }
01005 
01006         val = -_params._k_damp * _params._k_stretch * (
01007             stv._d2Cu_dxmdxn[ m ][ n ] * stv._dCu_dt
01008             + stv._d2Cv_dxmdxn[ m ][ n ] * stv._dCv_dt
01009         );
01010         _df_dx[ vidn ][ vidm ] += val;
01011         if ( DEBUG_STRETCH ) {
01012             _dd_dxi[ F_STRETCH ][ vidn ][ vidm ] += val;
01013             std::cout << "dd_dx[stretch][ " << m << " ][ " << n << " ] = "
01014                 << val << std::endl;
01015         }
01016 
01017         val = -_params._k_damp * _params._k_stretch * (
01018             GeMatrix3::outerProduct( stv._dCu_dxm[m], stv._dCu_dxm[n] )
01019             + GeMatrix3::outerProduct( stv._dCv_dxm[m], stv._dCv_dxm[n] )
01020         );
01021         _df_dv[ vidn ][ vidm ] += val;
01022         if ( DEBUG_STRETCH ) {
01023             _dd_dvi[ F_STRETCH ][ vidn ][ vidm ] += val;
01024             std::cout << "dd_dv[stretch][ " << m << " ][ " << n << " ] = "
01025                 << val << std::endl;
01026         }
01027     }
01028 
01029     Float E =
01030         _params._k_stretch * .5 * ( stv._Cu * stv._Cu + stv._Cv * stv._Cv );
01031     _trienergy[ F_STRETCH ][ face.getFaceId() ] = E;
01032     _fenergy[ F_STRETCH ] += E;
01033 
01034     if ( DEBUG_STRETCH ) {
01035         std::cout << std::endl;
01036     }
01037 
01038     if ( VERIFY_STRETCH ) {
01039         StretchVars ver_stv[3][3];
01040         for( m = 0; m < 3; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
01041             GePoint testx[3] = { x[0], x[1], x[2] };
01042             testx[ m ][ s ] += VERIFY_STEP;
01043             CommonVars ver_cv;
01044             ver_cv.calc( testx, tp );
01045             ver_stv[ m ][ s ].calc( ver_cv, v0, _params._b_u, _params._b_v );
01046         }
01047         bool DISPLAY;
01048 
01049         DISPLAY = false;
01050         for( m = 0; m < 3; ++m ) {
01051             GeVector testdCu_dxm, testdCv_dxm;
01052             for( UInt32 s = 0; s < 3; ++s ) {
01053                 const StretchVars& teststv = ver_stv[m][s];
01054                 testdCu_dxm[ s ] = ( teststv._Cu - stv._Cu ) / VERIFY_STEP;
01055                 testdCv_dxm[ s ] = ( teststv._Cv - stv._Cv ) / VERIFY_STEP;
01056             }
01057             Float err;
01058             if ( DISPLAY ) {
01059                 std::cout << "testdCu_dxm[ " << m << " ] = " << testdCu_dxm << std::endl;
01060                 std::cout << "testdCv_dxm[ " << m << " ] = " << testdCv_dxm << std::endl;
01061             }
01062             err = (
01063                 testdCu_dxm - stv._dCu_dxm[ m ]
01064             ).infinityNorm();
01065             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01066             err = (
01067                 testdCv_dxm - stv._dCv_dxm[ m ]
01068             ).infinityNorm();
01069             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01070         }
01071 
01072         DISPLAY = false;
01073         for( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01074             GeMatrix3 testd2Cu_dxmdxn, testd2Cv_dxmdxn;
01075             for( t = 0; t < 3; ++t ) {
01076                 const StretchVars& teststv = ver_stv[n][t];
01077                 const GeVector diffu(
01078                     teststv._dCu_dxm[ m ] - stv._dCu_dxm[ m ]
01079                 );
01080                 const GeVector diffv(
01081                     teststv._dCv_dxm[ m ] - stv._dCv_dxm[ m ]
01082                 );
01083                 for( s = 0; s < 3; ++s ) {
01084                     testd2Cu_dxmdxn( t, s ) = diffu[ s ] / VERIFY_STEP;
01085                     testd2Cv_dxmdxn( t, s ) = diffv[ s ] / VERIFY_STEP;
01086                 }
01087             }
01088 
01089             Float err;
01090             if ( DISPLAY ) {
01091                 std::cout << "testd2Cu_dxmdxn[ " << m << " ][ " << n
01092                     << " ] = " << testd2Cu_dxmdxn << std::endl;
01093             }
01094             err = (
01095                 testd2Cu_dxmdxn - stv._d2Cu_dxmdxn[ m ][ n ]
01096             ).infinityNorm();
01097             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01098 
01099             if ( DISPLAY ) {
01100                 std::cout << "testd2Cv_dxmdxn[ " << m << " ][ " << n
01101                     << " ] = " << testd2Cv_dxmdxn << std::endl;
01102             }
01103             err = (
01104                 testd2Cv_dxmdxn - stv._d2Cv_dxmdxn[ m ][ n ]
01105             ).infinityNorm();
01106             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01107         }
01108     }
01109 }
01110 
01111 //------------------------------------------------------------------------------
01112 
01113 void SimSimulator::calcShear(
01114     const GeMesh::FaceWrapper& face,
01115     const CommonVars &cv,
01116     const GePoint x[4],
01117     const GePoint tp[4],
01118     const GeVector v0[ 3 ]
01119 ) {
01120     const Float MAX_VERIFY_ERROR = .01f; // maximum allowed
01121     const Float MAX_VERIFY_ERROR_M = MAX_VERIFY_ERROR * 3; // for matrices
01122     const Float VERIFY_STEP = .001f;     // db
01123     UInt32 m,n,s,t;
01124 
01125     ShearVars shv;
01126     shv.calc( cv, v0 );
01127 
01128     if ( DEBUG_SHEAR ) {
01129         shv.debugOutput( std::cout );
01130     }
01131 
01132     for ( m = 0; m < 3; ++m ) {
01133         UInt32 vid = face.getVertexId( m );
01134         GeVector val;
01135 
01136         val = -_params._k_shear * shv._dC_dxm[ m ] * shv._C;
01137         _f0[ vid ] += val;
01138         DO_DEBUG( _f0i[ F_SHEAR ][ vid ] += val );
01139         if ( DEBUG_SHEAR ) {
01140             std::cout << "f0[shear][ " << m << " ] = " << val << std::endl;
01141         }
01142 
01143         val = -_params._k_damp * _params._k_shear
01144             * shv._dC_dxm[ m ] * shv._dC_dt;
01145         _f0[ vid ] += val;
01146 
01147         DO_DEBUG( _d0i[ F_SHEAR ][ vid ] += val );
01148         if ( DEBUG_SHEAR ) {
01149             std::cout << "d0[shear][ " << m << " ] = " << val << std::endl;
01150         }
01151     }
01152     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01153         UInt32 vidm = face.getVertexId( m );
01154         UInt32 vidn = face.getVertexId( n );
01155         GeMatrix3 val;
01156         val = -_params._k_shear * (
01157             GeMatrix3::outerProduct( shv._dC_dxm[ m ], shv._dC_dxm[ n ] )
01158             + shv._d2C_dxmdxn[ m ][ n ] * shv._C
01159         );
01160         _df_dx[ vidn ][ vidm ] += val;
01161         if ( DEBUG_SHEAR ) {
01162             _df_dxi[ F_SHEAR ][ vidn ][ vidm ] += val;
01163             std::cout << "df_dx[shear][ " << m << " ][ " << n << " ] = "
01164                 << val << std::endl;
01165         }
01166 
01167         val = -_params._k_damp * _params._k_shear
01168             * shv._d2C_dxmdxn[ m ][ n ] * shv._dC_dt;
01169         _df_dx[ vidn ][ vidm ] += val;
01170         if ( DEBUG_SHEAR ) {
01171             _dd_dxi[ F_SHEAR ][ vidn ][ vidm ] += val;
01172             std::cout << "dd_dx[shear][ " << m << " ][ " << n << " ] = "
01173                 << val << std::endl;
01174         }
01175 
01176         val = -_params._k_damp * _params._k_shear
01177             * GeMatrix3::outerProduct( shv._dC_dxm[ m ], shv._dC_dxm[ n ] );
01178         _df_dv[ vidn ][ vidm ] += val;
01179 
01180         if ( DEBUG_SHEAR ) {
01181             _dd_dvi[ F_SHEAR ][ vidn ][ vidm ] += val;
01182             std::cout << "dd_dv[shear][ " << m << " ][ " << n << " ] = "
01183                 << val << std::endl;
01184         }
01185     }
01186 
01187     Float E = _params._k_shear * .5 * shv._C * shv._C;
01188     _trienergy[ F_SHEAR ][ face.getFaceId() ] = E;
01189     _fenergy[ F_SHEAR ] += E;
01190 
01191     if ( DEBUG_SHEAR ) {
01192         std::cout << std::endl;
01193     }
01194 
01195     if ( VERIFY_SHEAR ) {
01196         ShearVars ver_shv[3][3];
01197         for( m = 0; m < 3; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
01198             GePoint testx[3] = { x[0], x[1], x[2] };
01199             testx[ m ][ s ] += VERIFY_STEP;
01200             CommonVars ver_cv;
01201             ver_cv.calc( testx, tp );
01202             ver_shv[ m ][ s ].calc( ver_cv, v0 );
01203         }
01204         bool DISPLAY;
01205 
01206         DISPLAY = false;
01207         for( m = 0; m < 3; ++m ) {
01208             GeVector testdC_dxm;
01209             for( UInt32 s = 0; s < 3; ++s ) {
01210                 const ShearVars& testshv = ver_shv[m][s];
01211                 testdC_dxm[ s ] = ( testshv._C - shv._C ) / VERIFY_STEP;
01212             }
01213             Float err;
01214             if ( DISPLAY ) {
01215                 std::cout << "testdC_dxm[ " << m << " ] = " << testdC_dxm << std::endl;
01216             }
01217             err = (
01218                 testdC_dxm - shv._dC_dxm[ m ]
01219             ).infinityNorm();
01220             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01221         }
01222 
01223         DISPLAY = false;
01224         for( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01225             GeMatrix3 testd2C_dxmdxn;
01226             for( t = 0; t < 3; ++t ) {
01227                 const ShearVars& testshv = ver_shv[n][t];
01228                 const GeVector diff( testshv._dC_dxm[ m ] - shv._dC_dxm[ m ] );
01229                 for( s = 0; s < 3; ++s ) {
01230                     testd2C_dxmdxn( t, s ) = diff[ s ] / VERIFY_STEP;
01231                 }
01232             }
01233 
01234             Float err;
01235             if ( DISPLAY ) {
01236                 std::cout << "testd2C_dxmdxn[ " << m << " ][ " << n
01237                     << " ] = " << testd2C_dxmdxn << std::endl;
01238             }
01239             err = (
01240                 testd2C_dxmdxn - shv._d2C_dxmdxn[ m ][ n ]
01241             ).infinityNorm();
01242             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01243         }
01244     }
01245 }
01246 
01247 //------------------------------------------------------------------------------
01248 
01249 void SimSimulator::calcBend(
01250     const GeMeshWingedEdge::HalfEdgeWrapper& edge
01251 ) {
01252     const Float MAX_VERIFY_ERROR = .01f; // maximum allowed
01253     const Float MAX_VERIFY_ERROR_M = MAX_VERIFY_ERROR * 3; // for matrices
01254     const Float VERIFY_STEP = .001f;     // db
01255     UInt32 m, n, s, t;
01256 
01257     GeMeshWingedEdge::HalfEdgeWrapper he_next( edge.getNextHalfEdge() );
01258     GeMeshWingedEdge::HalfEdgeWrapper he_prev( edge.getPrevHalfEdge() );
01259     GeMeshWingedEdge::HalfEdgeWrapper he_twin( edge.getTwinHalfEdge() );
01260 
01261     GeMesh::VertexId vid[ 4 ];
01262     vid[ 0 ] = he_prev.getOriginVertexId();
01263     vid[ 1 ] = edge.getOriginVertexId();
01264     vid[ 2 ] = he_next.getOriginVertexId();
01265     vid[ 3 ] = he_twin.getPrevHalfEdge().getOriginVertexId();
01266     GeMesh::VertexType x[ 4 ];
01267     GeMesh::TextureVertexType tv[ 4 ];
01268     GeVector v[ 4 ];
01269     for( m = 0; m < 4; ++m ) {
01270         x[ m ] = _mesh->getVertex( vid[ m ] );
01271         tv[ m ] = _initialMesh->getTextureVertex( vid[ m ] );
01272         v[ m ] = _v0[ vid[ m ] ];
01273     }
01274 
01275     const Float du = tv[ 1 ]._x - tv[ 2 ]._x;
01276     const Float dv = tv[ 1 ]._y - tv[ 2 ]._y;
01277     const Float k = (
01278         _params._k_bend_u * du*du + _params._k_bend_v * dv*dv ) /
01279         (du*du + dv*dv);
01280 
01281     BendVars bv;
01282     bv.calc( x, v );
01283     if ( DEBUG_BEND ) {
01284         std::cout << "x0 = " << x[0] << "  x1 = " << x[1]
01285             << "  x2 = " << x[2] << "  x3 = " << x[3] << std::endl;
01286         std::cout << "k = " << k << std::endl;
01287         bv.debugOutput( std::cout );
01288     }
01289 
01290     // Same finale as stretch/shear
01291     for ( m = 0; m < 4; ++m ) {
01292         GeVector val;
01293 
01294         val = -k * bv._dC_dxm[ m ] * bv._C;
01295         _f0[ vid[ m ] ] += val;
01296         DO_DEBUG( _f0i[ F_BEND ][ vid[ m ] ] += val );
01297         if ( DEBUG_BEND ) {
01298             std::cout << "f0[bend][ " << m << " ] = " << val << std::endl;
01299         }
01300 
01301         val = -_params._k_damp * k * bv._dC_dxm[ m ] * bv._dC_dt;
01302         _f0[ vid[ m ] ] += val;
01303 
01304         DO_DEBUG( _d0i[ F_BEND ][ vid[ m ] ] += val );
01305         if ( DEBUG_BEND ) {
01306             std::cout << "d0[bend][ " << m << " ] = " << val << std::endl;
01307         }
01308     }
01309 
01310     Float E = .5 * k * bv._C * bv._C;
01311     // Spread energy to both triangles for debugging
01312     _trienergy[ F_BEND ][ edge.getFaceId() ] += E * .5;
01313     _trienergy[ F_BEND ][ he_twin.getFaceId() ] += E * .5;
01314     _fenergy[ F_BEND ] += E;
01315 
01316     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
01317         GeMatrix3 val;
01318         val = -k * (
01319             GeMatrix3::outerProduct( bv._dC_dxm[ m ], bv._dC_dxm[ n ] )
01320             + bv._d2C_dxmdxn[ m ][ n ] * bv._C
01321         );
01322         _df_dx[ vid[ n ] ][ vid[ m ] ] += val;
01323         if ( DEBUG_BEND ) {
01324             _df_dxi[ F_BEND ][ vid[ n ] ][ vid[ m ] ] += val;
01325             std::cout << "df_dx[bend][ " << m << " ][ " << n << " ] = "
01326                 << val << std::endl;
01327         }
01328 
01329         val = -_params._k_damp * k
01330             * bv._d2C_dxmdxn[ m ][ n ] * bv._dC_dt;
01331         _df_dx[ vid[ n ] ][ vid[ m ] ] += val;
01332         if ( DEBUG_BEND ) {
01333             _dd_dxi[ F_BEND ][ vid[ n ] ][ vid[ m ] ] += val;
01334             std::cout << "dd_dx[bend][ " << m << " ][ " << n << " ] = "
01335                 << val << std::endl;
01336         }
01337 
01338         val = -_params._k_damp * k
01339             * GeMatrix3::outerProduct( bv._dC_dxm[ m ], bv._dC_dxm[ n ] );
01340         _df_dv[ vid[ n ] ][ vid[ m ] ] += val;
01341 
01342         if ( DEBUG_BEND ) {
01343             _dd_dvi[ F_BEND ][ vid[ n ] ][ vid[ m ] ] += val;
01344             std::cout << "dd_dv[bend][ " << m << " ][ " << n << " ] = "
01345                 << val << std::endl;
01346         }
01347     }
01348     if ( DEBUG_BEND ) {
01349         std::cout << std::endl << std::endl;
01350     }
01351 
01352     if ( VERIFY_BEND ) {
01353         BendVars ver_bv[4][3];
01354         for( m = 0; m < 4; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
01355             GePoint testx[4] = { x[0], x[1], x[2], x[3] };
01356             testx[ m ][ s ] += VERIFY_STEP;
01357             ver_bv[ m ][ s ].calc( testx, v, bv );
01358         }
01359         bool DISPLAY;
01360 
01361         DISPLAY = false;
01362         for( m = 0; m < 4; ++m ) for( UInt32 s = 0; s < 3; ++s ) {
01363             const BendVars& testbv = ver_bv[m][s];
01364 
01365             GeVector test_dnhatA_dxm =
01366                 ( testbv._nhatA - bv._nhatA ) / VERIFY_STEP;
01367             GeVector test_dnhatB_dxm =
01368                 ( testbv._nhatB - bv._nhatB ) / VERIFY_STEP;
01369             GeVector test_dehat_dxm = ( testbv._ehat - bv._ehat ) / VERIFY_STEP;
01370 
01371             Float err;
01372 
01373             if ( DISPLAY ) {
01374                 std::cout << "test_dnhatA_dxm[ " << m << " ][ " << s << "] = "
01375                     << test_dnhatA_dxm << std::endl;
01376             }
01377             err = ( test_dnhatA_dxm - bv._dnhatA_dxm[m][s] ).infinityNorm();
01378             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01379 
01380             if ( DISPLAY ) {
01381                 std::cout << "test_dnhatB_dxm[ " << m << " ][ " << s << "] = "
01382                     << test_dnhatB_dxm << std::endl;
01383             }
01384             err = ( test_dnhatB_dxm - bv._dnhatB_dxm[m][s] ).infinityNorm();
01385             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01386 
01387             if ( DISPLAY ) {
01388                 std::cout << "test_dehat_dxm[ " << m << " ][ " << s << "] = "
01389                     << test_dehat_dxm << std::endl;
01390             }
01391             err = ( test_dehat_dxm - bv._dehat_dxm[m][s] ).infinityNorm();
01392             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01393         }
01394 
01395         DISPLAY = false;
01396         for( n = 0; n < 4; ++n ) {
01397             GeVector test_d2nA_dxmdxn[ 4 ][ 3 ][ 3 ];
01398             GeVector test_d2nB_dxmdxn[ 4 ][ 3 ][ 3 ];
01399             GeVector test_d2e_dxmdxn[ 4 ][ 3 ][ 3 ];
01400             for( t = 0; t < 3; ++t ) {
01401                 const BendVars& testbv = ver_bv[n][t];
01402                 for( m = 0; m < 4; ++m ) for( s = 0; s < 3; ++s ) {
01403                     test_d2nA_dxmdxn[ m ][ s ][ t ] = (
01404                         testbv._dnhatA_dxm[ m ][ s ] - bv._dnhatA_dxm[ m ][ s ]
01405                     ) / VERIFY_STEP;
01406                     test_d2nB_dxmdxn[ m ][ s ][ t ] = (
01407                         testbv._dnhatB_dxm[ m ][ s ] - bv._dnhatB_dxm[ m ][ s ]
01408                     ) / VERIFY_STEP;
01409                     test_d2e_dxmdxn[ m ][ s ][ t ] = (
01410                         testbv._dehat_dxm[ m ][ s ] - bv._dehat_dxm[ m ][ s ]
01411                     ) / VERIFY_STEP;
01412                 }
01413             }
01414             Float err;
01415             for ( m = 0; m < 4; ++m ) {
01416                 for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
01417                     if ( DISPLAY ) {
01418                         std::cout << "test_d2nA_dxmdxn[ " << m << " ][ "
01419                             << n << " ][ " << s << " ][ " << t << " ] = "
01420                             << test_d2nA_dxmdxn[ m ][ s ][ t ] << std::endl;
01421                     }
01422                     test_d2nA_dxmdxn[m][s][t] -= bv._d2nA_dxmdxn[m][n][s][t];
01423                     err = test_d2nA_dxmdxn[m][s][t].infinityNorm();
01424                     DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01425 
01426                     if ( DISPLAY ) {
01427                         std::cout << "test_d2nB_dxmdxn[ " << m << " ][ "
01428                             << n << " ][ " << s << " ][ " << t << " ] = "
01429                             << test_d2nB_dxmdxn[ m ][ s ][ t ] << std::endl;
01430                     }
01431                     test_d2nB_dxmdxn[m][s][t] -= bv._d2nB_dxmdxn[m][n][s][t];
01432                     err = test_d2nB_dxmdxn[m][s][t].infinityNorm();
01433                     DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01434 
01435                     if ( DISPLAY ) {
01436                         std::cout << "test_d2e_dxmdxn[ " << m << " ][ "
01437                             << n << " ][ " << s << " ][ " << t << " ] = "
01438                             << test_d2e_dxmdxn[ m ][ s ][ t ] << std::endl;
01439                     }
01440 #if DO_NORM
01441                     test_d2e_dxmdxn[m][s][t] -= bv._d2e_dxmdxn[m][n][s][t];
01442 #endif
01443                     err = test_d2e_dxmdxn[m][s][t].infinityNorm();
01444                     DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01445                 }
01446             }
01447         }
01448 
01449         DISPLAY = false;
01450         for( m = 0; m < 4; ++m ) {
01451             GeVector test_dcosth_dxm, test_dsinth_dxm;
01452             for( UInt32 s = 0; s < 3; ++s ) {
01453                 const BendVars& testbv = ver_bv[m][s];
01454 
01455                 test_dcosth_dxm[ s ] =
01456                     (testbv._costh - bv._costh ) / VERIFY_STEP;
01457                 test_dsinth_dxm[ s ] =
01458                     (testbv._sinth - bv._sinth ) / VERIFY_STEP;
01459             }
01460             Float err;
01461 
01462             if ( DISPLAY ) {
01463                 std::cout << "test_dcosth_dxm[ " << m << " ] = "
01464                     << test_dcosth_dxm << std::endl;
01465             }
01466             err = (
01467                 test_dcosth_dxm - bv._dcosth_dxm[ m ]
01468             ).infinityNorm();
01469             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01470             if ( DISPLAY ) {
01471                 std::cout << "test_dsinth_dxm[ " << m << " ] = "
01472                     << test_dsinth_dxm << std::endl;
01473             }
01474             err = (
01475                 test_dsinth_dxm - bv._dsinth_dxm[ m ]
01476             ).infinityNorm();
01477             DGFX_ASSERT( err < MAX_VERIFY_ERROR );
01478         }
01479 
01480         DISPLAY = false;
01481         for( n = 0; n < 4; ++n ) {
01482             for( m = 0; m < 4; ++m ) {
01483                 GeMatrix3 test_d2costh_dxmdxn, test_d2sinth_dxmdxn;
01484                 for( t = 0; t < 3; ++t ) {
01485                     const BendVars& testbv = ver_bv[n][t];
01486                     const GeVector diffc(
01487                         ( testbv._dcosth_dxm[ m ] - bv._dcosth_dxm[ m ] ) / VERIFY_STEP
01488                     );
01489                     const GeVector diffs(
01490                         ( testbv._dsinth_dxm[ m ] - bv._dsinth_dxm[ m ] ) / VERIFY_STEP
01491                     );
01492                     for ( s = 0; s < 3; ++s ) {
01493                         test_d2costh_dxmdxn( t, s ) = diffc[ s ];
01494                         test_d2sinth_dxmdxn( t, s ) = diffs[ s ];
01495                     }
01496                 }
01497 
01498                 Float err;
01499 
01500                 if ( DISPLAY ) {
01501                     std::cout << "test_d2costh_dxmdxn[ " << m << " ][ " << n << " ] = "
01502                         << test_d2costh_dxmdxn << std::endl;
01503                 }
01504                 err = (
01505                     test_d2costh_dxmdxn - bv._d2costh_dxmdxn[ m ][ n ]
01506                 ).infinityNorm();
01507                 DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01508 
01509                 if ( DISPLAY ) {
01510                     std::cout << "test_d2sinth_dxmdxn[ " << m << " ][ " << n << " ] = "
01511                         << test_d2sinth_dxmdxn << std::endl;
01512                 }
01513                 err = (
01514                     test_d2sinth_dxmdxn - bv._d2sinth_dxmdxn[ m ][ n ]
01515                 ).infinityNorm();
01516                 DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01517             }
01518         }
01519 
01520         DISPLAY = false;
01521         for( m = 0; m < 4; ++m ) {
01522             GeVector testdC_dxm;
01523             for( UInt32 s = 0; s < 3; ++s ) {
01524                 const BendVars& testbv = ver_bv[m][s];
01525                 testdC_dxm[ s ] = ( testbv._C - bv._C ) / VERIFY_STEP;
01526             }
01527             Float err;
01528             if ( DISPLAY ) {
01529                 std::cout << "testdC_dxm[ " << m << " ] = "
01530                     << testdC_dxm << std::endl;
01531             }
01532             err = (
01533                 testdC_dxm - bv._dC_dxm[ m ]
01534             ).infinityNorm();
01535             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01536         }
01537 
01538         DISPLAY = false;
01539         for ( n = 0; n < 4; ++n ) for( m = 0; m < 4; ++m ) {
01540             GeMatrix3 testd2C_dxmdxn;
01541             for( t = 0; t < 3; ++t ) {
01542                 const BendVars& testbv = ver_bv[n][t];
01543                 const GeVector diff( testbv._dC_dxm[ m ] - bv._dC_dxm[ m ] );
01544                 for( s = 0; s < 3; ++s ) {
01545                     testd2C_dxmdxn( t, s ) = diff[ s ] / VERIFY_STEP;
01546                 }
01547             }
01548 
01549             Float err;
01550             if ( DISPLAY ) {
01551                 std::cout << "testd2C_dxmdxn[ " << m << " ][ " << n
01552                     << " ] = " << testd2C_dxmdxn << std::endl;
01553             }
01554             err = (
01555                 testd2C_dxmdxn - bv._d2C_dxmdxn[ m ][ n ]
01556             ).infinityNorm();
01557             DGFX_ASSERT( err < MAX_VERIFY_ERROR_M );
01558         }
01559     }
01560 }
01561 
01562 
01563 ////////////////////////////////////////////////////////////////////////////////
01564 // CLASS SimSimulator::CommonVars
01565 
01566 //------------------------------------------------------------------------------
01567 
01568 void SimSimulator::CommonVars::calc( const GePoint_3 p, const GePoint_3 tp )
01569 {
01570     _du1 = tp[1]._x - tp[0]._x;
01571     _dv1 = tp[1]._y - tp[0]._y;
01572     _du2 = tp[2]._x - tp[0]._x;
01573     _dv2 = tp[2]._y - tp[0]._y;
01574     const Float det = _du1 * _dv2 - _du2 * _dv1;
01575     //DGFX_ASSERT( ! BaMath::isEqual( det, 0 ) );
01576     const Float detInv = 1 / det;
01577 
01578     // Area in u/v co-ordinates.
01579     // $ a = \frac{1}{2} \norm{
01580     //          \begin{pmatrix} \du_1 \\ \dv_1 \\ 0 \end{pmatrix} \cross
01581     //          \begin{pmatrix} \du_2 \\ \dv_2 \\ 0 \end{pmatrix} } $
01582     _a = .5 * ( tp[ 1 ] - tp[ 0 ] ).cross( tp[ 2 ] - tp[ 0 ] ).length();
01583 
01584     // $ \whatu = \frac{ (\x_1 - \x_0) \dv_2 - (\x_2 - \x_0) \dv_1}
01585     //      {\du_1 \dv_2 - \du_2 \dv_1} $
01586     _wu = ((p[1]-p[0]) * _dv2 + (p[2]-p[0]) * (-_dv1)) * detInv;
01587     const Float wu_len = _wu.length();
01588     DGFX_ASSERT( BaMath::isGreater( wu_len, 0 ) );
01589     _wuim = 1 / wu_len;
01590     // $ \wu = \frac{ \whatu }{\norm {\whatu}} $
01591     _whatu = _wu * _wuim;
01592 
01593     // $ \whatv = \frac{ -(\x_1 - \x_0) \du_2 + (\x_2 - \x_0) \du_1}
01594     //      {\du_1 \dv_2 - \du_2 \dv_1} $
01595     _wv = (-(p[1]-p[0]) * _du2 + (p[2]-p[0]) * _du1) * detInv;
01596     const Float wv_len = _wv.length();
01597     DGFX_ASSERT( BaMath::isGreater( wv_len, 0 ) );
01598     _wvim = 1 / wv_len;
01599     // $ \wv = \frac{ \whatv }{\norm {\whatv}} $
01600     _whatv = _wv * _wvim;
01601 
01602     // Array subscript refers to *which* p this is a derivative
01603     // of pi, pj or pk. Here, we only have a scalar value - 
01604     // _dwux_dxmx, the derivative of the x-component of wu with
01605     // respect to the x-component of pi (or pj, or pk, etc.).
01606     // dwhu_dxm should be _dwux_dxmx times a 3x3 identity matrix.
01607     // $ \pfrac{\whatux}{\x_{0_x}} =
01608     //      \frac{\dv_1 - \dv_2}{\du_1\dv_2 - \du_2\dv_1} $
01609     // $ \pfrac{\whatux}{\x_{1_x}} = \frac{\dv_2}{\du_1\dv_2 - \du_2\dv_1} $
01610     // $ \pfrac{\whatux}{\x_{2_x}} = \frac{-\dv_1}{\du_1\dv_2 - \du_2\dv_1} $
01611     _dwux_dxmx[ 0 ] = (_dv1 - _dv2) * detInv;
01612     _dwux_dxmx[ 1 ] = _dv2 * detInv;
01613     _dwux_dxmx[ 2 ] =-_dv1 * detInv;
01614     // $ \pfrac{\whatvx}{\x_{0_x}} =
01615     //      \frac{\du_2 - \du_1}{\du_1\dv_2 - \du_2\dv_1} $
01616     // $ \pfrac{\whatvx}{\x_{1_x}} = \frac{-\du_2}{\du_1\dv_2 - \du_2\dv_1} $
01617     // $ \pfrac{\whatvx}{\x_{2_x}} = \frac{\du_1}{\du_1\dv_2 - \du_2\dv_1} $
01618     _dwvx_dxmx[ 0 ] = (_du2 - _du1) * detInv;
01619     _dwvx_dxmx[ 1 ] =-_du2 * detInv;
01620     _dwvx_dxmx[ 2 ] = _du1 * detInv;
01621 
01622 #if DO_NORM
01623     UInt32 m,n,s,t;
01624 
01625     for( m = 0; m < 3; ++m ) {
01626         for ( s = 0; s < 3; ++s ) {
01627             // $ \pfrac{\wu}{\xms} =
01628             //      \frac{1}{\norm{\whatu}}
01629             //      \pfrac{\whatux}{\xmx} \left( \Is - \wus \wu \right) $
01630             _dwhatu_dxm[ m ][ s ] = _wuim * _dwux_dxmx[ m ] *
01631                 ( GeVector::axis( s ) - _whatu[ s ] * _whatu );
01632             // $ \pfrac{\wv}{\xms} =
01633             //      \frac{1}{\norm{\whatv}}
01634             //      \pfrac{\whatvx}{\xmx} \left( \Is - \wvs \wv \right) $
01635             _dwhatv_dxm[ m ][ s ] = _wvim * _dwvx_dxmx[ m ] *
01636                 ( GeVector::axis( s ) - _whatv[ s ] * _whatv );
01637         }
01638     }
01639 
01640     for( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01641         for( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
01642             // $ \pfractwo{\wu}{\xms}{\xnt} &=
01643             //      -\frac{1}{\norm{\whatu}} \pfrac{\whatux}{\xmx} \left(
01644             //          \wus \pfrac{\wu}{\xnt} + \pfrac{\wus}{\xnt} \wu
01645             //      \right) -
01646             //      \pfrac{\whatux}{\xmx} \pfrac{\whatux}{\xnx}
01647             //      \frac{( \Is - \wus \wu ) \wut}{\norm{\whatu}^2} $
01648             _d2whatu_dxmdxn[m][n][s][t] =
01649                 -_wuim * _dwux_dxmx[ m ] *
01650                 (_whatu[s] * _dwhatu_dxm[n][t] + _dwhatu_dxm[n][t][s] * _whatu)
01651                 - _wuim*_wuim * _dwux_dxmx[m] * _dwux_dxmx[n] *
01652                 (GeVector::axis(s) - _whatu[s]*_whatu) * _whatu[t];
01653 
01654             // $ \pfractwo{\wv}{\xms}{\xnt} =
01655             //    -\frac{1}{\norm{\whatv}} \pfrac{\whatvx}{\xmx} \left(
01656             //        \wvs \pfrac{\wv}{\xnt} + \pfrac{\wvs}{\xnt} \wv
01657             //    \right) -
01658             //    \pfrac{\whatvx}{\xmx} \pfrac{\whatvx}{\xnx}
01659             //    \frac{( \Is - \wvs \wv ) \wvt}{\norm{\whatv}^2} $
01660             _d2whatv_dxmdxn[m][n][s][t] =
01661                 -_wvim * _dwvx_dxmx[ m ] *
01662                 (_whatv[s] * _dwhatv_dxm[n][t] + _dwhatv_dxm[n][t][s] * _whatv)
01663                 - _wvim*_wvim * _dwvx_dxmx[m] * _dwvx_dxmx[n] *
01664                 (GeVector::axis(s) - _whatv[s]*_whatv) * _whatv[t];
01665         }
01666     }
01667 #endif
01668 }
01669 
01670 //------------------------------------------------------------------------------
01671 
01672 void SimSimulator::CommonVars::debugOutput( std::ostream& os ) {
01673     UInt32 m;
01674 
01675     os << "a = " << _a << std::endl;
01676     os << "whatu = " << _whatu << "  _wuim = " << _wuim << "  wu = "
01677         << _wu << std::endl;
01678     os << "whatv = " << _whatv << "  _wvim = " << _wvim << "  wv = "
01679         << _wv << std::endl;
01680     for ( m = 0; m < 3; ++m ) {
01681         os << "_dwux_dxmx[" << m << "] = " << _dwux_dxmx[ m ] << std::endl;
01682         os << "_dwvx_dxmx[" << m << "] = " << _dwvx_dxmx[ m ] << std::endl;
01683     }
01684 #if DO_NORM
01685     UInt32 n,s,t;
01686 
01687     for ( m = 0; m < 3; ++m ) for ( s = 0; s < 3; ++s ) {
01688         std::cout << "_dwhatu_dxm[" << m << "][" << s << "] = " << _dwhatu_dxm[m][s]
01689             << std::endl;
01690         std::cout << "_dwhatv_dxm[" << m << "][" << s << "] = " << _dwhatv_dxm[m][s]
01691             << std::endl;
01692     }
01693     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01694         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
01695             std::cout << "_d2whatu_dxmdxn[" << m << "][" << n << "][" << s << "]["
01696                 << t << "] = " << _d2whatu_dxmdxn[m][n][s][t] << std::endl;
01697             std::cout << "_d2whatv_dxmdxn[" << m << "][" << n << "][" << s << "]["
01698                 << t << "] = " << _d2whatv_dxmdxn[m][n][s][t] << std::endl;
01699         }
01700     }
01701 #endif
01702 }
01703 
01704 
01705 ////////////////////////////////////////////////////////////////////////////////
01706 // CLASS SimSimulator::StretchVars
01707 
01708 //------------------------------------------------------------------------------
01709 
01710 void SimSimulator::StretchVars::calc(
01711     const SimSimulator::CommonVars& cv,
01712     const GeVector v0[ 3 ],
01713     Float b_u, Float b_v
01714 ) {
01715     UInt32 m,n;
01716 #if DO_SCALE_INVARIANT
01717     Float alpha = BaMath::sqrt( cv._a );
01718     // alpha = cv._a ^ 3/4
01719     alpha = alpha * BaMath::sqrt( alpha );
01720 #else
01721     const Float alpha = cv._a;
01722 #endif
01723 
01724     // As per [BarWit98] eq. (10)
01725     // $ \C = a \left(
01726     //      \begin{pmatrix}
01727     //          \norm{\wu} - b_u \\ %
01728     //          \norm{\wv} - b_v
01729     //      \end{pmatrix} \right) $
01730     _Cu = alpha * ( cv._wu.length() - b_u );
01731     _Cv = alpha * ( cv._wv.length() - b_v );
01732 
01733     for ( m = 0; m < 3; ++m ) {
01734         // $ \pfrac{\Cu}{\xm} = a \pfrac{\whatux}{\xmx} \wu $
01735         _dCu_dxm[ m ] = alpha * cv._dwux_dxmx[ m ] * cv._whatu;
01736         // $ \pfrac{\Cv}{\xm} = a \pfrac{\whatvx}{\xmx} \wv $
01737         _dCv_dxm[ m ] = alpha * cv._dwvx_dxmx[ m ] * cv._whatv;
01738     }
01739 
01740     // As per [BarWit98] equation just before (11) - but corrected to be
01741     // a sum.
01742     _dCu_dt = 0;
01743     _dCv_dt = 0;
01744     for( m = 0; m < 3; ++m ) {
01745         _dCu_dt += _dCu_dxm[ m ].dot( v0[ m ] );
01746         _dCv_dt += _dCv_dxm[ m ].dot( v0[ m ] );
01747     }
01748 
01749     // Second derivative of C, split into u and v components
01750     // FIXME: this is symmetric - if you switch pm and pn, you get the same
01751     // result.
01752     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01753         // $ \pfractwo{\Cu}{\xm}{\xn} =
01754         //      \frac{a}{\norm{\wuhat}}
01755         //      \pfrac{\whatux}{\xmx} \pfrac{\whatux}{\xnx}
01756         //      \left( \I - \wu \wu^T \right) $
01757 
01758         _d2Cu_dxmdxn[ m ][ n ] =
01759             alpha * cv._wuim * cv._dwux_dxmx[ m ] * cv._dwux_dxmx[ n ]
01760             * ( GeMatrix3::IDENTITY -
01761                 GeMatrix3::outerProduct( cv._whatu, cv._whatu ) );
01762 
01763         // $ \pfractwo{\Cv}{\xm}{\xn} =
01764         //      \frac{a}{\norm{\wvhat}}
01765         //      \pfrac{\whatvx}{\xmx} \pfrac{\whatvx}{\xnx}
01766         //      \left( \I - \wv \wv^T \right) $
01767 
01768         _d2Cv_dxmdxn[ m ][ n ] =
01769             alpha * cv._wvim * cv._dwvx_dxmx[ m ] * cv._dwvx_dxmx[ n ]
01770             * ( GeMatrix3::IDENTITY -
01771                 GeMatrix3::outerProduct( cv._whatv, cv._whatv ) );
01772     }
01773 }
01774 
01775 //------------------------------------------------------------------------------
01776 
01777 void SimSimulator::StretchVars::debugOutput( std::ostream& os )
01778 {
01779     UInt32 m,n;
01780     os << "C = ( " << _Cu << ", " << _Cv << " ) " << std::endl;
01781     for ( m = 0; m < 3; ++m ) {
01782         os << "dCu_dxm[ " << m << " ] = " << _dCu_dxm[ m ] << std::endl;
01783         os << "dCv_dxm[ " << m << " ] = " << _dCv_dxm[ m ] << std::endl;
01784     }
01785     os << "dCu_dt = " << _dCu_dt << std::endl;
01786     os << "dCv_dt = " << _dCv_dt << std::endl;
01787     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01788         os << "d2Cu_dxmdxn[ " << m << "," << n << " ] = "
01789             << _d2Cu_dxmdxn[ m ][ n ] << std::endl;
01790         os << "d2Cv_dxmdxn[ " << m << "," << n << " ] = "
01791             << _d2Cv_dxmdxn[ m ][ n ] << std::endl;
01792     }
01793 }
01794 
01795 
01796 ////////////////////////////////////////////////////////////////////////////////
01797 // CLASS SimSimulator::ShearVars
01798 
01799 //------------------------------------------------------------------------------
01800 
01801 void SimSimulator::ShearVars::calc(
01802     const SimSimulator::CommonVars& cv,
01803     const GeVector v0[ 3 ]
01804 ) {
01805     UInt32 m,n,s;
01806 
01807 #if DO_SCALE_INVARIANT
01808     Float alpha = BaMath::sqrt( cv._a );
01809     alpha = alpha * BaMath::sqrt( alpha );
01810 #else
01811     const Float alpha = cv._a;
01812 #endif
01813     // As per [BarWit98] section 4.3
01814     // $ C = a \wu \cdot \wv $
01815 #if DO_NORM
01816     // Correction: use normalised wu, wv
01817     _C = alpha * cv._whatu.dot( cv._whatv );
01818 #else
01819     _C = alpha * cv._wu.dot( cv._wv );
01820 #endif
01821 
01822     // $ \pfrac{C}{\xms} = a \left(
01823     //      \pfrac{\wu}{\xms} \cdot \wv + \wu \cdot pfrac{dwv}{\xms}
01824     //   \right) $
01825     for ( m = 0; m < 3; ++m ) {
01826         for ( s = 0; s < 3; ++s ) {
01827             _dC_dxm[ m ][ s ] = alpha * (
01828 #if DO_NORM
01829                 cv._dwhatu_dxm[m][s].dot( cv._whatv ) +
01830                 cv._whatu.dot( cv._dwhatv_dxm[m][s] )
01831 #else
01832                 cv._dwux_dxmx[m] * cv._wv[s] +
01833                 cv._wu[s] * cv._dwvx_dxmx[m]
01834 #endif
01835             );
01836         }
01837     }
01838 
01839     // As per [BarWit98] equation just before (11)
01840     _dC_dt = 0;
01841     for( m = 0; m < 3; ++m ) {
01842         _dC_dt += _dC_dxm[ m ].dot( v0[ m ] );
01843     }
01844 
01845     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01846 #if DO_NORM
01847         // $ \pfractwo{C}{\xms}{\xnt} = a \left(
01848         //      \pfractwo{\wu}{\xms}{\xnt} \cdot \wv +
01849         //      \pfrac{\wu}{\xms} \cdot \pfrac{\wv}{\xnt} +
01850         //      \pfrac{\wu}{\xnt} \cdot \pfrac{\wv}{\xms} +
01851         //      \wu \cdot \pfractwo{\wu}{\xms}{\xnt} \right) $
01852         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
01853             _d2C_dxmdxn[m][n]( t, s ) = alpha * (
01854                 cv._d2whatu_dxmdxn[m][n][s][t].dot( cv._whatv ) +
01855                 cv._dwhatu_dxm[m][s].dot( cv._dwhatv_dxm[n][t] ) +
01856                 cv._dwhatu_dxm[n][t].dot( cv._dwhatv_dxm[m][s] ) +
01857                 cv._whatu.dot( cv._d2whatv_dxmdxn[m][n][s][t] )
01858             );
01859         }
01860 #else
01861         // $ \pfractwo{C}{\xms}{\xnt} = a \left(
01862         //      \pfrac{\whatu}{\xms} \cdot \pfrac{\whatv}{\xnt} +
01863         //      \pfrac{\whatu}{\xnt} \cdot \pfrac{\whatv}{\xms} \right) $
01864         _d2C_dxmdxn[m][n] = GeMatrix3::ZERO;
01865         for ( s = 0; s < 3; ++s ) {
01866             _d2C_dxmdxn[m][n]( s, s ) = alpha * (
01867                 cv._dwux_dxmx[m] * cv._dwvx_dxmx[n] +
01868                 cv._dwux_dxmx[n] * cv._dwvx_dxmx[m]
01869             );
01870         }
01871 #endif
01872     }
01873 }
01874 
01875 //------------------------------------------------------------------------------
01876 
01877 void SimSimulator::ShearVars::debugOutput( std::ostream& os )
01878 {
01879     UInt32 m,n;
01880 
01881     os << "C = " << _C << std::endl;
01882     for ( m = 0; m < 3; ++m ) {
01883         os << "dC_dxm[ " << m << " ] = " << _dC_dxm[ m ] << std::endl;;
01884     }
01885     os << "dC_dt = " << _dC_dt << std::endl;;
01886     for ( m = 0; m < 3; ++m ) for ( n = 0; n < 3; ++n ) {
01887         os << "d2C_dxmdxn[ " << m << "," << n << " ] = "
01888             << _d2C_dxmdxn[ m ][ n ] << std::endl;
01889     }
01890 }
01891 
01892 
01893 ////////////////////////////////////////////////////////////////////////////////
01894 // CLASS SimSimulator::BendVars
01895 
01896 //------------------------------------------------------------------------------
01897 
01898 void SimSimulator::BendVars::calc(
01899     const GePoint_4 x,
01900     const GeVector_4 v
01901 ) {
01902     // My x[0],x[1],x[2],x[3] are equivalent to Macri's ph,pi,pj,pk
01903     // My nhatA,nhatB are equivalent to Baraff & Witkin's n1,n2
01904     // i.e. unit vectors
01905     // My nA, nB are unscaled versions of nhatA,nhatB
01906     // _nAim = 1 / || nA ||      "nA inverse magnitude"
01907     calcNE( x );
01908     mainCalc( x, v );
01909 }
01910 
01911 //------------------------------------------------------------------------------
01912 
01913 void SimSimulator::BendVars::calc(
01914     const GePoint_4 x,
01915     const GeVector_4 v,
01916     const BendVars& bv
01917 ) {
01918     calcNE( x );
01919 #if !DO_NORM
01920     // Enforce the assumption that the normals have constant magnitude - don't
01921     // scale by 1/||nA||, instead scale by the inverse of the *old* normal's
01922     // magnitude.
01923     _nhatA *= bv._nAim / _nAim;
01924     _nAim = bv._nAim;
01925     _nhatB *= bv._nBim / _nBim;
01926     _nBim = bv._nBim;
01927     _ehat *= bv._eim / _eim;
01928     _eim = bv._eim;
01929 #endif
01930     mainCalc( x, v );
01931 }
01932 
01933 //------------------------------------------------------------------------------
01934 
01935 void SimSimulator::BendVars::mainCalc(
01936     const GePoint_4 x,
01937     const GeVector_4 v0
01938 ) {
01939     UInt32 m;
01940 
01941     calcThetas();
01942     calcQs( x );
01943     calcDqs();
01944     calcNEderiv();
01945     calcD2NE();
01946     calcCosSinDeriv();
01947     calcD2cossinth();
01948     calcCderivs();
01949 
01950     _dC_dt = 0;
01951     // As per [BarWit98] equation just before (11)
01952     for( m = 0; m < 4; ++m ) {
01953         _dC_dt += _dC_dxm[ m ].dot( v0[ m ] );
01954     }
01955 }
01956 
01957 //------------------------------------------------------------------------------
01958 
01959 void SimSimulator::BendVars::calcNE( const GePoint_4 x )
01960 {
01961     // $ \nhat^A = (\x_2 - \x_0) \cross (\x_1 - \x_0) $
01962     const GeVector nA( (x[2] - x[0]).cross( x[1] - x[0] ) );
01963     // nA inverse magnitude
01964     _nAim = 1 / nA.length();
01965     // $ \n^A = \frac{\nhat^A}{\norm{\nhat^A}} $
01966     _nhatA = _nAim * nA;
01967 
01968     // $ \nhat^B = (\x_1 - \x_3) \cross (\x_2 - \x_3) $
01969     const GeVector nB( (x[1] - x[3]).cross( x[2] - x[3] ) );
01970     _nBim = 1 / nB.length();
01971     // $ \n^B = \frac{\nhat^B}{\norm{\nhat^B}} $
01972     _nhatB = _nBim * nB;
01973 
01974     // $ \ehat = \x_1 - \x_2 $
01975     const GeVector e( x[1] - x[2] );
01976     _eim = 1 / e.length();
01977     // $ \e = \frac{\ehat}{\norm{\ehat}} $
01978     _ehat = _eim * e;
01979 }
01980 
01981 //------------------------------------------------------------------------------
01982 
01983 void SimSimulator::BendVars::calcThetas()
01984 {
01985     // $ \cos \theta = \n^A \cdot \n^B $
01986     _costh = _nhatA.dot( _nhatB );
01987     // $ \sin \theta = (\n^A \cross \n^B) \cdot \e $
01988     _sinth = _nhatA.cross( _nhatB ).dot( _ehat );
01989     // FIXME: not *just* arctan
01990     // $ C = \theta = \arctan \frac{\sin \theta}{\cos \theta} $
01991     // In range [-pi,+pi] - Macri uses abs of this!
01992     _C = BaMath::arctan2( _sinth, _costh );
01993 }
01994 
01995 //------------------------------------------------------------------------------
01996 
01997 void SimSimulator::BendVars::calcQs( const GePoint_4 x )
01998 {
01999     // $ \pfrac{\nhat^A}{\xms} = S_s(\q^A_m) $
02000     // $ \q^A_0 = \x_2 - \x_1 $
02001     // $ \q^A_1 = \x_0 - \x_2 $
02002     // $ \q^A_2 = \x_1 - \x_0 $
02003     // $ \q^A_3 = {\bf 0} $
02004     _qA[ 0 ] = x[2] - x[1];
02005     _qA[ 1 ] = x[0] - x[2];
02006     _qA[ 2 ] = x[1] - x[0];
02007     _qA[ 3 ] = GeVector::ZERO;
02008 
02009     // $ \pfrac{\nhat^B}{\xms} = S_s(\q^B_m) $
02010     // $ \q^B_0 = {\bf 0} $
02011     // $ \q^B_1 = \x_2 - \x_3 $
02012     // $ \q^B_2 = \x_3 - \x_1 $
02013     // $ \q^B_3 = \x_1 - \x_2 $
02014     _qB[ 0 ] = GeVector::ZERO;
02015     _qB[ 1 ] = x[2] - x[3];
02016     _qB[ 2 ] = x[3] - x[1];
02017     _qB[ 3 ] = x[1] - x[2];
02018 
02019     // $ \pfrac{\ehat}{\xms} = q^e_m \Is $
02020     // $ q^e = \begin{pmatrix} 0 \\ 1 \\ -1 \\ 0 \end{pmatrix} $
02021     _qe[ 0 ] = 0;
02022     _qe[ 1 ] = 1;
02023     _qe[ 2 ] = -1;
02024     _qe[ 3 ] = 0;
02025 }
02026 
02027 //------------------------------------------------------------------------------
02028 
02029 void SimSimulator::BendVars::calcDqs()
02030 {
02031     // FIXME: document this
02032     
02033     // Row represents m, column represents n
02034     const Int32 D1[4][4] = {
02035         { 0, -1, 1, 0 },
02036         { 1, 0, -1, 0 },
02037         { -1, 1, 0, 0 },
02038         { 0, 0, 0, 0 }
02039     };
02040     const Int32 D2[4][4] = {
02041         { 0, 0, 0, 0 },
02042         { 0, 0, 1, -1 },
02043         { 0, -1, 0, 1 },
02044         { 0, 1, -1, 0 }
02045     };
02046     for( UInt32 m = 0; m < 4; ++m ) {
02047         for( UInt32 n = 0; n < 4; ++n ) {
02048             for( UInt32 t = 0; t < 3; ++t ) {
02049                 _dqAm_dxn[m][n][t] = GeVector::ZERO;
02050                 _dqAm_dxn[m][n][t][t] = D1[m][n];
02051                 _dqBm_dxn[m][n][t] = GeVector::ZERO;
02052                 _dqBm_dxn[m][n][t][t] = D2[m][n];
02053             }
02054         }
02055     }
02056 }
02057 
02058 //------------------------------------------------------------------------------
02059 
02060 void SimSimulator::BendVars::calcNEderiv()
02061 {
02062 #if DO_NORM
02063     const GeMatrix3 InAnAt =
02064         GeMatrix3::IDENTITY - GeMatrix3::outerProduct( _nhatA, _nhatA );
02065     const GeMatrix3 InBnBt =
02066         GeMatrix3::IDENTITY - GeMatrix3::outerProduct( _nhatB, _nhatB );
02067     const GeMatrix3 Ieet =
02068         GeMatrix3::IDENTITY - GeMatrix3::outerProduct( _ehat, _ehat );
02069 
02070     for ( UInt32 m = 0; m < 4; ++m ) {
02071         for ( UInt32 s = 0; s < 3; ++s ) {
02072             // $ \pfrac{\n^A}{\xms} = \left(\I - \n^A(\n^A)^T\right)
02073             //      \frac{ S_s( \q^A_m ) }{ \norm{\nhat^A} } $
02074             _dnhatA_dxm[ m ][ s ] = InAnAt * makeSkewRow( _qA[ m ], s ) * _nAim;
02075             // $ \pfrac{\n^B}{\xms} = \left(\I - \n^B(\n^B)^T\right)
02076             //      \frac{ S_s( \q^B_m ) }{ \norm{\nhat^B} } $
02077             _dnhatB_dxm[ m ][ s ] = InBnBt * makeSkewRow( qB[ m ], s ) * _nBim;
02078             // $ \pfrac{\e}{\xms} = (\I - \e\e^T)
02079             //      \frac{ \Is( q^e_m ) }{ \norm{\ehat} } $
02080             _dehat_dxm[ m ][ s ] = Ieet * GeVector::axis( s ) * _qe[ m ] * _eim;
02081         }
02082     }
02083 #else
02084     for ( UInt32 m = 0; m < 4; ++m ) {
02085         for ( UInt32 s = 0; s < 3; ++s ) {
02086             _dnhatA_dxm[ m ][ s ] = makeSkewRow( _qA[ m ], s ) * _nAim;
02087             _dnhatB_dxm[ m ][ s ] = makeSkewRow( _qB[ m ], s ) * _nAim;
02088             _dehat_dxm[ m ][ s ] = GeVector::axis( s ) * _qe[ m ] * _eim;
02089         }
02090     }
02091 #endif
02092 }
02093 
02094 //------------------------------------------------------------------------------
02095 
02096 void SimSimulator::BendVars::calcD2NE()
02097 {
02098     UInt32 m,n,s,t;
02099 #if DO_NORM
02100     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02101         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02102             GeMatrix3 tempm;
02103             GeVector tempv;
02104 
02105             // $ \pfractwo{\n^A}{\xms}{\xnt} =
02106             // - \left(
02107             //      \pfrac{\n^A}{\xnt} (\n^A)^T +
02108             //      \n^A \left( \pfrac{\n^A}{\xnt} \right)^T
02109             //   \right) \frac{S_s(\q^A_m)}{\norm{\nhat^A}} +
02110             //   \frac{\I - \n^A(\n^A)^T}{\norm{\nhat^A}^2}
02111             //   \left(
02112             //      \norm{\nhat^A} S_s\left( \pfrac{\q^A_m}{\xnt} \right) -
02113             //      \left( S_t(\q^A_n) \cdot \n^A \right) S_s(\q^A_m)
02114             //   \right) $
02115 
02116             GeVector SqAm = makeSkewRow( _qA[ m ], s );
02117             GeVector SqAn = makeSkewRow( _qA[ n ], t );
02118             tempm = GeMatrix3::outerProduct( _dnhatA_dxm[ n ][ t ], _nhatA );
02119             tempm += GeMatrix3::outerProduct( _nhatA, _dnhatA_dxm[ n ][ t ] );
02120             _d2nA_dxmdxn[m][n][s][t] = tempm * SqAm * -_nAim;
02121             tempm = (
02122                 GeMatrix3::IDENTITY - GeMatrix3::outerProduct( _nhatA, _nhatA )
02123             ) * (_nAim * _nAim);
02124             tempv = makeSkewRow( _dqAm_dxn[ m ][ n ][ t ], s ) / _nAim;
02125             tempv -= SqAn.dot( _nhatA ) * SqAm;
02126             _d2nA_dxmdxn[m][n][s][t] += tempm * tempv;
02127 
02128             // $ \pfractwo{\n^B}{\xms}{\xnt} =
02129             // - \left(
02130             //      \pfrac{\n^B}{\xnt} (\n^B)^T +
02131             //      \n^B \left( \pfrac{\n^B}{\xnt} \right)^T
02132             //   \right) \frac{S_s(\q^B_m)}{\norm{\nhat^B}} +
02133             //   \frac{\I - \n^B(\n^B)^T}{\norm{\nhat^B}^2}
02134             //   \left(
02135             //      \norm{\nhat^B} S_s\left( \pfrac{\q^B_m}{\xnt} \right) -
02136             //      \left( S_t(\q^B_n) \cdot \n^B \right) S_s(\q^B_m)
02137             //   \right) $
02138 
02139             GeVector SqBm = makeSkewRow( qB[ m ], s );
02140             GeVector SqBn = makeSkewRow( qB[ n ], t );
02141             tempm = GeMatrix3::outerProduct( _dnhatB_dxm[ n ][ t ], _nhatB );
02142             tempm += GeMatrix3::outerProduct( _nhatB, _dnhatB_dxm[ n ][ t ] );
02143             _d2nB_dxmdxn[m][n][s][t] = tempm * SqBm * -_nBim;
02144             tempm = (
02145                 GeMatrix3::IDENTITY -GeMatrix3::outerProduct( _nhatB, _nhatB )
02146             ) * (_nBim * _nBim);
02147             tempv = makeSkewRow( _dqBm_dxn[ m ][ n ][ t ], s ) / _nBim;
02148             tempv -= SqBn.dot( _nhatB ) * SqBm;
02149             _d2nB_dxmdxn[m][n][s][t] += tempm * tempv;
02150 
02151             // $ \pfractwo{\e}{\xms}{\xnt} =
02152             // - \left(
02153             //      \pfrac{\e}{\xnt} \e^T +
02154             //      \e \left( \pfrac{\e}{\xnt} \right)^T
02155             //   \right) \frac{S_s(q^e_m)}{\norm{\ehat}} -
02156             //   \frac{\I - \e\e^T}{\norm{\ehat}^2}
02157             //      q^e_m q^e_n \e_t \Is $
02158 
02159             tempm = GeMatrix3::outerProduct( _dehat_dxm[ n ][ t ], _ehat );
02160             tempm += GeMatrix3::outerProduct( _ehat, _dehat_dxm[ n ][ t ] );
02161             _d2e_dxmdxn[m][n][s][t] = tempm * GeVector::axis( s ) *
02162                 (-_qe[ m ] * _eim);
02163             tempm =
02164                 GeMatrix3::IDENTITY - GeMatrix3::outerProduct( _ehat, _ehat );
02165             tempv = _eim * _eim * _qe[ n ] * _qe[ m ] * _ehat[ t ] *
02166                 GeVector::axis( s );
02167             _d2e_dxmdxn[m][n][s][t] -= tempm * tempv;
02168         }
02169     }
02170 #else
02171     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02172         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02173             _d2nA_dxmdxn[m][n][s][t] =
02174                 makeSkewRow( _dqAm_dxn[m][n][t], s ) * _nAim;
02175             _d2nB_dxmdxn[m][n][s][t] =
02176                 makeSkewRow( _dqBm_dxn[m][n][t], s ) * _nBim;
02177         }
02178     }
02179 #endif
02180 }
02181 
02182 //------------------------------------------------------------------------------
02183 
02184 void SimSimulator::BendVars::calcCosSinDeriv()
02185 {
02186     UInt32 m,s;
02187 
02188     // $ \pfrac{ \cos \theta }{\xms} =
02189     //   \pfrac{ \n^A \cdot \n^B }{\xms} =
02190     //      \pfrac{\n^A}{\xms} \cdot \n^B +
02191     //      \n^A \cdot \pfrac{\n^B}{\xms} $
02192     for( m = 0; m < 4; ++m ) {
02193         for ( s = 0; s < 3; ++s ) {
02194             _dcosth_dxm[m][s] =
02195                 _dnhatA_dxm[m][s].dot( _nhatB ) +
02196                 _nhatA.dot( _dnhatB_dxm[m][s] );
02197         }
02198     }
02199 
02200     // $ \pfrac{ \sin \theta }{\xms} =
02201     //   \pfrac{ (\n^A \cross \n^B) \cdot \e}{\xms} =
02202     //      \left(
02203     //          \pfrac{\n^A}{\xms} \cross \n^B +
02204     //          \n^A \cross \pfrac{\n^B}{\xms}
02205     //      \right) \cdot \e +
02206     //      (\n^A \cross \n^B) \cdot \pfrac{\e}{\xms} $
02207     GeVector nhatAxnhatB( _nhatA.cross( _nhatB ) );
02208     for( m = 0; m < 4; ++m ) {
02209         for ( s = 0; s < 3; ++s ) {
02210             _dsinth_dxm[m][s] =
02211                 (
02212                     _dnhatA_dxm[m][s].cross( _nhatB ) +
02213                     _nhatA.cross( _dnhatB_dxm[m][s] )
02214                 ).dot( _ehat ) + nhatAxnhatB.dot( _dehat_dxm[m][s] );
02215         }
02216     }
02217 }
02218 
02219 //------------------------------------------------------------------------------
02220 
02221 void SimSimulator::BendVars::calcD2cossinth()
02222 {
02223     UInt32 m,n,s,t;
02224 
02225     // $ \pfractwo{\cos \theta}{\xmt}{\xns} =
02226     //      \pfractwo{\n^A}{\xms}{\xnt} \cdot \n^B +
02227     //      \pfrac{\n^B}{\xnt} \cdot \pfrac{\n^A}{\xms} +
02228     //      \pfrac{\n^A}{\xnt} \cdot \pfrac{\n^B}{\xms} +
02229     //      \n^A \cdot \pfractwo{\n^B}{\xms}{\xnt} $
02230     for( m = 0; m < 4; ++m ) for( n = 0; n < 4; ++n ) {
02231         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02232             _d2costh_dxmdxn[m][n](t,s) =
02233                 _d2nA_dxmdxn[m][n][s][t].dot( _nhatB ) +
02234                 _dnhatA_dxm[m][s].dot( _dnhatB_dxm[n][t] ) +
02235                 _dnhatA_dxm[n][t].dot( _dnhatB_dxm[m][s] ) +
02236                 _d2nB_dxmdxn[m][n][s][t].dot( _nhatA );
02237         }
02238     }
02239 
02240     // $ \pfractwo{\sin \theta}{\xms}{\xnt} =
02241     //      \left(
02242     //          \pfractwo{\n^A}{\xms}{\xnt} \cross \n^B +
02243     //          \pfrac{\n^A}{\xms} \cross \pfrac{\n^B}{\xnt} +
02244     //          \pfrac{\n^A}{\xnt} \cross \pfrac{\n^B}{\xms} +
02245     //          \n^A \cross \pfractwo{\n^B}{\xms}{\xnt}
02246     //      \right) \cdot \e +
02247     //      \left(
02248     //          \pfrac{\n^A}{\xms} \cross \n^B +
02249     //          \n^A \cross \pfrac{\n^B}{\xms}
02250     //      \right) \cdot \pfrac{\e}{\xnt} +
02251     //      \left(
02252     //          \pfrac{\n^A}{\xnt} \cross \n^B +
02253     //          \n^A \cross \pfrac{\n^B}{\xnt}
02254     //      \right) \cdot \pfrac{\e}{\xms} +
02255     //      (\n^A \cross \n^B) \pfractwo{\e}{\xms}{\xnt} $
02256     for( m = 0; m < 4; ++m ) for( n = 0; n < 4; ++n ) {
02257         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02258             _d2sinth_dxmdxn[ m ][ n ]( t, s ) = (
02259                 _d2nA_dxmdxn[m][n][s][t].cross( _nhatB ) +
02260                 _dnhatA_dxm[m][s].cross( _dnhatB_dxm[n][t] ) +
02261                 _dnhatA_dxm[n][t].cross( _dnhatB_dxm[m][s] ) +
02262                 _nhatA.cross( _d2nB_dxmdxn[m][n][s][t] )
02263             ).dot( _ehat );
02264             _d2sinth_dxmdxn[ m ][ n ]( t, s ) += (
02265                 _dnhatA_dxm[m][s].cross( _nhatB ) +
02266                 _nhatA.cross( _dnhatB_dxm[m][s] )
02267             ).dot( _dehat_dxm[n][t] );
02268             _d2sinth_dxmdxn[ m ][ n ]( t, s ) += (
02269                 _dnhatA_dxm[n][t].cross( _nhatB ) +
02270                 _nhatA.cross( _dnhatB_dxm[n][t] )
02271             ).dot( _dehat_dxm[m][s] );
02272 #if DO_NORM
02273             _d2sinth_dxmdxn[ m ][ n ]( t, s ) +=
02274                 _nhatA.cross( _nhatB ).dot( _d2e_dxmdxn[m][n][s][t] );
02275 #endif
02276         }
02277     }
02278 }
02279 
02280 //------------------------------------------------------------------------------
02281 
02282 void SimSimulator::BendVars::calcCderivs()
02283 {
02284     UInt32 m,n,s,t;
02285 
02286     // $ \pfrac{C}{\xms} = \pfrac{\theta}{\xms} =
02287     //      \cos \theta \pfrac{\sin \theta}{\xms} -
02288     //      \sin \theta \pfrac{\cos \theta}{\xms} $
02289     for ( m = 0; m < 4; ++m ) {
02290         _dC_dxm[ m ] = _costh * _dsinth_dxm[ m ] - _sinth * _dcosth_dxm[ m ];
02291     }
02292     // $ \pfractwo{C}{\xms}{\xnt} = \pfractwo{\theta}{\xms}{\xnt} =
02293     //      \pfrac{\cos \theta}{\xnt}\pfrac{\sin \theta}{\xms} +
02294     //      \cos \theta \pfractwo{\sin \theta}{\xms}{\xnt} -
02295     //      \pfrac{\sin \theta}{\xnt} \pfrac{\cos \theta}{\xms} -
02296     //      \sin \theta \pfractwo{\cos \theta}{\xms}{\xnt} $
02297     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02298         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02299             _d2C_dxmdxn[m][n](t,s) =
02300                 _dcosth_dxm[n][t] * _dsinth_dxm[m][s] +
02301                 _costh * _d2sinth_dxmdxn[m][n](t,s) -
02302                 _dsinth_dxm[n][t] * _dcosth_dxm[m][s] -
02303                 _sinth * _d2costh_dxmdxn[m][n](t,s);
02304         }
02305     }
02306             
02307 }
02308 
02309 //------------------------------------------------------------------------------
02310 
02311 void SimSimulator::BendVars::debugOutput( std::ostream& os )
02312 {
02313     UInt32 m,n,s,t;
02314 
02315     os << "nhatA = " << _nhatA << "  _nAim = " << _nAim << std::endl;
02316     os << "nhatB = " << _nhatB << "  _nBim = " << _nBim << std::endl;
02317     os << "ehat = " << _ehat << "  _eim = " << _eim << std::endl;
02318 
02319     os  << "cos(theta) = " << _costh << "  sin(theta) = " << _sinth
02320         << "  C = theta = " << _C << " radians ("
02321         << _C * 180 / M_PI << " degrees)"
02322         << std::endl;
02323 
02324     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02325         for ( s = 0; s < 3; ++s ) {
02326             os << "dqAm_dxn[ " << m << " ][ " << n << " ][ "
02327                 << s << " ] = " << _dqAm_dxn[m][n][s] << std::endl;
02328             os << "dqBm_dxn[ " << m << " ][ " << n << " ][ "
02329                 << s << " ] = " << _dqBm_dxn[m][n][s] << std::endl;
02330         }
02331     }
02332 
02333     for( m = 0; m < 4; ++m ) {
02334         for( s = 0; s < 3; ++s ) {
02335             os << "dnhatA_dxm[ " << m << " ][ " << s << " ] = "
02336                 << _dnhatA_dxm[ m ][ s ] << std::endl;
02337             os << "dnhatB_dxm[ " << m << " ][ " << s << " ] = "
02338                 << _dnhatB_dxm[ m ][ s ] << std::endl;
02339             os << "dehat_dxm[ " << m << " ][ " << s << " ] = "
02340                 << _dehat_dxm[ m ][ s ] << std::endl;
02341         }
02342     }
02343 
02344     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02345         for ( s = 0; s < 3; ++s ) for ( t = 0; t < 3; ++t ) {
02346             os << "d2nA_dxmdxn[ " << m << " ][ " << n << " ][ "
02347                 << s << " ][ " << t << " ] = " << _d2nA_dxmdxn[m][n][s][t]
02348                 << std::endl;
02349             os << "d2nB_dxmdxn[ " << m << " ][ " << n << " ][ "
02350                 << s << " ][ " << t << " ] = " << _d2nB_dxmdxn[m][n][s][t]
02351                 << std::endl;
02352 #if DO_NORM
02353             os << "d2e_dxmdxn[ " << m << " ][ " << n << " ][ "
02354                 << s << " ][ " << t << " ] = " << _d2e_dxmdxn[m][n][s][t]
02355                 << std::endl;
02356 #endif
02357         }
02358     }
02359 
02360     for ( m = 0; m < 4; ++m ) {
02361         os << "dcosth_dxm[ " << m << " ] = " << _dcosth_dxm[ m ] << std::endl;
02362         os << "dsinth_dxm[ " << m << " ] = " << _dsinth_dxm[ m ] << std::endl;
02363     }
02364 
02365     for( m = 0; m < 4; ++m ) for( n = 0; n < 4; ++n ) {
02366         os << "d2costh_dxmdxn[ " << m << " ][ " << n << " ] = "
02367             << _d2costh_dxmdxn[ m ][ n ] << std::endl;
02368         os << "d2sinth_dxmdxn[ " << m << " ][ " << n << " ] = "
02369             << _d2sinth_dxmdxn[ m ][ n ] << std::endl;
02370     }
02371 
02372     for ( m = 0; m < 4; ++m ) {
02373         os << "dC_dxm[ " << m << " ] = " << _dC_dxm[ m ] << std::endl;;
02374     }
02375     os << "dC_dt = " << _dC_dt << std::endl;
02376     for ( m = 0; m < 4; ++m ) for ( n = 0; n < 4; ++n ) {
02377         os << "d2C_dxmdxn[ " << m << "," << n << " ] = "
02378             << _d2C_dxmdxn[ m ][ n ] << std::endl;
02379     }
02380 }
02381 
02382 
02383 ////////////////////////////////////////////////////////////////////////////////
02384 // CLASS SimSimulator::ModPCGSolver
02385 //
02386 
02387 //------------------------------------------------------------------------------
02388 
02389 SimSimulator::ModPCGSolver::ModPCGSolver()
02390  : _tolerance( 1e-4f )
02391 {
02392 }
02393 
02394 //------------------------------------------------------------------------------
02395 
02396 bool SimSimulator::ModPCGSolver::done() const
02397 {
02398     return _done;
02399 }
02400 
02401 //------------------------------------------------------------------------------
02402 
02403 const SimVector& SimSimulator::ModPCGSolver::result() const
02404 {
02405     return _x;
02406 }
02407 
02408 //------------------------------------------------------------------------------
02409 
02410 void SimSimulator::ModPCGSolver::setTolerance( Float tolerance )
02411 {
02412     _tolerance = tolerance;
02413 }
02414 
02415 //------------------------------------------------------------------------------
02416 
02417 Float SimSimulator::ModPCGSolver::getTolerance() const
02418 {
02419     return _tolerance;
02420 }
02421 
02422 //------------------------------------------------------------------------------
02423 
02424 void SimSimulator::ModPCGSolver::preStep()
02425 {
02426     setupPreconditioner();
02427     setupCG();
02428     _nbSteps = 0;
02429     _done = false;
02430 }
02431 
02432 //------------------------------------------------------------------------------
02433 
02434 void SimSimulator::ModPCGSolver::setupPreconditioner()
02435 {
02436     // FIXME: this assertion is failing... why?
02437     //DGFX_ASSERT( isSymmetric( _A ) );
02438 
02439     UInt32 N = _A.nbRows();
02440     if ( _P.nbRows() != _A.nbRows() ) {
02441         _P = SimMatrix( N, N );
02442         _Pinv = SimMatrix( N, N );
02443 
02444     }
02445     for ( UInt32 i = 0; i < N; ++i ) {
02446         const GeMatrix3& a = _A( i, i );
02447         GeMatrix3& p = _P( i, i );
02448         GeMatrix3& pinv = _Pinv( i, i );
02449         p = GeMatrix3::ZERO;
02450         pinv = GeMatrix3::ZERO;
02451         for ( UInt32 j = 0; j < 3; ++j ) {
02452             DGFX_ASSERT( !BaMath::isEqual( a( j, j ), 0, 10e-12f ) );
02453             // This is the inverse of the [BarWit98]'s recommendation...
02454             // but makes things work much better.
02455             p( j, j ) = a( j, j );
02456             pinv( j, j ) = 1 / a( j, j );
02457         }
02458     }
02459 }
02460 
02461 //------------------------------------------------------------------------------
02462 
02463 void SimSimulator::ModPCGSolver::setupCG()
02464 {
02465     _x = _z;
02466     const SimVector bf( filter( _b ) );
02467     _delta0 = ( _P * bf ).dot( bf );
02468     _r = filter( _b - _A * _x );
02469     _c = filter( _Pinv * _r );
02470     _deltaNew = _r.dot( _c );
02471 }
02472     
02473 //------------------------------------------------------------------------------
02474 
02475 SimVector SimSimulator::ModPCGSolver::filter( const SimVector& a ) const
02476 {
02477     DGFX_ASSERT( _S.size() == a.size() );
02478     SimVector result( a.size() );
02479     std::vector<GeMatrix3>::const_iterator Si = _S.begin();
02480     SimVector::const_iterator ai = a.begin();
02481     SimVector::iterator ri = result.begin();
02482     for( ; Si != _S.end(); ++Si, ++ai, ++ri ) {
02483         *ri = *Si * *ai;
02484     }
02485     return result;
02486 }
02487 
02488 //------------------------------------------------------------------------------
02489 
02490 void SimSimulator::ModPCGSolver::filterInPlace( SimVector& a ) const
02491 {
02492     DGFX_ASSERT( _S.size() == a.size() );
02493     std::vector<GeMatrix3>::const_iterator Si = _S.begin();
02494     SimVector::iterator ai = a.begin();
02495     for( ; Si != _S.end(); ++Si, ++ai ) {
02496         *ai = *Si * *ai;
02497     }
02498 }
02499 
02500 //------------------------------------------------------------------------------
02501 
02502 void SimSimulator::ModPCGSolver::step()
02503 {
02504     if ( _deltaNew < _tolerance * _tolerance * _delta0 ) {
02505         _done = true;
02506         return;
02507     }
02508 
02509     SimMatrix::multiply( _q, _A, _c );
02510     filterInPlace( _q );
02511     Float alpha = _deltaNew / _c.dot( _q );
02512     _x.plusEqualsScaled( alpha, _c );
02513     _r.plusEqualsScaled( -alpha, _q );
02514 
02515     SimMatrix::multiply( _s, _Pinv, _r );
02516     Float _deltaOld = _deltaNew;
02517     _deltaNew = _r.dot( _s );
02518     _c *= _deltaNew / _deltaOld;
02519     _c += _s;
02520     filterInPlace( _c );
02521     ++_nbSteps;
02522 }
02523 
02524 FREECLOTH_NAMESPACE_END

Generated on Fri May 2 16:51:14 2003 for Freecloth by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002