Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ContactSolver.cpp

Go to the documentation of this file.
00001 #include "ContactSolver.h"
00002 #include "SystemSolver.h"
00003 
00004 ContactSolver::ContactSolver(GlobalContactInfoVector* iniContacts){
00005    contacts=iniContacts;
00006    nContacts=0;
00007    nContactsMax=0;
00008    contactMatrix=NULL;
00009    contactMatrixTemp=NULL;
00010    contactVector=NULL;
00011    contactVectorTemp=NULL;
00012    contactForces=NULL;
00013    contactDForces=NULL;
00014    contactVelocities=NULL;
00015    contactSets=NULL;
00016    contactIndexC=NULL;
00017    contactIndexTemp=NULL;
00018    zeros=NULL;
00019    tempVector1=NULL;
00020    tempVector2=NULL;
00021    tempMatrix=NULL;
00022    //TODO: initialize nContactsMax and the contact matrix, vector
00023 
00024 }
00025 
00026 ContactSolver::~ContactSolver(){
00027    if(contactMatrix!=NULL){
00028       for (int i=0; i < nContactsMax; i++) {
00029          delete[] contactMatrix[i];
00030          delete[] contactMatrixTemp[i];
00031          delete[] tempMatrix[i];
00032       }
00033       delete[] contactMatrix;
00034       delete[] contactMatrixTemp;
00035       delete[] contactVector;
00036       delete[] contactVectorTemp;
00037       delete[] contactForces;
00038       delete[] contactDForces;
00039       delete[] contactVelocities;
00040       delete[] contactSets;
00041       delete[] contactIndexC;
00042       delete[] contactIndexTemp;
00043       delete[] zeros;
00044       delete[] tempVector1;
00045       delete[] tempVector2;
00046    }
00047 
00048 }
00049 
00050 void ContactSolver::init(){
00051    nContacts=contacts->size();
00052 
00053    /* Realloc memory for the contact matrix and vectors, if needed. */
00054    if(nContacts > nContactsMax){
00055       if(contactMatrix != NULL){
00056          {for(int i = 0; i < nContactsMax; i++){
00057             delete[] contactMatrix[i];
00058             delete[] contactMatrixTemp[i];
00059             delete[] tempMatrix[i];
00060          }}
00061          delete[] contactMatrix;
00062          delete[] contactMatrixTemp;
00063          delete[] contactVector;
00064          delete[] contactVectorTemp;
00065          delete[] contactForces;
00066          delete[] contactDForces;
00067          delete[] contactVelocities;
00068          delete[] contactSets;
00069          delete[] contactIndexC;
00070          delete[] contactIndexTemp;
00071          delete[] zeros;
00072          delete[] tempVector1;
00073          delete[] tempVector2;
00074       }
00075       contactMatrix=new real*[nContacts];
00076       contactMatrixTemp=new real*[nContacts];
00077       tempMatrix=new real*[nContacts];
00078       {for(int i = 0; i < nContacts; i++){
00079          contactMatrix[i]=new real[nContacts];
00080          contactMatrixTemp[i]=new real[nContacts];
00081          tempMatrix[i]=new real[nContacts];
00082       }}
00083       contactVector=new real[nContacts];
00084       contactVectorTemp=new real[nContacts];
00085       contactForces=new real[nContacts];
00086       contactDForces=new real[nContacts];
00087       contactVelocities=new real[nContacts];
00088       contactSets=new ContactSet[nContacts];
00089       contactIndexC=new int[nContacts];
00090       contactIndexTemp=new int[nContacts];
00091       zeros=new int[nContacts];
00092       tempVector1=new real[nContacts];
00093       tempVector2=new real[nContacts];
00094       nContactsMax=nContacts;
00095    }
00096 
00097    /* Reset to zero the contact matrix and vectors. */
00098    for (int i = 0; i < nContacts; i++) {
00099       for(int j = 0; j < nContacts; j++) {
00100          contactMatrix[i][j]=0.0f;
00101         }
00102       contactVector[i]=0.0f;
00103       contactForces[i]=0.0f;
00104    }
00105 }
00106 
00107 real ContactSolver::maxStep(int d, int *sIndex) {
00108    static const real zeroMinus = -1e-8;
00109     //the maxstep part
00110     //s=infinity
00111     real s = 1e10;
00112     *sIndex = -1;
00113     //if delta a_d>0
00114     if(contactVectorTemp[d] > 0) {
00115         *sIndex = d;
00116         //s=-a_d/delta a_d
00117         s = -contactVelocities[d]/contactVectorTemp[d];
00118     }
00119     for(int i = 0; i < d; i++){
00120         if(contactSets[i] == contactSetC){
00121             //i (- C
00122             //if delta f_i<0
00123             if(contactDForces[i]<zeroMinus){
00124                 //assert(contactForces[i] > 0);
00125                 //s'=-f_i/delta f_i
00126                 real sp = -contactForces[i]/contactDForces[i];
00127                 if (sp < s) {
00128                     s = sp;
00129                     *sIndex = i;
00130                 }
00131             }
00132         } else {
00133             //i (- NC
00134             //if delta a_i<0
00135             if(contactVectorTemp[i]<zeroMinus){
00136                 //assert(contactVelocities[i] > 0);
00137                 //s'=-a_i/delta a_i
00138                 real sp = -contactVelocities[i]/contactVectorTemp[i];
00139                 if (sp < s) {
00140                     s = sp;
00141                     *sIndex = i;
00142                 }
00143             }
00144         }
00145     }
00146     //end of maxstep part
00147     assert(s<1e5 && *sIndex > -1);
00148     return s;
00149 }
00150 
00151 bool ContactSolver::driveToZero(int d) {
00152     if (contactVelocities[d] >= 0) {
00153         contactSets[d] = contactSetNC;
00154         return true;
00155     }
00156 
00157     //contactVelocities[d] < 0)
00158     int cycleCount = 0;
00159     int sIndex;
00160     do {
00161         ++cycleCount;
00162         if (cycleCount > nContacts * 10) {
00163             return false;
00164         }
00165 
00166         //the fdirection part
00167         //initialize
00168         //delta f=0
00169         {for (int i = 0; i < d; i++) {
00170             contactDForces[i] = 0;
00171         }}
00172         //delta f_d=1
00173         contactDForces[d] = 1;
00174         
00175         //index the contacts in the C set
00176         int nC = 0;
00177         {for (int i=0; i < d; i++) {
00178             if (contactSets[i] == contactSetC) {
00179                 //assert(contactVelocities[i] <= 0);
00180                 //assert(contactForces[i] >= 0);
00181                 contactIndexC[nC] = i;
00182                 nC++;               
00183             } else {
00184                 //assert(contactVelocities[i] >= 0);
00185                 //assert(contactForces[i] == 0);
00186             }
00187         }}
00188     
00189         if(nC>0){ 
00190             //fill the A11 matrix, the v1 vector
00191             {for (int i = 0; i < nC; i++){
00192                 for (int j = 0; j < (int)nC; j++) {
00193                     contactMatrixTemp[i][j] = contactMatrix[contactIndexC[i]][contactIndexC[j]];
00194                 }
00195                 //contactVectorTemp is now -v1
00196                 contactVectorTemp[i] = -contactMatrix[contactIndexC[i]][d];
00197             }}
00198             //LOG(("\nsystem matrix\n"));
00199             //logMatrix(contactMatrixTemp, nC);
00200             //solve the system
00201             
00202                   //SystemSolver::luDecompose(contactMatrixTemp, nC, contactIndexTemp, tempVector1);
00203             //SystemSolver::luSubstitute(contactMatrixTemp, nC, contactIndexTemp, contactVectorTemp);
00204 
00205                   SystemSolver::svDecompose(contactMatrixTemp, nC, tempVector1, tempMatrix, tempVector2);
00206                   SystemSolver::svSubstitute(contactMatrixTemp, nC, tempVector1, tempMatrix, 
00207                      contactVectorTemp, tempVector2);
00208 
00209 
00210             //contactVectorTemp is now x, if using lu; tempVector1 is now x, if using sv
00211             //transfer x into delta f
00212             for (int i=0; i < nC; i++) {
00213                      //contactDForces[contactIndexC[i]]=contactVectorTemp[i];
00214                      contactDForces[contactIndexC[i]]=tempVector1[i];
00215             }
00216         }
00217         //end of fdirection part
00218         //contactVectorTemp is now delta a
00219         //delta a= A delta f
00220         {for (int i=0; i < nContacts; i++){
00221             contactVectorTemp[i] = 0;
00222             for (int j = 0; j <= d; j++) {
00223                 contactVectorTemp[i] += contactMatrix[i][j] * contactDForces[j];
00224             }
00225         }}
00226         
00227         real s = maxStep(d, &sIndex);
00228         //assert(s > 0);
00229         
00230         //end of maxstep part
00231         assert(s < 1e5 && sIndex > -1);
00232         if (s == 0) {
00233             zeros[sIndex]++;
00234         } else{
00235             zeros[sIndex] = 0;
00236         }
00237         if (zeros[sIndex] > 1) {
00238             contactSets[sIndex]   = contactSetI;
00239             contactForces[sIndex] = 0;
00240         } else {
00241             {for (int i = 0; i <= d; i++) {
00242                 //f=f+s delta f
00243                 contactForces[i] += contactDForces[i] * s;
00244             }}
00245             {for(int i = 0; i < nContacts; i++) {
00246                 //a=a+s delta a
00247                 contactVelocities[i] += contactVectorTemp[i] * s;
00248             }}
00249 
00250             if (sIndex == d) {
00251                 contactSets[sIndex] = contactSetC;
00252             } else if (contactSets[sIndex] == contactSetC) {
00253                 contactSets[sIndex] = contactSetNC;
00254             } else {
00255                 contactSets[sIndex] = contactSetC;
00256             }
00257         }
00258     } while (sIndex != d);
00259     return true;
00260 }
00261 
00262 void ContactSolver::initForcesVelocities() {
00263     //initialize
00264     for (int i = 0; i < nContacts; i++) {
00265         //f=0
00266         contactForces[i] = 0;
00267         //a=b
00268         contactVelocities[i] = contactVector[i];
00269         zeros[i] = 0;
00270     } 
00271 }
00272 
00273 void ContactSolver::computeContacts(){
00274    /*
00275    f        -> contactForces
00276    a        -> contactVelocities
00277    b        -> contactVector
00278    A        -> contactMatrix
00279    delta a  -> contactVectorTemp
00280    A11      -> contactMatrixTemp
00281    v1       -> contactVectorTemp
00282    delta f  -> contactDForces
00283    */
00284 
00285     initForcesVelocities();
00286    
00287     bool divergence = false;
00288     for (int d = 0; d < nContacts && !divergence; ++d) {
00289         divergence = !driveToZero(d);
00290     }
00291     
00292       
00293     if(divergence){
00294         computeContactsPreda();
00295     }
00296       
00297 }
00298 
00308 void ContactSolver::computeContactsPreda(){
00309    initForcesVelocities();
00310    for(unsigned repeat = 0; repeat < 10; repeat++){   
00311       for (int i = 0; i < nContacts; ++i) {
00312          assert(contactMatrix[i][i] > 0);
00313             
00314          real velocity = contactVector[i];
00315          real *line = contactMatrix[i];
00316          for (int j = 0; j < nContacts; ++j) {
00317                if (j != i) {
00318                      velocity += line[j] * contactForces[j];
00319                }
00320          }
00321          if (velocity < 0) {
00322                contactForces[i] = -velocity / contactMatrix[i][i];
00323                //now velocity becomes 0;
00324          } else {
00325                contactForces[i] = 0;
00326          }
00327       }
00328    }
00329 
00330     /* the code below is exactly equivalent with the one above,
00331        but the Gauss-Seidel parallel is less apparent.
00332 
00333     real deltaForce = - contactVelocities[i] / contactMatrix[i][i];
00334     if (deltaForce < -contactForces[i]) {
00335         deltaForce = -contactForces[i];
00336     }
00337     for (int j = 0; j < nContacts; ++j) {
00338         contactVelocities[j] += contactMatrix[j][i] * deltaForce;
00339     }
00340     contactForces[i] += deltaForce;
00341     */
00342 }
00343 
00344 void ContactSolver::uploadForces(){
00345    unsigned int k=0;
00346    for(GlobalContactInfoVector::iterator it = contacts->begin(), end = contacts->end(); 
00347          it != end; ++it){    
00348       //add penalty elastic force if there are penetrations, proportional to the penetration surface
00349       contactForces[k]+=ThyrixParameters::kContact * it->penetration;
00350       
00351       //put force in contacts
00352       it->force = contactForces[k];
00353       it->contact1->force =contactForces[k];
00354       if(it->contact2 != NULL) {
00355          it->contact2->force=contactForces[k];
00356         }
00357       k++;
00358    }
00359 
00360 }

Thyrix homepageUsers' guide

(C) Arxia 2004-2005