_fem.c

Go to the documentation of this file.
00001 /*
00002 %M This modules contains the Finite Element Method methods and definitions
00003 %a Joao Luiz Elias Campos.
00004 %d September 4th, 1998.
00005 %r $Id: fem.c,v 1.3 2004/06/24 18:32:35 joaoluiz Exp $
00006 %w (C) COPYRIGHT 1995-1996, Eduardo Nobre Lages.
00007    (C) COPYRIGHT 1997-1999, Joao Luiz Elias Campos.
00008    All Rights Reserved
00009    Duplication of this program or any part thereof without the express
00010    written consent of the author is prohibited.
00011  *
00012  *   Modified:    25-Aug-05    Alexandre A. Del Savio
00013  *     Modificada a função DisplacementVelocity onde implementou-se um 
00014  *     espaço paramétrico auxiliar para encontrar o novo ponto da 
00015  *     interação seguinte já sobre a restrição, sem introduzir
00016  *     desequilíbrio no sistema.
00017  *
00018  *   Modified:    30-Aug-05    Alexandre A. Del Savio
00019  *     Modificada a função DisplacementVelocity onde implementou-se o
00020  *     uso do nó piloto. Após a primeira interação os nós que possuem o 
00021  *     atributo DISPLACEMENT passam a ter o atributo OBJECT nas
00022  *     interações seguintes com exceção do nó piloto, para 
00023  *     "NodeVector[i].dof.{x,y,x}". 
00024  *
00025  *   Modified:    08-Sep-05    Alexandre A. Del Savio
00026  *     Modificada a função DisplacementVelocity onde corrigiu-se a 
00027  *     atualização do UVector e do VVector.
00028  *
00029  *   Modified:    23-Fev-06    Juan Pablo Ibañez
00030  *     Modificada a funcão DisplacementVelocity, que passa a retornar
00031  *     um valor int.
00032  *
00033  *   Modified:    23-Fev-06    Juan Pablo Ibañez
00034  *     Modificada a funcão DisplacementVelocity, onde a variável "id"
00035  *     é obtido segundo o valor de NumConstrains.     
00036  *
00037  *   Modified:    23-Fev-06    Juan Pablo Ibañez
00038  *     Modificada a funcão DisplacementVelocity, onde acessa-se o
00039  *     vetor ConstList em funcão do tipo de transformacão.
00040  *
00041  *   Modified:    24-Mai-06    Juan Pablo Ibañez
00042  *     Modificada a funcão DisplacementVelocity, onde se faz o 
00043  *     tratamento da "shear constrain" que é aplicada aos nós 
00044  *     no modo Pure Shear.
00045  *
00046  *   Modified:    23-Jun-06    Alexandre A. Del Savio
00047  *     Modified the DisplacementVelocity function when it was 
00048  *     corrected to treat curve and surface type constrains.
00049  *
00050  *   Modified:    5-Ago-06    Juan Pablo Ibanez
00051  *     Modificada a funcao DisplacementVelocity para permitir processar
00052  *     as restricoes independentemente do tipo de transformacao.
00053  *
00054  *   Modified     14-Set-06   Juan Pablo Ibanez
00055  *     Modificada a funcao DisplacementVelocity, onde adaptou-se a mesma
00056  *     as mudancas na struct sNode (NodeVector) no campo constrain.
00057  *
00058  *   Modified     18-Set-06   Márcio Santi & Gisele Cunha & Juan Pablo Ibañez
00059  *     When changed API for constrain methods that now gets the identifier
00060  *     for the current constrained node element. 
00061  *     Changed constrain methods name from GlobalParametric to Slide
00062  *
00063  *   Modified     27-Set-06   Márcio Santi e Juan Pablo Ibañez
00064  *     When reviewed all necessary routines for implementing the constrain
00065  *     modules. Here in fem was removed the COnstToGlobal call for any
00066  *     iteration excepts iteration 0 (zero).
00067  *     ConstSlide function now recieves vectors in local element constrain
00068  *     coordinates instead of global coordinates as it was used before.
00069  *     Reorganized code generaly.
00070  *
00071  *   Modified:    Dez-06 André Luis Muller
00072  *     Criadas as funções para analise com o método
00073  *     gradiente conjugado. (FirstSolution)- ElmKpr, ElmKp, GCSolver
00074  *
00075  *   Modified:    Fev-07 André Luis Muller
00076  *     Criadas as funções para analise com o método
00077  *     BFGS. (BFGS)- SearchDirection
00078  *
00079  *   Modified:    Jun-07 André Luis Muller
00080  *     Criadas as funções para analise com algoritmos implícitos
00081  *     LINEAR, BFGS e NRM.
00082  *
00083  *   Modified:    Jul-07 André Luis Muller
00084  *     Modificadas as funções ElmKpr e ElmKp para utilizar o
00085  *     formato CSR na armazernagem da matriz de rigidez.
00086  *     
00087  *     Possibilidade de utilizar o solver SAMG em todos os algoritmos
00088  *     implícitos.
00089  *     
00090  *
00091  */
00092 
00093 /*
00094 ** ------------------------------------------------------------------------
00095 ** Global variables and symbols:
00096 */
00097 #include <stdio.h>
00098 #include <stdlib.h>
00099 #include <math.h>
00100 
00101 #include "constrain.h"
00102 #include "load.h"
00103 #include "elm.h"
00104 #include "node.h"
00105 #include "alg.h"
00106 #include "xgplib.h"
00107 #include "fem.h"
00108 #include "csr.h"
00109 #include "pfs.h"
00110 #include "solversamg.h"
00111 
00112 
00113 /*
00114 ** ------------------------------------------------------------------------
00115 ** Local variables and symbols:
00116 */
00117 #ifndef maxcor
00118 #define maxcor 30
00119 #endif
00120 
00121 #ifndef maxiter
00122 #define maxiter 5000
00123 #endif
00124 
00125 #ifndef cgtol
00126 #define cgtol 1.0e-10
00127 #endif
00128 
00129 #ifndef ngr
00130 #define ngr 10e20
00131 #endif
00132 
00133 
00134 /*
00135 ** ------------------------------------------------------------------------
00136 ** Local functions:
00137 */
00138 static void ElmKpr(double *);
00139 static void ElmKp(double *, double *);
00140 static void GCSolver(double *, double *);
00141 static void SearchDirection(int i, int k, double *vector, double **w, double **v); 
00142 
00143 static void ElmKpParalelo(int , int , int , int , double *, double *,
00144                           double *, double *, double *, double *);
00145 static void ElmKprParalelo(int , int , int , int, double *,
00146                            double *, double *, double *, double *,
00147                            double *, double *);
00148 static void ContourParalelo(int , int , double *, double *);
00149 static void ContourKpParalelo(int , int , double *); 
00150 static void ProdEscalarParalelo(int, int , double *, double *,
00151                                 double *, double *, double *, double *);
00152 static void UpDataParalelo(int , int , double *, double *, double ,
00153                            double *, double *, double *, double *,
00154                            double *, double *, double *);
00155 static void ResParalelo(int , int , double ,
00156                         double *, double *, double *,
00157                         double *, double *, double *); 
00158 static void PreParalelo(int , int , double *, double *,
00159                         double *, double *, double *,
00160                         double *, double *);                                                                                                            
00161 
00162 /*
00163 ** ------------------------------------------------------------------------
00164 ** Local functions:
00165 */
00166 
00167 /*
00168 %F
00169 */
00170 static void SearchDirection(int i, int k, double *vector, double **w, double **v)
00171 {
00172 /*
00173 Essa função calcula a direção de busca para
00174 o método BFGS
00175 */      
00176   int n;
00177   int j;
00178   int m;
00179   double a;
00180   double *b;
00181   int    matrix = 12;
00182   int    iversion = 4;
00183   int    nsys = 1;
00184   int    npnt = 0;
00185   
00186   n=0;
00187   a=0.0;
00188   m=k;
00189 
00190   b =  (double*)malloc(i*sizeof(double)); 
00191 
00192   for (j = 0; j < i; j++){
00193    a += w[j][m]*vector[j];
00194   }
00195   for (j = 0; j < i; j++){
00196    b[j] = vector[j]+v[j][m]*a;
00197   }
00198   for (j = 0; j < i; j++){
00199    vector[j] = b[j];
00200   }
00201   while(m>0){
00202    m -=1;
00203    a=0.0;
00204    for (j = 0; j < i; j++){
00205     a += w[j][m]*vector[j];
00206    }
00207    for (j = 0; j < i; j++){
00208     b[j] = vector[j]+v[j][m]*a;
00209    }
00210    for (j = 0; j < i; j++){
00211     vector[j] = b[j];
00212    }
00213   }
00214 
00215   if(Config.solver == 0){
00216 
00217    /* usa o método do gradiente conjugado
00218    */
00219    GCSolver(b, vector);
00220   
00221   }
00222   else{
00223  
00224    /* chama o solver Samg para calcular o incremento dos deslocamentos
00225    */
00226    SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, b, vector );
00227    
00228   }
00229   
00230   a=0.0;
00231   for (j = 0; j < i; j++){
00232    a += v[j][n]*vector[j];
00233   }
00234   for (j = 0; j < i; j++){
00235    b[j] = vector[j]+w[j][n]*a;
00236   }
00237   for (j = 0; j < i; j++){
00238    vector[j] = b[j];
00239   }
00240   while(n<k){
00241    n +=1;
00242    a=0.0;
00243    for (j = 0; j < i; j++){
00244     a += v[j][n]*vector[j];
00245    }
00246    for (j = 0; j < i; j++){
00247     b[j] = vector[j]+w[j][n]*a;
00248    }
00249    for (j = 0; j < i; j++){
00250     vector[j] = b[j];
00251    }
00252   }
00253   free ( b );
00254 }
00255 
00256 /*INICIO TESTE*/
00257 
00258 static void ProdutoEscalar(int n, int nn, double *w, double *v, double *a )
00259 {
00260  int  i;
00261  
00262  *a = 0.0;
00263  
00264  for (i = n; i < nn; i++){
00265   *a += w[i]*v[i];
00266  }
00267 }
00268 
00269 static void SomaVector(int n, int nn, double *w, double *v, double *b, double a)
00270 {
00271  int  i;
00272  
00273  for (i = n; i < nn; i++){
00274   b[i] = w[i] + v[i]*a;
00275   v[i] = b[i];
00276  }
00277 }
00278 
00279 static void SearchDirectionParalelo(int i, int k, double *vector, double **w, double **v,
00280                                     int ni[], int nf[], int gli[], int glf[])
00281 {
00282 /*
00283 Essa função calcula a direção de busca para
00284 o método BFGS
00285 */      
00286   int n;
00287   int j;
00288   int m;
00289   double a;
00290   double *b;
00291   int    matrix = 12;
00292   int    iversion = 4;
00293   int    nsys = 1;
00294   int    npnt = 0;
00295   
00296   int    nd = 10;
00297   int    l;
00298   double ea;
00299   double *wi, *vi;
00300   
00301   n=0;
00302   a=0.0;
00303   m=k;
00304 
00305   b  = (double*)malloc(i*sizeof(double)); 
00306   wi = (double*)malloc(i*sizeof(double));
00307   vi = (double*)malloc(i*sizeof(double));
00308   
00309   for(j = 0; j < i; j++){
00310    wi[j] = w[j][m];
00311    vi[j] = v[j][m];
00312   } 
00313   
00314   ea = 0.0;
00315   
00316   for (l = 0; l < nd; l++){
00317    
00318    ProdutoEscalar(gli[l], glf[l], wi, vector, &a);
00319    
00320    ea += a;
00321   }
00322   
00323   for (l = 0; l < nd; l++){
00324    
00325    SomaVector(gli[l], glf[l], vector, vi, b, ea);
00326    
00327   }
00328 
00329   while(m>0){
00330    m -=1;
00331    ea = 0.0;
00332    
00333    for(j = 0; j < i; j++){
00334     wi[j] = w[j][m];
00335     vi[j] = v[j][m];
00336    }
00337    
00338    for (l = 0; l < nd; l++){
00339    
00340     ProdutoEscalar(gli[l], glf[l], wi, vector, &a);
00341    
00342     ea += a;
00343    }
00344    
00345    for (l = 0; l < nd; l++){
00346    
00347     SomaVector(gli[l], glf[l], vector, vi, b, ea);
00348    
00349    }
00350    
00351   }
00352 
00353   if(Config.solver == 0){
00354 
00355    /* usa o método do gradiente conjugado
00356    */
00357    GCSolver(b, vector);
00358   
00359   }
00360   else{
00361  
00362    /* chama o solver Samg para calcular o incremento dos deslocamentos
00363    */
00364    SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, b, vector );
00365    
00366   }
00367   
00368   ea = 0.0;
00369   
00370   for(j = 0; j < i; j++){
00371    wi[j] = w[j][n];
00372    vi[j] = v[j][n];
00373   } 
00374   
00375   for (l = 0; l < nd; l++){
00376    
00377    ProdutoEscalar(gli[l], glf[l], vi, vector, &a);
00378    
00379    ea += a;
00380   }
00381   
00382   for (l = 0; l < nd; l++){
00383    
00384    SomaVector(gli[l], glf[l], vector, wi, b, ea);
00385    
00386   }
00387   
00388   while(n<k){
00389    n +=1;
00390    ea = 0.0;
00391    
00392    for (l = 0; l < nd; l++){
00393    
00394     ProdutoEscalar(gli[l], glf[l], vi, vector, &a);
00395    
00396     ea += a;
00397    }
00398   
00399    for (l = 0; l < nd; l++){
00400    
00401     SomaVector(gli[l], glf[l], vector, wi, b, ea);
00402    
00403    }
00404    
00405   }
00406   free ( b );
00407   free ( vi );
00408   free ( wi );
00409 }
00410 
00411 /*FIM TESTE*/
00412 
00413 #if 0
00414 
00415 /*
00416 %F
00417 */
00418 static void ElmKpr(double *Kp)
00419 {
00420  int     i;           
00421 
00422  for( i = 0; i < NumNodes * NDof; i++ ){         
00423   Kp[i] = avector[ia[i]];
00424  }
00425 }
00426 
00427 /*
00428 %F
00429 */
00430 static void ElmKp(double *d, double *p)
00431 {
00432  int     i,j,k,l,m;           
00433 
00434  for( i = 0; i < NumNodes * NDof; i++ ){  
00435   j = ia[i];
00436   l = ia[i+1];  
00437   for (k = j; k < l; k++){
00438    m=ja[k]; 
00439    d[i] += avector[k] * p[m];
00440   }
00441  }
00442 }
00443 
00444 /*
00445 %F
00446 */
00447 static void GCSolver(double *R, double *u)
00448 {
00449  int    i,j,m;                      
00450  double alpha,beta,a,b;                
00451  double *rn,*p,*d,*Kp,*z;
00452  double error;
00453  int    iter;
00454  
00455  m = NumNodes * NDof;
00456  
00457  rn =  (double*)malloc(m*sizeof(double));
00458  p  =  (double*)malloc(m*sizeof(double));
00459  d  =  (double*)malloc(m*sizeof(double));
00460  Kp =  (double*)malloc(m*sizeof(double));
00461  z  =  (double*)malloc(m*sizeof(double));
00462  
00463  for( i = 0; i < m; i++ ){
00464   Kp[i] = 0.0;
00465  }
00466  
00467  /* monta matriz de precondicionamento diagonal
00468  */
00469  ElmKpr(Kp);
00470  
00471  for( i = 0; i < NumNodes; i++ ){
00472   if( NodeVector[i].dof.x == DISPLACEMENT ){
00473    Kp[NDof*i]+= ngr;
00474   }
00475   if( NodeVector[i].dof.y == DISPLACEMENT ){
00476    Kp[NDof*i+1]+= ngr;
00477   }
00478   if( NDof == 3 ) {
00479    if( NodeVector[i].dof.z == DISPLACEMENT ){
00480     Kp[NDof*i+2]+= ngr;
00481    }
00482   }
00483  }      
00484  
00485  for( j = 0; j < m; j++ ){
00486   if(Kp[j] != 0.0){
00487    Kp[j] = 1.0/Kp[j];
00488   }
00489   else{
00490    Kp[j] = 1.0;
00491   }
00492   rn[j] = R[j];
00493   z[j] = p[j] = Kp[j]*rn[j];
00494   d[j] = u[j] = 0.0;
00495  }
00496  
00497  error = 1.0; iter = 0;
00498  
00499  while((error>=cgtol)&&(iter<maxiter)){
00500   iter ++;
00501   
00502   error = 0.0;
00503   
00504   ElmKp(d,p);
00505   
00506   for( i = 0; i < NumNodes; i++ ){
00507    if( NodeVector[i].dof.x == DISPLACEMENT ){
00508     d[NDof*i] = ngr*p[NDof*i];
00509    }
00510    if( NodeVector[i].dof.y == DISPLACEMENT ){
00511     d[NDof*i+1] = ngr*p[NDof*i+1];
00512    }
00513    if( NDof == 3 ) {
00514     if( NodeVector[i].dof.z == DISPLACEMENT ){
00515      d[NDof*i+2] = ngr*p[NDof*i+2];
00516     }
00517    }
00518   }
00519   
00520   a = b = 0.0;
00521   
00522   for (j = 0; j < m; j++){
00523    a+= z[j]*rn[j]; 
00524    b+= p[j]*d[j];
00525   }
00526   
00527   alpha = a/b;
00528   a = b = 0.0;
00529   
00530   for( j = 0; j < m; j++ ){
00531    u[j]+= alpha*p[j];
00532    rn[j]= R[j]-alpha*d[j];
00533    b+= z[j]*R[j];
00534    z[j]= Kp[j]*rn[j];
00535    a+= z[j]*rn[j];
00536   }
00537   
00538   beta=a/b;
00539   
00540   for( j = 0; j < m; j++ ){
00541    p[j]= z[j]+beta*p[j];
00542    R[j]= rn[j]; 
00543    d[j]= 0.0;
00544    error+= rn[j]*rn[j];
00545   }
00546   
00547   error=sqrt(error);
00548   
00549  }
00550  
00551  free ( rn );
00552  free ( p  );
00553  free ( d  );
00554  free ( Kp );
00555  free ( z  );
00556 }
00557 
00558 #else
00559 /* TESTE PARA PARALELISMO*/                           
00560                                                       
00561 /*                                                    
00562 %F                                                    
00563 */                                                    
00564 static void ElmKprParalelo(int n, int nn, int m, int mm, double *Kp,
00565                            double *d, double *p, double *z, double *rn,
00566                            double *u, double *R)                        
00567 {                                                     
00568  int     i;                                           
00569                                                       
00570  for( i = n; i < nn; i++ ){           
00571   Kp[i] = avector[ia[i]];                             
00572  }                 
00573  
00574  ContourKpParalelo(m, mm, Kp); 
00575  
00576  PreParalelo(n, nn, Kp, d, p, z, rn, u, R); 
00577                                     
00578 }                                                     
00579                                                       
00580 /*                                                    
00581 %F                                                    
00582 */                                                    
00583 static void ElmKpParalelo(int n, int nn, int ni, int nf, double *d, double *p,
00584                           double *z, double *rn, double *a, double *b)                          
00585 {                                                     
00586  int     i,j,k,l,m;                                   
00587                                                       
00588  for( i = n; i < nn; i++ ){                            
00589   j = ia[i];                                      
00590   l = ia[i+1];                                        
00591   for (k = j; k < l; k++){                            
00592    m=ja[k];                                           
00593    d[i] += avector[k] * p[m];                         
00594   }                                                   
00595  }         
00596      
00597  ContourParalelo(ni, nf, d, p);
00598    
00599  ProdEscalarParalelo(n, nn, a, b, d, p, z, rn);  
00600                                       
00601 }          
00602 
00603 static void ContourParalelo(int n, int nn, double *d, double *p) 
00604 {
00605  int i;
00606  
00607  for( i = n; i < nn; i++ ){  
00608   if( NodeVector[i].dof.x == DISPLACEMENT ){        
00609    d[NDof*i] = ngr*p[NDof*i];                       
00610   }                                                 
00611   if( NodeVector[i].dof.y == DISPLACEMENT ){        
00612    d[NDof*i+1] = ngr*p[NDof*i+1];                   
00613   }                                                 
00614   if( NDof == 3 ) {                                 
00615    if( NodeVector[i].dof.z == DISPLACEMENT ){       
00616     d[NDof*i+2] = ngr*p[NDof*i+2];                  
00617    }                                                
00618   } 
00619  }  
00620    
00621 }  
00622 
00623 static void ContourKpParalelo(int n, int nn, double *Kp) 
00624 {
00625  int i;
00626  
00627  for( i = n; i < nn; i++ ){                       
00628   if( NodeVector[i].dof.x == DISPLACEMENT ){          
00629    Kp[NDof*i]+= ngr;                                  
00630   }                                                   
00631   if( NodeVector[i].dof.y == DISPLACEMENT ){          
00632    Kp[NDof*i+1]+= ngr;                                
00633   }                                                   
00634   if( NDof == 3 ) {                                   
00635    if( NodeVector[i].dof.z == DISPLACEMENT ){         
00636     Kp[NDof*i+2]+= ngr;                               
00637    }                                                  
00638   }                                                   
00639  }
00640    
00641 }    
00642 
00643 static void ProdEscalarParalelo(int n, int nn, double *a, double *b,
00644                                 double *d, double *p, double *z, double *rn) 
00645 {
00646  int i;
00647  
00648  *a = *b = 0.0;  
00649 
00650  for (i = n; i < nn; i++){                           
00651   *a += z[i]*rn[i];                                   
00652   *b += p[i]*d[i];                                    
00653  }
00654  
00655 }   
00656 
00657 static void UpDataParalelo(int n, int nn, double *a, double *b, double alpha,
00658                            double *u, double *d, double *p, double *z,
00659                            double *rn, double *R, double *Kp) 
00660                              
00661 {
00662  int i;
00663  
00664  *a = *b = 0.0;  
00665  
00666  for (i = n; i < nn; i++){                           
00667   u[i]+= alpha*p[i];                               
00668   rn[i]= R[i]-alpha*d[i];                          
00669   *b += z[i]*R[i];                                   
00670   z[i]= Kp[i]*rn[i];                               
00671   *a += z[i]*rn[i];                                   
00672  }
00673  
00674 }
00675 
00676 static void ResParalelo(int n, int nn, double beta,
00677                         double *d, double *p, double *z,
00678                         double *rn, double *R, double *error) 
00679 {
00680  int i;
00681  
00682  for( i = n; i < nn; i++ ){                         
00683   p[i]= z[i]+beta*p[i];                            
00684   R[i]= rn[i];                                     
00685   d[i]= 0.0;                                       
00686   *error+= rn[i]*rn[i];                             
00687  } 
00688  
00689 }
00690 
00691 static void PreParalelo(int n, int nn, double *Kp, double *d,
00692                         double *p, double *z, double *rn,
00693                         double *u, double *R) 
00694 {
00695  int i;
00696  
00697  for( i = n; i < nn; i++ ){                                                    
00698   if(Kp[i] != 0.0){                                   
00699    Kp[i] = 1.0/Kp[i];                                 
00700   }                                                   
00701   else{                                               
00702    Kp[i] = 1.0;                                       
00703   }                                                   
00704   rn[i] = R[i];                                       
00705   z[i] = p[i] = Kp[i]*rn[i];                          
00706   d[i] = u[i] = 0.0;                                  
00707  }
00708  
00709 }    
00710 
00711                        
00712                                                       
00713 /*                                                    
00714 %F                                                    
00715 */                                                    
00716 static void GCSolver(double *R, double *u)            
00717 {                                                     
00718  int    i,m;                                        
00719  double alpha,beta;                               
00720  double *rn,*p,*d,*Kp,*z;                             
00721  double error;                                        
00722  int    iter;                                         
00723  int    gli[10], glf[10];
00724  int    ni[10], nf[10];
00725  double ea, eb;
00726  double a, b;
00727  int    nno;
00728  
00729  /*define número de divisões*/
00730  int    nd = 10;
00731  
00732  /*define nó inicial e nó final de cada divisão*/ 
00733  nno = NumNodes/nd;
00734                                                       
00735  ni[0] = 0;
00736  nf[0] = nno;
00737  for( i = 1; i < nd-1; i++ ){  
00738   ni[i] = nf[i-1] + 1;                          
00739   nf[i] = nf[i-1] + nno;                                        
00740  }
00741  ni[nd-1] = nf[nd-2] + 1;
00742  nf[nd-1] = NumNodes - 1;
00743  
00744  /*define dof inicial e dof final de cada divisão*/
00745  gli[0] = 0;
00746  glf[0] = nf[0] * NDof;
00747  for( i = 1; i < nd-1; i++ ){  
00748   gli[i] = glf[i-1];                          
00749   glf[i] = nf[i] * NDof;                                        
00750  }
00751  gli[nd-1] = glf[nd-2];
00752  glf[nd-1] = nf[nd-1] * NDof + NDof;
00753  
00754  /* dof total */                                                
00755  m = NumNodes * NDof;                                 
00756                                                       
00757  rn =  (double*)malloc(m*sizeof(double));             
00758  p  =  (double*)malloc(m*sizeof(double));             
00759  d  =  (double*)malloc(m*sizeof(double));             
00760  Kp =  (double*)malloc(m*sizeof(double));             
00761  z  =  (double*)malloc(m*sizeof(double));             
00762                                                                                                          
00763  /* monta matriz de precondicionamento diagonal       
00764  */      
00765  for(i = 0; i < nd; i++){
00766                 
00767   ElmKprParalelo(gli[i], glf[i], ni[i], nf[i], Kp, d, p, z, rn, u, R);
00768   
00769  }                                             
00770                                                                                                                                                                                                                                                       
00771                                                       
00772  error = 1.0; iter = 0;                               
00773                                                       
00774  while((error>=cgtol)&&(iter<maxiter)){
00775                        
00776   iter ++;                                            
00777                                                       
00778   error = ea = eb = 0.0;                                   
00779   
00780   /*divide o processo em nd*/
00781   for(i = 0; i < nd; i++){
00782                 
00783    ElmKpParalelo(gli[i], glf[i], ni[i], nf[i], d, p, z, rn, &a, &b);
00784    
00785    ea += a;
00786    eb += b; 
00787    
00788   }  
00789   
00790   alpha = ea/eb;
00791   ea = eb = 0.0; 
00792   
00793   /*divide o processo em nd*/
00794   for(i = 0; i < nd; i++){ 
00795         
00796    UpDataParalelo(gli[i], glf[i], &a, &b, alpha, u, d, p, z, rn, R, Kp);                                            
00797    
00798    ea += a;
00799    eb += b;
00800    
00801   }
00802   
00803   beta = ea/eb;                                         
00804   
00805   /*divide o processo em nd*/
00806   for(i = 0; i < nd; i++){ 
00807         
00808    ResParalelo(gli[i], glf[i], beta, d, p, z, rn, R, &error);
00809                                                                                                 
00810   }       
00811   error = sqrt(error);                         
00812  }                                                    
00813                                                       
00814  free ( rn );                                         
00815  free ( p  );                                         
00816  free ( d  );                                         
00817  free ( Kp );                                         
00818  free ( z  );                                         
00819 }                                                     
00820                                                       
00821 /* FIM DO TESTE*/
00822 #endif
00823 
00824 /*
00825 ** ------------------------------------------------------------------------
00826 ** Public functions:
00827 */
00828 
00829 /*
00830 %F
00831 */
00832 void BuildAVector( void )
00833 {
00834  int    i,j,k,l,elm;                      
00835  double ke[24][24];
00836  int    u[24];
00837  int    index;
00838  
00839  /* monta matriz de rigidez dos elementos
00840     no formato csr
00841  */
00842  for( elm = 0; elm < NumElements; elm++ ){
00843   /* pega os graus de liberdade do elemento
00844   */
00845   ElmGetDof(ElmList[elm], u, &index);
00846   /* monta matriz de rigidez do elemento
00847   */
00848   ElmKMatrix(ElmList[elm], ke);
00849   /* coloca os termos da matriz do elemento
00850      no vetor de coeficientes avector
00851   */
00852   for(i = 0; i < index; i++){
00853    for(j = 0; j < index; j++){
00854     k = u[i];  
00855     l = u[j];
00856     BuildaVector(k,l,ke[i][j]);
00857    }
00858   }
00859  }
00860  /* aplica condições de contorno em avector
00861  */
00862  for( i = 0; i < NumNodes; i++ ){
00863   if( NodeVector[i].dof.x == DISPLACEMENT ){
00864    avector[ia[NDof*i]]+= ngr;
00865   }
00866   if( NodeVector[i].dof.y == DISPLACEMENT ){
00867    avector[ia[NDof*i+1]]+= ngr;
00868   }
00869   if( NDof == 3 ) {
00870    if( NodeVector[i].dof.z == DISPLACEMENT ){
00871     avector[ia[NDof*i+2]]+= ngr;
00872    }
00873   }
00874  }
00875 }       
00876 
00877 
00878 /*
00879 %F
00880 */
00881 void BFGS(double dtime, double *F, double *U, double *V,
00882           int *iteration, double *error, double error0, int loadstep )
00883 {
00884 /*
00885 Essa função busca minimizar o vetor resíduo
00886 com o método BFGS
00887 */
00888   int    i,j,k,n;
00889   double vp[3];
00890   eRestType dof[3];                     
00891   double b, c;                                                 
00892   double *q, *F0;
00893   double **w, **v;
00894   int    needite;
00895   int    stop = 0;
00896   int    matrix = 12;
00897   int    iversion = 4;
00898   int    nsys = 1;
00899   int    npnt = 0;
00900   
00901   n = NumNodes*NDof;
00902   
00903   q  = (double*)malloc(n*sizeof(double));
00904   F0 = (double*)malloc(n*sizeof(double));
00905   w  = (double**)malloc(n*sizeof(double*));
00906   v  = (double**)malloc(n*sizeof(double*));
00907   for(i=0; i < n; i++){
00908    w[i] = (double*)malloc(maxcor*sizeof(double));
00909    v[i] = (double*)malloc(maxcor*sizeof(double));
00910   }
00911  
00912   for( i = 0; i < NumNodes; i++ ) {
00913    dof[0] = NodeVector[i].dof.x;
00914    dof[1] = NodeVector[i].dof.y;
00915    dof[2] = NodeVector[i].dof.z;
00916    vp[0]  = NodeVector[i].dof.vpx;
00917    vp[1]  = NodeVector[i].dof.vpy;
00918    vp[2]  = NodeVector[i].dof.vpz;
00919    for( j = 0; j < NDof; j++ ) {
00920    /* Verifica a condição de contorno de deslocamento
00921     */
00922     if(dof[j] == DISPLACEMENT){
00923      U[NDof*i+j] = vp[j] * Config.loadfactor;
00924     }
00925    }
00926   }
00927  
00928   /* Calcula o vetor de forças desequilibradas
00929   */
00930   InternalForces( dtime, F, U, V );
00931 
00932   for( j = 0; j < n; j++ ){
00933    q[j] = F0[j] = V[j] = F[j];
00934   }
00935   k=0; 
00936  
00937   /* Calcula o vetor de incrementos de deslocamentos
00938   */
00939   if(Config.solver == 0){
00940 
00941    /* usa o método do gradiente conjugado
00942    */
00943    GCSolver(F, V);
00944    
00945   }
00946   else{
00947  
00948    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
00949    SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
00950   }
00951   
00952   *error = Config.tolerance;  needite   = 0;
00953   
00954   do {
00955    /* atualiza o vetor de deslocamentos
00956    */
00957    for( i = 0; i < NumNodes; i++ ) {
00958     U[NDof*i]   +=  V[NDof*i];    
00959     U[NDof*i+1] +=  V[NDof*i+1];  
00960     if( NDof == 3 ) {
00961      U[NDof*i+2] += V[NDof*i+2];  
00962     }
00963    }
00964    
00965    /* Calcula o vetor de forças desequilibradas
00966    */
00967    InternalForces( dtime, F, U, V); 
00968    
00969    *error = ComputeError( F, V, error0 );
00970   
00971    if( _count_it != NULL )
00972     (*_count_it) ( *iteration, *error, loadstep); 
00973     
00974    if( _fstop != NULL )
00975      (*_fstop) ( &stop ); 
00976      
00977    /* Check for another iteration
00978    */
00979    needite = NeedIteration( error, iteration, stop );
00980    
00981    printf( "\tStep: %d             Error: %5.3E\r", *iteration, *error );
00982    
00983    if(!needite) break;
00984    if(*error < Config.tolerance) break;
00985 
00986    b=c=0.0;
00987    for (j = 0; j < n; j++){
00988     q[j] -= F[j];
00989     b += V[j]*q[j];
00990     c += V[j]*F0[j];
00991    }
00992    for (j = 0; j < n; j++){
00993     v[j][k]= -(pow(fabs(b/c),0.5))*F0[j]-q[j];   
00994     w[j][k]= V[j]/b;                            
00995     V[j] = q[j] = F0[j] = F[j];
00996    }
00997    /* calcula a direção de busca*/
00998    SearchDirection(n, k, V, w, v);    
00999    k ++;
01000    if( k == maxcor ) k = 0;
01001   }while( needite); 
01002  
01003   free ( q );
01004   free ( F0 );
01005   for(i=0; i < n; i++){
01006    free( w[i] );
01007    free( v[i] );
01008   }
01009   free( w ); 
01010   free( v );    
01011  
01012 }
01013 
01014 /*
01015 %F
01016 */
01017 void NRM(double dtime, double *F, double *U, double *V,
01018           int *iteration, double *error, double error0, int loadstep )
01019 {
01020 /*
01021 Essa função busca minimizar o vetor resíduo
01022 com o método NRM
01023 */
01024   int    i,j,n;
01025   double vp[3];
01026   eRestType dof[3];                       
01027   int    needite = 0;
01028   int    stop = 0;
01029   int    matrix = 12;
01030   int    iversion = 4;
01031   int    nsys = 1;
01032   int    npnt = 0;
01033   
01034   n = NumNodes*NDof;
01035   
01036   do {
01037         
01038    for( i = 0; i < NumNodes; i++ ) {
01039     dof[0] = NodeVector[i].dof.x;
01040     dof[1] = NodeVector[i].dof.y;
01041     dof[2] = NodeVector[i].dof.z;
01042     vp[0]  = NodeVector[i].dof.vpx;
01043     vp[1]  = NodeVector[i].dof.vpy;
01044     vp[2]  = NodeVector[i].dof.vpz;
01045     for( j = 0; j < NDof; j++ ) {
01046     /* Verifica a condição de contorno de deslocamento
01047      */
01048      if(dof[j] == DISPLACEMENT){
01049       U[NDof*i+j] = vp[j] * Config.loadfactor;
01050      }
01051     }
01052    }
01053  
01054    /* Calcula o vetor de forças desequilibradas
01055    */
01056    InternalForces( dtime, F, U, V );
01057 
01058    for( j = 0; j < n; j++ ){
01059     V[j] = F[j];
01060    }
01061  
01062    /* Calcula o vetor de incrementos de deslocamentos
01063    */
01064   if(Config.solver == 0){
01065 
01066    /* usa o método do gradiente conjugado
01067    */
01068    GCSolver(F, V);
01069   
01070   }
01071   else{
01072  
01073    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
01074    SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
01075    
01076   }
01077  
01078    /* atualiza o vetor de deslocamentos
01079    */
01080    for( i = 0; i < NumNodes; i++ ) {
01081     U[NDof*i]   +=  V[NDof*i];    
01082     U[NDof*i+1] +=  V[NDof*i+1];  
01083     if( NDof == 3 ) {
01084      U[NDof*i+2] += V[NDof*i+2];  
01085     }
01086    }
01087    
01088    /* Calcula o vetor de forças desequilibradas
01089    */
01090    InternalForces( dtime, F, U, V); 
01091    
01092    *error = ComputeError( F, V, error0 );
01093   
01094    if( _count_it != NULL )
01095     (*_count_it) ( *iteration, *error, loadstep); 
01096     
01097    if( _fstop != NULL )
01098      (*_fstop) ( &stop ); 
01099      
01100    /* Check for another iteration
01101    */
01102    needite = NeedIteration( error, iteration, stop );
01103    
01104    printf( "\tStep: %d             Error: %5.3E\r", *iteration, *error );            
01105                  
01106   }while(needite); 
01107  
01108 }
01109 
01110 /*
01111 %F
01112 */
01113 void LINEAR(double dtime, double *F, double *U, double *V,
01114                int *iteration, double *error, double error0, int loadstep )
01115 {
01116   int    i,j;
01117   double vp[3];
01118   eRestType dof[3];                     
01119   int    stop = 0;
01120   int    matrix = 12;
01121   int    iversion = 4;
01122   int    nsys = 1;
01123   int    npnt = 0;
01124  
01125   for( i = 0; i < NumNodes; i++ ) {
01126    dof[0] = NodeVector[i].dof.x;
01127    dof[1] = NodeVector[i].dof.y;
01128    dof[2] = NodeVector[i].dof.z;
01129    vp[0]  = NodeVector[i].dof.vpx;
01130    vp[1]  = NodeVector[i].dof.vpy;
01131    vp[2]  = NodeVector[i].dof.vpz;
01132    for( j = 0; j < NDof; j++ ) {
01133    /* Verifica a condição de contorno de deslocamento
01134     */
01135     if(dof[j] == DISPLACEMENT){
01136      U[NDof*i+j] = vp[j] * Config.loadfactor;
01137     }
01138    }
01139   }
01140  
01141   /* Calcula o vetor de forças desequilibradas
01142   */
01143   InternalForces( dtime, F, U, V );
01144   
01145   for( j = 0; j < NumNodes*NDof; j++ ){
01146    V[j] = F[j];
01147   }
01148  
01149   /* Calcula o vetor de incrementos de deslocamentos
01150   */
01151   if(Config.solver == 0){
01152 
01153    /* usa o método do gradiente conjugado
01154    */
01155    GCSolver(F, V);
01156    
01157   }
01158   else{
01159   
01160    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
01161    SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
01162   }
01163  
01164   /* atualiza o vetor de deslocamentos
01165   */
01166   for( i = 0; i < NumNodes; i++ ) {
01167    U[NDof*i]   +=  V[NDof*i];    
01168    U[NDof*i+1] +=  V[NDof*i+1];  
01169    if( NDof == 3 ) {
01170     U[NDof*i+2] += V[NDof*i+2];  
01171    }
01172   }
01173   
01174   /* Calcula o vetor de forças desequilibradas
01175    */
01176   InternalForces( dtime, F, U, V); 
01177    
01178   *error = ComputeError( F, V, error0 );
01179   
01180   if( _count_it != NULL )
01181     (*_count_it) ( *iteration, *error, loadstep); 
01182     
01183   if( _fstop != NULL )
01184      (*_fstop) ( &stop );
01185 
01186 }
01187 
01188 
01189 /*INICIO TESTE*/
01190 #if 0
01191 /*
01192 %F
01193 */
01194 void InternalForces( double dtime, double *F, double *U, double *V )
01195 {
01196  int     i;
01197  sTensor stress[8], strain[8];
01198  double  iforce[24];
01199 
01200 /* Initialize the internal forces
01201  */
01202  for( i = 0; i < NumNodes; i++ ) {
01203   if( NodeVector[i].rezone == NONE ) {
01204    if( NodeVector[i].dof.x == FORCE ) F[NDof*i] = NodeVector[i].dof.vpx * Config.loadfactor;
01205    else                               F[NDof*i] = 0.0;
01206 
01207    if( NodeVector[i].dof.y == FORCE ) F[NDof*i+1] = NodeVector[i].dof.vpy * Config.loadfactor;
01208    else                               F[NDof*i+1] = 0.0;
01209 
01210    if( NDof == 3 ) {
01211     if( NodeVector[i].dof.z == FORCE ) F[NDof*i+2] = NodeVector[i].dof.vpz * Config.loadfactor;
01212     else                               F[NDof*i+2] = 0.0;
01213    }
01214   }
01215  }
01216 
01217 /* Loop over the elements
01218  */
01219  for( i = 0; i < NumElements; i++ ) {
01220  /* Check to see if the element was not rezoned
01221   */
01222   if( ElmList[i]->rezone != NONE )
01223    continue;
01224 
01225  /* Compute element stress strain
01226   */
01227   ElmStressStrain( ElmList[i], dtime, U, 0L, stress, strain );
01228 
01229  /* Correct stresses for the larger displacements case
01230   */
01231   if( IsGeomNonLinear && (ElmList[i]->rezone != DONE) )
01232    ElmUpdateStress( ElmList[i], dtime, V, stress );
01233 
01234  /* Compute element internal forces
01235   */
01236   ElmInterForce( ElmList[i], stress, iforce );
01237 
01238  /* Assemble in the global vector
01239   */
01240   ElmAssVector( ElmList[i], F, iforce );
01241  }
01242 
01243 } /* End of InternalForces */
01244 
01245 #else
01246 
01247 /*
01248 %F
01249 */
01250 void InternalForces( double dtime, double *F, double *U, double *V )
01251 {
01252  int     i,j;
01253  sTensor stress[8], strain[8];
01254  double  iforce[24];
01255  /*número de divisões*/
01256  int nd = 10;
01257  int ei[10], ef[10];
01258  int nelm;
01259  double *Faux;
01260  
01261  nelm = NumElements/nd;
01262  
01263  /*elemento inicial e elemento final de cada divisão*/
01264  ei[0] = 0;
01265  ef[0] = nelm;
01266  
01267  for(i = 1; i < (nd-1); i++){
01268   ei[i] = ef[i-1];
01269   ef[i] = ei[i] + nelm;
01270  }
01271  ei[nd-1] = ef[nd-2];
01272  ef[nd-1] = NumElements;
01273  
01274  /*vetor auxiliar. pega o resíduo para cada divisão*/
01275  Faux  = (double *)calloc( NDof*NumNodes, sizeof(double) );
01276 
01277 /* Initialize the internal forces
01278  */
01279  for( i = 0; i < NumNodes; i++ ) {
01280   if( NodeVector[i].rezone == NONE ) {
01281    if( NodeVector[i].dof.x == FORCE ) F[NDof*i] = NodeVector[i].dof.vpx * Config.loadfactor;
01282    else                               F[NDof*i] = 0.0;
01283 
01284    if( NodeVector[i].dof.y == FORCE ) F[NDof*i+1] = NodeVector[i].dof.vpy * Config.loadfactor;
01285    else                               F[NDof*i+1] = 0.0;
01286 
01287    if( NDof == 3 ) {
01288     if( NodeVector[i].dof.z == FORCE ) F[NDof*i+2] = NodeVector[i].dof.vpz * Config.loadfactor;
01289     else                               F[NDof*i+2] = 0.0;
01290    }
01291   }
01292  }
01293  
01294  for( j = 0; j < nd; j++ ) { 
01295  
01296   for( i = 0; i < NDof*NumNodes; i++ ) {
01297    Faux[i] = 0.0;
01298   }
01299  
01300   for( i = ei[j]; i < ef[j]; i++ ) {
01301  /* Loop over the elements
01302   */
01303   /* Check to see if the element was not rezoned
01304    */
01305    if( ElmList[i]->rezone != NONE )
01306     continue;
01307  
01308   /* Compute element stress strain
01309    */
01310    ElmStressStrain( ElmList[i], dtime, U, 0L, stress, strain );
01311  
01312   /* Correct stresses for the larger displacements case
01313    */
01314    if( IsGeomNonLinear && (ElmList[i]->rezone != DONE) )
01315     ElmUpdateStress( ElmList[i], dtime, V, stress );
01316  
01317   /* Compute element internal forces
01318    */
01319    ElmInterForce( ElmList[i], stress, iforce );
01320  
01321   /* Assemble in the global vector
01322    */
01323    ElmAssVector( ElmList[i], Faux, iforce );
01324   }
01325   
01326   for( i = 0; i < NDof*NumNodes; i++ ) {
01327    F[i] += Faux[i];
01328   }
01329  
01330  }
01331  
01332  free(Faux);
01333  
01334 
01335 } /* End of InternalForces */
01336 
01337 #endif
01338 
01339 /*
01340 %F
01341 */
01342 int DisplacementVelocity( int iteration, double alpha, double dtime,
01343                                          double *FVector, double *VVector,
01344                                          double *UVector, double *MVector )
01345 {
01346  int         i, j;
01347  double      a, b, df, disp, veloc;
01348  double      vp[3];
01349  eRestType   dof[3];
01350  
01351  /* Cumpute the auxiliares constantes
01352   */
01353  a = 2.0 - (alpha * dtime);
01354  b = 2.0 + (alpha * dtime);
01355  /*teste adicionado por Gisele*/
01356  pfs_iter = iteration;
01357 
01358  /* Loop over the nodes
01359   */
01360  for( i = 0; i < NumNodes; i++ ) 
01361  {
01362   pfs_node = i;
01363   /* Check to see if the node was not rezoned
01364    */
01365   if( NodeVector[i].rezone != NONE )
01366    continue;
01367 
01368   /* Fill the auxiliare vector for the prescribed value
01369    */
01370   dof[0] = NodeVector[i].dof.x;
01371   dof[1] = NodeVector[i].dof.y;
01372   dof[2] = NodeVector[i].dof.z;
01373   vp[0]  = NodeVector[i].dof.vpx;
01374   vp[1]  = NodeVector[i].dof.vpy;
01375   vp[2]  = NodeVector[i].dof.vpz;
01376 
01377   /* Inicialize total displacement and total velocity
01378    */ 
01379   disp  = 0.0;
01380   veloc = 0.0;
01381 
01382   /* case: node with any constrain */  
01383   if((dof[0] == OBJECT) || (dof[1] == OBJECT) || (dof[2] == OBJECT))
01384   {
01385     /* id node constrain */
01386     int idNodeConst = NodeVector[i].constrain.id - 1;
01387     /* pointer to id element constrain */
01388     void* ConstrElm = &(NodeVector[i].constrain.curr_elm);
01389 
01390     double fl[3];
01391     double vl[3];
01392     double ml = MVector[NDof*i];
01393 
01394     sCoord p;
01395 
01396     if( iteration == 0 ) 
01397     {
01398       if( !ConstToLocal(ConstList[idNodeConst], &NodeVector[i].coord,
01399                         ConstrElm, vp, fl) ) 
01400       {
01401         return 0;
01402       } 
01403 
01404       for(j = 0; j < NDof; j++) 
01405         vl[j] = 0.01 * dtime * (fl[j] / (2.0 * ml));
01406 
01407       if( !ConstToGlobal(ConstList[idNodeConst], &NodeVector[i].coord,
01408                          ConstrElm, vl, &VVector[NDof*i]) )
01409         return 0;
01410 
01411       /* Usado somente para a implementação ESPAÇO PARAMÉTRICO */
01412       for(j = 0; j < NDof; j++) 
01413         UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
01414     }
01415     else
01416     {
01417       /* O ponto p calculado abaixo tem que estar sobre a curva -> ConstList.
01418        * Se nao estiver nao sera possivel: ConstToLocal e ConstToGlobal.
01419        */
01420       p.x = NodeVector[i].coord.x + UVector[NDof*i];
01421       p.y = NodeVector[i].coord.y + UVector[NDof*i+1];
01422       if(NDof == 3) 
01423         p.z = NodeVector[i].coord.z + UVector[NDof*i+2];
01424       else
01425         p.z = 0.0;
01426       if( !ConstToLocal(ConstList[idNodeConst], &p, ConstrElm,
01427                         &FVector[NDof*i], fl) ) return 0;
01428       if( !ConstToLocal(ConstList[idNodeConst], &p, ConstrElm,
01429                         &VVector[NDof*i], vl) ) return 0;
01430       /* Integração.
01431        */
01432       for(j = 0; j < NDof; j++) 
01433         vl[j] = ((a / b) * vl[j]) + (2.0 * dtime * (fl[j] / (b * ml)));
01434 
01435       /* Projetando as grandezas no elemento corrente da restricao
01436        */
01437       fl[2] = vl[2] = 0.0;
01438       if(NDof <= 2)
01439         fl[1] = vl[1] = 0.0;
01440 
01441       {
01442         double UVecPrev[3];   /* UVector no passo anterior.             */
01443         sCoord pl;            /* Ponto sobre a restrição.               */
01444         sCoord delta_u;       /* deslocamento no elemento da restrição. */
01445 
01446         /* Calcula o deslocamento ("delta") no espaço paramétrico.
01447          */
01448         delta_u.x = dtime * vl[0];
01449 
01450         if(NDof == 3)
01451           delta_u.y = dtime * vl[1];
01452         else
01453           delta_u.y = 0.0;       /* dtime * vl[1] */
01454 
01455         delta_u.z = 0.0;         /* dtime * vl[2] */
01456            
01457         if( !ConstSlide(ConstList[idNodeConst], &p, ConstrElm, 
01458                         &delta_u, vl, &VVector[NDof*i], &pl) ) 
01459         {
01460          /* ERROR */
01461           printf( "DisplacementVelocity: Node didn't slide\n" );
01462          
01463         }
01464 
01465         /* Guarda o UVector antes de atualizar ele para atualizar o 
01466          * VVector.
01467          */
01468         for(j = 0; j < NDof; j++) 
01469           UVecPrev[j] = UVector[NDof*i+j];
01470 
01471         /* Calcula o UVector. 
01472          */
01473         UVector[NDof*i]   = pl.x - NodeVector[i].coord.x;
01474         UVector[NDof*i+1] = pl.y - NodeVector[i].coord.y; 
01475         if(NDof == 3) 
01476           UVector[NDof*i+2] = pl.z - NodeVector[i].coord.z; 
01477 
01478         /* Calcula o VVector.
01479          */    
01480         for(j = 0; j < NDof; j++) 
01481           VVector[NDof*i+j] = (UVector[NDof*i+j] - UVecPrev[j]) / dtime;
01482       }
01483     }
01484   }
01485 
01486  /* Loop over the D.O.F. for each node
01487   */
01488   for( j = 0; j < NDof; j++ ) {
01489   /* Check the D.O.F. condition
01490    */
01491    if(MVector[NDof*i+j] != 0.0){
01492            
01493     switch( dof[j] ) {
01494      case FORCE:
01495       if( iteration == 0 )
01496        df = vp[j];
01497       else
01498        df = FVector[NDof*i+j];
01499     
01500       if( iteration == 0 )
01501         VVector[NDof*i+j] = 0.01 * dtime * (df / (2.0 * MVector[NDof*i+j]));
01502       else
01503         VVector[NDof*i+j] = ((a / b) * VVector[NDof*i+j]) +
01504                            (2.0 * dtime * (df / (b * MVector[NDof*i+j])));
01505     
01506       UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
01507       break;
01508     
01509      case DISPLACEMENT:
01510       VVector[NDof*i+j] = 0.0;
01511       UVector[NDof*i+j] = vp[j] * Config.loadfactor;
01512       /* Com o nó piloto. */
01513       if(iteration == 0)
01514       {
01515         /* O nó tem que estar sobre uma das restrições.
01516          */
01517         if(NodeVector[i].constrain.id) 
01518         {
01519           /* O nó não pode ser o nó piloto.
01520            */
01521           if(!NodeVector[i].pilot) 
01522           {
01523             NodeVector[i].dof.x = OBJECT;
01524             NodeVector[i].dof.y = OBJECT;
01525             NodeVector[i].dof.z = OBJECT;
01526           }
01527         }
01528       }
01529       break;
01530     
01531      case VELOCITY:
01532       VVector[NDof*i+j]  = vp[j];
01533       UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
01534       break;
01535     
01536      default:
01537       break;
01538     }
01539    }
01540 
01541    if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 0) )
01542     disp += (UVector[NDof*i+j] * UVector[NDof*i+j]);
01543    else if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 1) )
01544     veloc += (VVector[NDof*i+j] * VVector[NDof*i+j]);
01545   }
01546 
01547   if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 0) )
01548    XGPSendPoint( NodeVector[i].curve, (double)iteration, sqrt( disp ) );
01549   else if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 1) )
01550    XGPSendPoint( NodeVector[i].curve, (double)iteration, sqrt( veloc ) );
01551  }
01552    return 1;
01553 } /* End of DisplacementVelocity */
01554 
01555 
01556 /*
01557 %F This function computes the mass vector for the model.
01558 */
01559 void MassVector( double *MVector )
01560 {
01561  int    i;
01562  double mass[24];
01563 
01564 /* Initialize the mass vector
01565  */
01566  for( i = 0; i < NDof*NumNodes; i++ )
01567   MVector[i] = 0.0;
01568 
01569 /* Loop over the elements
01570  */
01571  for( i = 0; i < NumElements; i++ ) {
01572  /* Check to see if the element was rezoned
01573   */
01574   if( ElmList[i]->rezone == DONE )
01575    continue;
01576 
01577  /* Compute the element mass matrix
01578   */
01579   ElmMass( ElmList[i], mass );
01580 
01581  /* Assemble in to the global vector
01582   */
01583   ElmAssVector( ElmList[i], MVector, mass );
01584  }
01585 
01586 } /* End of MassVector */
01587 
01588 
01589 /*
01590 %F
01591 */
01592 int DoRezone( int step, double *FVector )
01593 {
01594  int i, j, id, numnodes;
01595  int inc[8];
01596 
01597 /* Check to see if the rezone descriptor exists
01598  */
01599  if( Rezone == 0L )
01600   return( 0 );
01601 
01602 /* Update element rezone status for the current step
01603  */
01604  for( i = 0; i < Rezone[step-1].numelm; i++ ) {
01605   id = Rezone[step-1].elm[i] - 1;
01606   if( ElmList[id]->rezone == NONE ) ElmList[id]->rezone = TODO;
01607   else                              ElmList[id]->rezone = DONE;
01608  }
01609 
01610 /* Update node flag
01611  */
01612  for( i = 0; i < NumNodes; i++ )
01613   NodeVector[i].rezone = DONE;
01614 
01615  for( i = 0; i < NumElements; i++ ) {
01616   if( ElmList[i]->rezone == NONE ) {
01617    ElmConnect( ElmList[i], inc );
01618    ElmNumNodes( ElmList[i], &numnodes );
01619    for( j = 0; j < numnodes; j++ )
01620     NodeVector[inc[j]-1].rezone = NONE;
01621   }
01622  }
01623 
01624 /* Update prescribed values
01625  */
01626  UpdatePrescribedValues( FVector );
01627 
01628 /* Set element rezone state to DONE
01629  */
01630  for( i = 0; i < NumElements; i++ )
01631   if( ElmList[i]->rezone == TODO )
01632    ElmList[i]->rezone = DONE;
01633 
01634  return( 1 );
01635 
01636 } /* End of DoRezone */
01637 
01638 
01639 /*
01640 %F
01641 */
01642 void PercolationForces( double *F )
01643 {
01644  int    i;
01645  double pforce[24];
01646 
01647 /* Loop over the elements
01648  */
01649  for( i = 0; i < NumElements; i++ ) {
01650  /* Check to see if the element was not rezoned
01651   */
01652   if( ElmList[i]->rezone != NONE )
01653    continue;
01654 
01655  /* Compute element percolation forces
01656   */
01657   ElmPercForce( ElmList[i], pforce );
01658 
01659  /* Assemble in the global vector
01660   */
01661   ElmAssVector( ElmList[i], F, pforce );
01662  }
01663 
01664 } /* End of PercolationForces */
01665 
01666 
01667 /* =======================================================  End of File  */
01668 

Generated on Fri Oct 5 15:54:14 2007 for ReconMS by  doxygen 1.5.1