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

Generated on Wed Apr 23 15:58:52 2003 for Freecloth by doxygen1.3-rc3