00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sofa/helper/LCPcalc.h>
00028 #include <vector>
00029 #include <algorithm>
00030 #include <functional>
00031 #include <iostream>
00032 #include <fstream>
00033 #include <cstring>
00034
00035 namespace sofa
00036 {
00037
00038 namespace helper
00039 {
00040
00041 using namespace std;
00042
00043
00044 LCP::LCP(unsigned int mxC) : maxConst(mxC), tol(0.00001), numItMax(1000), useInitialF(true), mu(0.0), dim(0)
00045 {
00046 W = new double*[maxConst];
00047 for (int i = 0; i < maxConst; i++)
00048 {
00049 W[i] = new double[maxConst];
00050 memset(W[i], 0, maxConst * sizeof(double));
00051 }
00052 dfree = new double[maxConst];
00053 f = new double[2 * maxConst + 1];
00054
00055 memset(dfree, 0, maxConst * sizeof(double));
00056 memset(f, 0, (2 * maxConst + 1) * sizeof(double));
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 LCP::~LCP()
00100 {
00101 delete [] dfree;
00102 for (int i = 0; i < maxConst; i++)
00103 {
00104 delete [] W[i];
00105 }
00106 delete [] W;
00107 }
00108
00109
00110 void LCP::reset(void)
00111 {
00112
00113 for (int i = 0; i < maxConst; i++)
00114 {
00115 memset(W[i], 0, maxConst * sizeof(double));
00116 }
00117
00118 memset(dfree, 0, maxConst * sizeof(double));
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 int resoudreLCP(int dim, double * q, double ** M, double * res) {
00130
00131
00132 int compteur;
00133 int compteur2;
00134 double ** mat;
00135 int * base;
00136 int ligPiv;
00137 int colPiv;
00138 double pivot;
00139 double min;
00140 double coeff;
00141 int boucles;
00142 int result=1;
00143
00144
00145 mat = (double **)malloc(dim*sizeof(double *));
00146 for(compteur=0;compteur<dim;compteur++) {
00147 mat[compteur]=(double *)malloc((2*dim+1)*sizeof(double));
00148 }
00149
00150 base = (int *)malloc(dim*sizeof(int));
00151
00152
00153 for(compteur=0;compteur<dim;compteur++) {
00154
00155 for(compteur2=0;compteur2<dim;compteur2++) {
00156 if(compteur2==compteur) {
00157 mat[compteur][compteur2] = 1;
00158 }
00159 else {
00160 mat[compteur][compteur2] = 0;
00161 }
00162 }
00163
00164 for(;compteur2<2*dim;compteur2++) {
00165 mat[compteur][compteur2] = -(M[compteur][compteur2-dim]);
00166 }
00167
00168 mat[compteur][compteur2] = q[compteur];
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 for(compteur=0;compteur<dim;compteur++) {
00182 base[compteur]=compteur;
00183 }
00184
00185
00186 boucles=0;
00187
00188
00189 ligPiv=-1;
00190 min = -EPSILON_LCP;
00191 for(compteur=0;compteur<dim;compteur++) {
00192 if (mat[compteur][2*dim]<min) {
00193 ligPiv=compteur;
00194 min=mat[compteur][2*dim];
00195 }
00196 }
00197
00198
00199 while ((ligPiv>=0) && (boucles<MAX_BOU)) {
00200
00201 boucles++;
00202
00203 if (base[ligPiv]<dim) {
00204
00205 colPiv=dim+base[ligPiv];
00206 }
00207 else {
00208
00209 colPiv=base[ligPiv]-dim;
00210 }
00211
00212
00213 pivot=mat[ligPiv][colPiv];
00214
00215
00216
00217
00218 if (fabs(pivot)<EPSILON_LCP) {
00219 afficheLCP(q,M,dim);
00220 printf("*** Pas de solution *** \n");
00221 boucles=MAX_BOU;
00222 result=0;
00223 return result;
00224 } else {
00225
00226 for(compteur=0;compteur<2*dim+1;compteur++) {
00227 mat[ligPiv][compteur]/=pivot;
00228 }
00229
00230
00231 for(compteur=0;compteur<dim;compteur++) {
00232 if (compteur!=ligPiv) {
00233 coeff=mat[compteur][colPiv];
00234 for(compteur2=0;compteur2<2*dim+1;compteur2++) {
00235 mat[compteur][compteur2]-=coeff*mat[ligPiv][compteur2];
00236 }
00237 }
00238 }
00239
00240
00241 base[ligPiv]=colPiv;
00242
00243
00244 ligPiv=-1;
00245 min = -EPSILON_LCP;
00246 for(compteur=0;compteur<dim;compteur++) {
00247 if (mat[compteur][2*dim]<min) {
00248 ligPiv=compteur;
00249 min=mat[compteur][2*dim];
00250 }
00251 }
00252
00253 }
00254 }
00255
00256
00257
00258
00259
00260 for(compteur=0;compteur<2*dim;compteur++) {
00261 res[compteur]=0;
00262 }
00263
00264 if (boucles<MAX_BOU) {
00265 for(compteur=0;compteur<dim;compteur++) {
00266 res[base[compteur]]=mat[compteur][2*dim];
00267 }
00268 }
00269
00270
00271 for(compteur=0;compteur<dim;compteur++) {
00272 free(mat[compteur]);
00273 }
00274 free(mat);
00275
00276 free(base);
00277
00278 return result;
00279 }
00280
00281
00282
00283
00284 void afficheSyst(double *q,double **M, int *base, double **mat, int dim)
00285 {
00286 int compteur, compteur2;
00287
00288
00289 printf("M = [");
00290 for(compteur=0;compteur<dim;compteur++) {
00291 for(compteur2=0;compteur2<dim;compteur2++) {
00292 printf("\t%.4f",M[compteur][compteur2]);
00293 }
00294 printf("\n");
00295 }
00296 printf(" ]\n\n");
00297
00298
00299 printf("q = [");
00300 for(compteur=0;compteur<dim;compteur++) {
00301 printf("\t%.4f\n",q[compteur]);
00302 }
00303 printf(" ]\n\n");
00304
00305
00306 printf("B = [");
00307 for(compteur=0;compteur<dim;compteur++) {
00308 printf("\t%d",base[compteur]);
00309 }
00310 printf("\t]\n\n");
00311
00312
00313 printf("mat = [");
00314 for(compteur=0;compteur<dim;compteur++) {
00315 for(compteur2=0;compteur2<2*dim+1;compteur2++) {
00316 printf("\t%.4f",mat[compteur][compteur2]);
00317 }
00318 printf("\n");
00319 }
00320 printf(" ]\n\n");
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00390
00391
00392
00393 int lcp_lexicolemke(int dim, double * q, double ** M, double * res) {
00394
00395 int i,drive,block,Ifound;
00396 int ic,jc;
00397 int dim2,ITER;
00398 int nobasis;
00399 int itermax,ispeak;
00400
00401 double qs,z0,zb,dblock;
00402 double pivot, tovip;
00403 double tmp;
00404 int *basis;
00405 static double** A;
00406
00407
00408 dim2 = 2*(dim+1);
00409
00410
00411
00412 itermax = dim2;
00413 ispeak = 0;
00414
00415
00416
00417
00418 basis = (int *)malloc( dim*sizeof(int) );
00419
00420
00421 A = (double **)malloc( dim*sizeof(double*) );
00422 for( ic = 0 ; ic < dim; ++ic )
00423 A[ic] = (double *)malloc( dim2*sizeof(double) );
00424
00425 for( ic = 0 ; ic < dim; ++ic )
00426 for( jc = 0 ; jc < dim2; ++jc )
00427 A[ic][jc] = 0.0;
00428
00429
00430
00431
00432
00433 for( ic = 0 ; ic < dim; ++ic )
00434 for( jc = 0 ; jc < dim; ++jc )
00435 A[ic][jc+dim+2] = -M[ic][jc];
00436
00437 for( ic = 0 ; ic < dim; ++ic ) A[ic][0] = q[ic];
00438
00439 for( ic = 0 ; ic < dim; ++ic ) A[ic][ic+1 ] = 1.0;
00440 for( ic = 0 ; ic < dim; ++ic ) A[ic][dim+1] = -1.0;
00441
00442
00443
00444
00445
00446
00447
00448 qs = q[0];
00449
00450 for( ic = 1 ; ic < dim ; ++ic ){
00451 if( q[ic] < qs ) qs = q[ic];
00452 }
00453
00454 Ifound = 0;
00455
00456 ITER=0;
00457 if( qs >= 0 ){
00458
00459
00460
00461
00462
00463 for( ic = 0 ; ic < dim; ++ic ){
00464 res[ic] = 0.0;
00465
00466 z0 = 0.0;
00467 }
00468
00469 Ifound=1;
00470
00471 }
00472 else{
00473
00474 for( ic = 0 ; ic < dim ; ++ic ) basis[ic]=ic+1;
00475
00476 drive = dim+1;
00477 block = 0;
00478 z0 = A[block][0];
00479
00480
00481
00482
00483
00484 for( ic = 1 ; ic < dim ; ++ic ){
00485 zb = A[ic][0];
00486 if( zb < z0 ){
00487 z0 = zb;
00488 block = ic;
00489 }
00490 else if( zb == z0 ){
00491 for( jc = 0 ; jc < dim ; ++jc ){
00492 dblock = A[block][1+jc] - A[ic][1+jc];
00493 if( dblock < 0 ){
00494 break;
00495 }
00496 else if( dblock > 0 ){
00497 block = ic;
00498 break;
00499 }
00500 }
00501 }
00502 }
00503
00504
00505
00506 pivot = A[block][drive];
00507 tovip = 1.0/pivot;
00508
00509
00510
00511 A[block][drive] = 1;
00512 for( ic = 0 ; ic < drive ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00513 for( ic = drive+1 ; ic < dim2 ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00514
00515
00516
00517 for( ic = 0 ; ic < block ; ++ic ){
00518 tmp = A[ic][drive];
00519 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00520 }
00521 for( ic = block+1 ; ic < dim ; ++ic ){
00522 tmp = A[ic][drive];
00523 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00524 }
00525
00526 nobasis = basis[block];
00527 basis[block] = drive;
00528
00529 while( ITER < itermax && !Ifound ){
00530
00531 ++ITER;
00532
00533 if( nobasis < dim + 1 ) drive = nobasis + (dim+1);
00534 else if( nobasis > dim + 1 ) drive = nobasis - (dim+1);
00535
00536
00537
00538 pivot = 1e20;
00539 block = -1;
00540
00541 for( ic = 0 ; ic < dim ; ++ic ){
00542 zb = A[ic][drive];
00543 if( zb > 0.0 ){
00544 z0 = A[ic][0]/zb;
00545 if( z0 > pivot ) continue;
00546 if( z0 < pivot ){
00547 pivot = z0;
00548 block = ic;
00549 }
00550 else{
00551 for( jc = 1 ; jc < dim+1 ; ++jc ){
00552 dblock = A[block][jc]/pivot - A[ic][jc]/zb;
00553 if( dblock < 0 ) break;
00554 else if( dblock > 0 ){
00555 block = ic;
00556 break;
00557 }
00558 }
00559 }
00560 }
00561 }
00562 if( block == -1 ) break;
00563
00564 if( basis[block] == dim+1 ) Ifound = 1;
00565
00566
00567
00568 pivot = A[block][drive];
00569 tovip = 1.0/pivot;
00570 A[block][drive] = 1;
00571
00572 for( ic = 0 ; ic < drive ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00573 for( ic = drive+1 ; ic < dim2 ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00574
00575
00576
00577 for( ic = 0 ; ic < block ; ++ic ){
00578 tmp = A[ic][drive];
00579 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00580 }
00581 for( ic = block+1 ; ic < dim ; ++ic ){
00582 tmp = A[ic][drive];
00583 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00584 }
00585
00586 nobasis = basis[block];
00587 basis[block] = drive;
00588
00589 }
00590
00591 for( ic = 0 ; ic < dim; ++ic ){
00592 drive = basis[ic];
00593 if( drive < dim + 1 ){
00594 res[drive-1] = 0.0;
00595
00596 }
00597 else if( drive > dim + 1 ){
00598 res[drive-dim-2] = A[ic][0];
00599
00600 }
00601 }
00602
00603 }
00604
00605
00606
00607
00608
00609
00610 free(basis);
00611
00612
00613 for( i = 0 ; i < dim ; ++i ) free(A[i]);
00614 free(A);
00615
00616
00617
00618
00619 for( i = 0 ; i < dim ; ++i )
00620 res[i+dim] = res[i];
00621
00622
00623 if (Ifound) return 1;
00624
00625 printf("\n Problem with this LCP :\n");
00626 afficheLCP(q,M,dim);
00627 return 0;
00628
00629 }
00630
00631
00632 int lcp_lexicolemke(int dim, double * q, double ** M, double **A, double * res) {
00633
00634 int i,drive,block,Ifound;
00635 int ic,jc;
00636 int dim2,ITER;
00637 int nobasis;
00638 int itermax,ispeak;
00639
00640 double qs,z0,zb,dblock;
00641 double pivot, tovip;
00642 double tmp;
00643 int *basis;
00644
00645 dim2 = 2*(dim+1);
00646
00647
00648
00649 itermax = dim2;
00650 ispeak = 0;
00651
00652
00653
00654 basis = (int *)malloc( dim*sizeof(int) );
00655
00656 for( ic = 0 ; ic < dim; ++ic )
00657 for( jc = 0 ; jc < dim2; ++jc )
00658 A[ic][jc] = 0.0;
00659
00660
00661
00662
00663
00664 for( ic = 0 ; ic < dim; ++ic )
00665 for( jc = 0 ; jc < dim; ++jc )
00666 A[ic][jc+dim+2] = -M[ic][jc];
00667
00668 for( ic = 0 ; ic < dim; ++ic ) A[ic][0] = q[ic];
00669
00670 for( ic = 0 ; ic < dim; ++ic ) A[ic][ic+1 ] = 1.0;
00671 for( ic = 0 ; ic < dim; ++ic ) A[ic][dim+1] = -1.0;
00672
00673
00674
00675
00676
00677
00678
00679 qs = q[0];
00680
00681 for( ic = 1 ; ic < dim ; ++ic ){
00682 if( q[ic] < qs ) qs = q[ic];
00683 }
00684
00685 Ifound = 0;
00686
00687 ITER=0;
00688 if( qs >= 0 ){
00689
00690
00691
00692
00693
00694 for( ic = 0 ; ic < dim; ++ic ){
00695 res[ic] = 0.0;
00696
00697 z0 = 0.0;
00698 }
00699
00700 Ifound=1;
00701
00702 }
00703 else{
00704
00705 for( ic = 0 ; ic < dim ; ++ic ) basis[ic]=ic+1;
00706
00707 drive = dim+1;
00708 block = 0;
00709 z0 = A[block][0];
00710
00711
00712
00713
00714
00715 for( ic = 1 ; ic < dim ; ++ic ){
00716 zb = A[ic][0];
00717 if( zb < z0 ){
00718 z0 = zb;
00719 block = ic;
00720 }
00721 else if( zb == z0 ){
00722 for( jc = 0 ; jc < dim ; ++jc ){
00723 dblock = A[block][1+jc] - A[ic][1+jc];
00724 if( dblock < 0 ){
00725 break;
00726 }
00727 else if( dblock > 0 ){
00728 block = ic;
00729 break;
00730 }
00731 }
00732 }
00733 }
00734
00735
00736
00737 pivot = A[block][drive];
00738 tovip = 1.0/pivot;
00739
00740
00741
00742 A[block][drive] = 1;
00743 for( ic = 0 ; ic < drive ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00744 for( ic = drive+1 ; ic < dim2 ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00745
00746
00747
00748 for( ic = 0 ; ic < block ; ++ic ){
00749 tmp = A[ic][drive];
00750 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00751 }
00752 for( ic = block+1 ; ic < dim ; ++ic ){
00753 tmp = A[ic][drive];
00754 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00755 }
00756
00757 nobasis = basis[block];
00758 basis[block] = drive;
00759
00760 while( ITER < itermax && !Ifound ){
00761
00762 ++ITER;
00763
00764 if( nobasis < dim + 1 ) drive = nobasis + (dim+1);
00765 else if( nobasis > dim + 1 ) drive = nobasis - (dim+1);
00766
00767
00768
00769 pivot = 1e20;
00770 block = -1;
00771
00772 for( ic = 0 ; ic < dim ; ++ic ){
00773 zb = A[ic][drive];
00774 if( zb > 0.0 ){
00775 z0 = A[ic][0]/zb;
00776 if( z0 > pivot ) continue;
00777 if( z0 < pivot ){
00778 pivot = z0;
00779 block = ic;
00780 }
00781 else{
00782 for( jc = 1 ; jc < dim+1 ; ++jc ){
00783 dblock = A[block][jc]/pivot - A[ic][jc]/zb;
00784 if( dblock < 0 ) break;
00785 else if( dblock > 0 ){
00786 block = ic;
00787 break;
00788 }
00789 }
00790 }
00791 }
00792 }
00793 if( block == -1 ) break;
00794
00795 if( basis[block] == dim+1 ) Ifound = 1;
00796
00797
00798
00799 pivot = A[block][drive];
00800 tovip = 1.0/pivot;
00801 A[block][drive] = 1;
00802
00803 for( ic = 0 ; ic < drive ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00804 for( ic = drive+1 ; ic < dim2 ; ++ic ) A[block][ic] = A[block][ic]*tovip;
00805
00806
00807
00808 for( ic = 0 ; ic < block ; ++ic ){
00809 tmp = A[ic][drive];
00810 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00811 }
00812 for( ic = block+1 ; ic < dim ; ++ic ){
00813 tmp = A[ic][drive];
00814 for( jc = 0 ; jc < dim2 ; ++jc ) A[ic][jc] -= tmp*A[block][jc];
00815 }
00816
00817 nobasis = basis[block];
00818 basis[block] = drive;
00819
00820 }
00821
00822 for( ic = 0 ; ic < dim; ++ic ){
00823 drive = basis[ic];
00824 if( drive < dim + 1 ){
00825 res[drive-1] = 0.0;
00826
00827 }
00828 else if( drive > dim + 1 ){
00829 res[drive-dim-2] = A[ic][0];
00830
00831 }
00832 }
00833
00834 }
00835
00836
00837
00838
00839
00840
00841 free(basis);
00842
00843
00844
00845
00846
00847
00848
00849
00850 for( i = 0 ; i < dim ; ++i )
00851 res[i+dim] = res[i];
00852
00853
00854 if (Ifound) return 1;
00855
00856 printf("\n Problem with this LCP :\n");
00857
00858 return 0;
00859
00860 }
00861
00862 void afficheLCP(double *q, double **M, int dim)
00863 {
00864 int compteur, compteur2;
00865
00866 printf("M = [");
00867 for(compteur=0;compteur<dim;compteur++) {
00868 for(compteur2=0;compteur2<dim;compteur2++) {
00869 printf("\t%.4f",M[compteur][compteur2]);
00870 }
00871 printf("\n");
00872 }
00873 printf(" ];\n\n");
00874
00875
00876 printf("q = [");
00877 for(compteur=0;compteur<dim;compteur++) {
00878 printf("\t%.4f\n",q[compteur]);
00879 }
00880 printf(" ]\n\n");
00881 }
00882
00883
00884 void afficheLCP(double *q, double **M, double *f, int dim)
00885 {
00886 int compteur, compteur2;
00887
00888 printf("\n M = [");
00889 for(compteur=0;compteur<dim;compteur++) {
00890 for(compteur2=0;compteur2<dim;compteur2++) {
00891 printf("\t%.5f",M[compteur][compteur2]);
00892 }
00893 printf("\n");
00894 }
00895 printf(" ];\n\n");
00896
00897
00898 printf("q = [");
00899 for(compteur=0;compteur<dim;compteur++) {
00900 printf("\t%.5f\n",q[compteur]);
00901 }
00902 printf(" ];\n\n");
00903
00904
00905 printf("f = [");
00906 for(compteur=0;compteur<dim;compteur++) {
00907 printf("\t%.5f\n",f[compteur]);
00908 }
00909 printf(" ];\n\n");
00910
00911 }
00912
00913
00914
00915
00916 void LocalBlock33::compute(double &w11, double &w12, double &w13, double &w22, double &w23, double &w33)
00917 {
00918 w[0]=w11; w[1]=w12; w[2] = w13; w[3]=w22; w[4]=w23; w[5]=w33;
00919 det = w11*w22*w33-w11*w23*w23-w12*w12*w33+2*w12*w13*w23-w13*w13*w22;
00920 wInv[0] = (w22*w33-w23*w23)/det;
00921 wInv[1] = -(w12*w33-w13*w23)/det;
00922 wInv[2] = (w12*w23-w13*w22)/det;
00923 wInv[3] = (w11*w33-w13*w13)/det;
00924 wInv[4] = -(w11*w23-w12*w13)/det;
00925 wInv[5] = (w11*w22-w12*w12)/det;
00926 computed=true;
00927 }
00928
00929 void LocalBlock33::stickState(double &dn, double &dt, double &ds, double &fn, double &ft, double &fs)
00930 {
00931 fn = -wInv[0]*dn - wInv[1]*dt - wInv[2]*ds;
00932 ft = -wInv[1]*dn - wInv[3]*dt - wInv[4]*ds;
00933 fs = -wInv[2]*dn - wInv[4]*dt - wInv[5]*ds;
00934 }
00935
00936
00937
00938
00939 void LocalBlock33::slipState(double &mu, double &dn, double &dt, double &ds, double &fn, double &ft, double &fs)
00940 {
00941 double d[3];
00942 double normFt;
00943
00944 for (int iteration=0; iteration<10000; iteration++)
00945 {
00946
00947 f_1[0]=fn; f_1[1]=ft; f_1[2]=fs;
00948
00949
00950 d[0] = w[0]*fn + w[1]*ft + w[2]*fs + dn;
00951
00952 fn -= d[0]/w[0];
00953
00954
00955 d[1] = w[1]*fn + w[3]*ft + w[4]*fs + dt;
00956 d[2] = w[2]*fn + w[4]*ft + w[5]*fs + ds;
00957
00958
00959 ft -= 2*d[1]/(w[3]+w[5]);
00960 fs -= 2*d[2]/(w[3]+w[5]);
00961 normFt=sqrt(ft*ft+fs*fs);
00962 ft *=mu*fn/normFt;
00963 fs *=mu*fn/normFt;
00964
00965
00966 if (normError(fn,ft,fs,f_1[0],f_1[1],f_1[2]) < 0.000001)
00967 {
00968 dn=d[0]; dt=d[1]; ds=d[2];
00969
00970 return;
00971 }
00972
00973 }
00974
00975
00976
00977 }
00978
00979 void LocalBlock33::GS_State(double &mu, double &dn, double &dt, double &ds, double &fn, double &ft, double &fs)
00980 {
00981 double d[3];
00982 double normFt;
00983 f_1[0]=fn; f_1[1]=ft; f_1[2]=fs;
00984
00985
00986 d[0] = w[0]*fn + w[1]*ft + w[2]*fs + dn;
00987
00988 fn -= d[0]/w[0];
00989
00990 if (fn < 0){
00991 fn=0; ft=0; fs=0;
00992 return;
00993 }
00994
00995
00996
00997 d[1] = w[1]*fn + w[3]*ft + w[4]*fs + dt;
00998 d[2] = w[2]*fn + w[4]*ft + w[5]*fs + ds;
00999
01000
01001 ft -= 2*d[1]/(w[3]+w[5]);
01002 fs -= 2*d[2]/(w[3]+w[5]);
01003
01004 normFt=sqrt(ft*ft+fs*fs);
01005
01006 if (normFt > mu*fn){
01007 ft *=mu*fn/normFt;
01008 fs *=mu*fn/normFt;
01009 }
01010
01011 dn += w[0]*fn + w[1]*ft + w[2]*fs;
01012 dt += w[1]*fn + w[3]*ft + w[4]*fs;
01013 ds += w[2]*fn + w[4]*ft + w[5]*fs;
01014
01015 }
01016
01018
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01037
01039
01040 typedef struct{ double value; int index;} listElem;
01041 struct listSortAscending {
01042 bool operator()(const listElem& e1, const listElem& e2){
01043 return e1.value < e2.value;
01044 }
01045 };
01046
01047 int nlcp_gaussseidel(int dim, double *dfree, double**W, double *f, double mu, double tol, int numItMax, bool useInitialF)
01048 {
01049 double test = dim/3;
01050 double zero = 0.0;
01051 int numContacts = (int) floor(test);
01052 test = dim/3 - numContacts;
01053
01054 if (test>0.01){
01055 printf("\n WARNING dim should be dividable by 3 in nlcp_gaussseidel");
01056 return 0;
01057 }
01058
01059 int it,c1,i;
01060
01061
01062 double *d;
01063 d = (double*)malloc(dim*sizeof(double));
01064
01065 if (!useInitialF)
01066 memset(f, 0, dim*sizeof(double));
01067
01068
01069 double f_1[3];
01070 double d_1[3];
01071
01072
01073 LocalBlock33 **W33;
01074 W33 = (LocalBlock33 **) malloc (dim*sizeof(LocalBlock33));
01075 for (c1=0; c1<numContacts; c1++)
01076 W33[c1] = new LocalBlock33();
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01090
01092 double error = 0;
01093 double dn, dt, ds, fn, ft, fs;
01094
01095 for (it=0; it<numItMax; it++)
01096 {
01097 error =0;
01098 for (c1=0; c1<numContacts; c1++)
01099 {
01100
01101 int index1 = c1;
01102
01103
01104 f_1[0] = f[3*index1]; f_1[1] = f[3*index1+1]; f_1[2] = f[3*index1+2];
01105 set3Dof(f,index1,zero,zero,zero);
01106
01107
01108 dn=dfree[3*index1];dt=dfree[3*index1+1]; ds=dfree[3*index1+2];
01109 for (i=0; i<dim; i++){
01110 dn += W[3*index1 ][i]*f[i];
01111 dt += W[3*index1+1][i]*f[i];
01112 ds += W[3*index1+2][i]*f[i];
01113 }
01114 d_1[0] = dn + W[3*index1 ][3*index1 ]*f_1[0]+W[3*index1 ][3*index1+1]*f_1[1]+W[3*index1 ][3*index1+2]*f_1[2];
01115 d_1[1] = dt + W[3*index1+1][3*index1 ]*f_1[0]+W[3*index1+1][3*index1+1]*f_1[1]+W[3*index1+1][3*index1+2]*f_1[2];
01116 d_1[2] = ds + W[3*index1+2][3*index1 ]*f_1[0]+W[3*index1+2][3*index1+1]*f_1[1]+W[3*index1+2][3*index1+2]*f_1[2];
01117
01118 if(W33[index1]->computed==false)
01119 {
01120 W33[index1]->compute(W[3*index1][3*index1],W[3*index1][3*index1+1],W[3*index1][3*index1+2],
01121 W[3*index1+1][3*index1+1], W[3*index1+1][3*index1+2],W[3*index1+2][3*index1+2]);
01122 }
01123
01124
01125 fn=f_1[0]; ft=f_1[1]; fs=f_1[2];
01126 W33[index1]->GS_State(mu,dn,dt,ds,fn,ft,fs);
01127 error += absError(dn,dt,ds,d_1[0],d_1[1],d_1[2]);
01128
01129
01130 set3Dof(f,index1,fn,ft,fs);
01131
01132 }
01133
01134 if (error < tol){
01135 free(d);
01136 for (int i = 0; i < numContacts; i++)
01137 delete W33[i];
01138 free(W33);
01139
01140
01141 return 1;
01142 }
01143 }
01144 free(d);
01145 for (int i = 0; i < numContacts; i++)
01146 delete W33[i];
01147 free(W33);
01148
01149
01150
01151 return 0;
01152
01153 }
01154
01155 int nlcp_gaussseidelTimed(int dim, double *dfree, double**W, double *f, double mu, double tol, int numItMax, bool useInitialF, double timeout)
01156 {
01157 double test = dim/3;
01158 double zero = 0.0;
01159 int numContacts = (int) floor(test);
01160 test = dim/3 - numContacts;
01161
01162 ctime_t t0 = CTime::getTime()/CTime::getTicksPerSec();
01163
01164 if (test>0.01){
01165 printf("\n WARNING dim should be dividable by 3 in nlcp_gaussseidel");
01166 return 0;
01167 }
01168
01169 int it,c1,i;
01170
01171
01172 double *d;
01173 d = (double*)malloc(dim*sizeof(double));
01174
01175 if (!useInitialF)
01176 memset(f, 0, dim*sizeof(double));
01177
01178
01179 double f_1[3];
01180 double d_1[3];
01181
01182
01183 LocalBlock33 **W33;
01184 W33 = (LocalBlock33 **) malloc (dim*sizeof(LocalBlock33));
01185 for (c1=0; c1<numContacts; c1++)
01186 W33[c1] = new LocalBlock33();
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01200
01202 double error = 0;
01203 double dn, dt, ds, fn, ft, fs;
01204
01205 for (it=0; it<numItMax; it++)
01206 {
01207 error =0;
01208 for (c1=0; c1<numContacts; c1++)
01209 {
01210
01211 int index1 = c1;
01212
01213
01214 f_1[0] = f[3*index1]; f_1[1] = f[3*index1+1]; f_1[2] = f[3*index1+2];
01215 set3Dof(f,index1,zero,zero,zero);
01216
01217
01218 dn=dfree[3*index1];dt=dfree[3*index1+1]; ds=dfree[3*index1+2];
01219 for (i=0; i<dim; i++){
01220 dn += W[3*index1 ][i]*f[i];
01221 dt += W[3*index1+1][i]*f[i];
01222 ds += W[3*index1+2][i]*f[i];
01223 }
01224 d_1[0] = dn + W[3*index1 ][3*index1 ]*f_1[0]+W[3*index1 ][3*index1+1]*f_1[1]+W[3*index1 ][3*index1+2]*f_1[2];
01225 d_1[1] = dt + W[3*index1+1][3*index1 ]*f_1[0]+W[3*index1+1][3*index1+1]*f_1[1]+W[3*index1+1][3*index1+2]*f_1[2];
01226 d_1[2] = ds + W[3*index1+2][3*index1 ]*f_1[0]+W[3*index1+2][3*index1+1]*f_1[1]+W[3*index1+2][3*index1+2]*f_1[2];
01227
01228 if(W33[index1]->computed==false)
01229 {
01230 W33[index1]->compute(W[3*index1][3*index1],W[3*index1][3*index1+1],W[3*index1][3*index1+2],
01231 W[3*index1+1][3*index1+1], W[3*index1+1][3*index1+2],W[3*index1+2][3*index1+2]);
01232 }
01233
01234
01235 fn=f_1[0]; ft=f_1[1]; fs=f_1[2];
01236 W33[index1]->GS_State(mu,dn,dt,ds,fn,ft,fs);
01237 error += absError(dn,dt,ds,d_1[0],d_1[1],d_1[2]);
01238
01239
01240 set3Dof(f,index1,fn,ft,fs);
01241
01242 ctime_t t1 = CTime::getTime()/CTime::getTicksPerSec();
01243 if((t1-t0) > timeout)
01244 {
01245 free(d);
01246 for (int i = 0; i < numContacts; i++)
01247 delete W33[i];
01248 free(W33);
01249
01250
01251 return 1;
01252 }
01253 }
01254
01255 if (error < tol){
01256 free(d);
01257 for (int i = 0; i < numContacts; i++)
01258 delete W33[i];
01259 free(W33);
01260
01261
01262 return 1;
01263 }
01264 }
01265 free(d);
01266 for (int i = 0; i < numContacts; i++)
01267 delete W33[i];
01268 free(W33);
01269
01270
01271
01272 return 0;
01273
01274 }
01275
01276
01277
01278
01279
01280
01281
01282 void gaussSeidelLCP1(int dim, FemClipsReal * q, FemClipsReal ** M, FemClipsReal * res, double tol, int numItMax) {
01283 int compteur;
01284 int compteur2, compteur3;
01285
01286 double f_1;
01287 double error=0.0;
01288
01289 for (compteur=0; compteur<numItMax; compteur++)
01290 {
01291
01292 error=0.0;
01293 for (compteur2=0; compteur2<dim; compteur2++)
01294 {
01295
01296 res[compteur2]=q[compteur2];
01297 for (compteur3=0; compteur3<dim; compteur3++)
01298 {
01299 res[compteur2]+=M[compteur2][compteur3]* res[dim+compteur3];
01300 }
01301 res[compteur2] -= M[compteur2][compteur2]* res[dim+compteur2];
01302 f_1 = res[dim+compteur2];
01303
01304 if (res[compteur2]<0)
01305 {
01306 res[dim+compteur2]=-res[compteur2]/M[compteur2][compteur2];
01307 }
01308 else
01309 {
01310 res[dim+compteur2]=(FemClipsReal)0.0;
01311 }
01312
01313 error +=fabs( M[compteur2][compteur2] * (res[dim+compteur2] - f_1) );
01314
01315
01316 }
01317
01318 if (error < tol)
01319 {
01320
01321 break;
01322 }
01323
01324 }
01325
01326 for (compteur=0; compteur<dim; compteur++)
01327 res[compteur] = res[compteur+dim];
01328
01329 if (error >= tol)
01330 {
01331 std::cout << "No convergence in gaussSeidelLCP1 : error = " << error << std::endl;
01332
01333 }
01334 }
01335
01336 }
01337
01338 }