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 homepage Users' guide
(C) Arxia 2004-2005