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 
00111 #ifdef USE_SAMG
00112   #include "solversamg.h"
00113 #endif
00114 
00115 
00116 
00117 /*
00118 ** ------------------------------------------------------------------------
00119 ** Local variables and symbols:
00120 */
00121 #ifndef maxcor
00122 #define maxcor 30
00123 #endif
00124 
00125 #ifndef maxiter
00126 #define maxiter 5000
00127 #endif
00128 
00129 #ifndef cgtol
00130 #define cgtol 1.0e-10
00131 #endif
00132 
00133 #ifndef ngr
00134 #define ngr 10e20
00135 #endif
00136 
00137 
00138 /*
00139 ** ------------------------------------------------------------------------
00140 ** Local functions:
00141 */
00142 static void ElmKpr(double *, int *, double *);
00143 static void ElmKp(double *, double *, int *, int *, double *);
00144 static void GCSolver(double *, double *, int *, int *, double *);
00145 static void SearchDirection(int i, int k, double *vector, double **w, double **v,
00146                             int nna, int nnu, int *ia, int *ja, double *avector); 
00147 
00148 /*
00149 ** ------------------------------------------------------------------------
00150 ** Local functions:
00151 */
00152 
00153 /*
00154 %F
00155 */
00156 static void SearchDirection(int i, int k, double *vector, double **w, double **v,
00157                             int nna, int nnu, int *ia, int *ja, double *avector)
00158 {
00159 /*
00160 Essa função calcula a direção de busca para
00161 o método BFGS
00162 */      
00163   int n;
00164   int j;
00165   int m;
00166   double a;
00167   double *b;
00168   int    matrix = 12;
00169   int    iversion = 4;
00170   int    nsys = 1;
00171   int    npnt = 0;
00172   
00173   n=0;
00174   a=0.0;
00175   m=k;
00176 
00177   b =  (double*)malloc(i*sizeof(double)); 
00178 
00179   for (j = 0; j < i; j++){
00180    a += w[j][m]*vector[j];
00181   }
00182   for (j = 0; j < i; j++){
00183    b[j] = vector[j]+v[j][m]*a;
00184   }
00185   for (j = 0; j < i; j++){
00186    vector[j] = b[j];
00187   }
00188   while(m>0){
00189    m -=1;
00190    a=0.0;
00191    for (j = 0; j < i; j++){
00192     a += w[j][m]*vector[j];
00193    }
00194    for (j = 0; j < i; j++){
00195     b[j] = vector[j]+v[j][m]*a;
00196    }
00197    for (j = 0; j < i; j++){
00198     vector[j] = b[j];
00199    }
00200   }
00201 
00202   if(Config.solver == 0){
00203 
00204    /* usa o método do gradiente conjugado
00205    */
00206    GCSolver(b, vector, ia, ja, avector);
00207   
00208   }
00209   else{
00210  
00211    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
00212    #ifdef USE_SAMG
00213     SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, b, vector );
00214    #endif
00215   }
00216   
00217   a=0.0;
00218   for (j = 0; j < i; j++){
00219    a += v[j][n]*vector[j];
00220   }
00221   for (j = 0; j < i; j++){
00222    b[j] = vector[j]+w[j][n]*a;
00223   }
00224   for (j = 0; j < i; j++){
00225    vector[j] = b[j];
00226   }
00227   while(n<k){
00228    n +=1;
00229    a=0.0;
00230    for (j = 0; j < i; j++){
00231     a += v[j][n]*vector[j];
00232    }
00233    for (j = 0; j < i; j++){
00234     b[j] = vector[j]+w[j][n]*a;
00235    }
00236    for (j = 0; j < i; j++){
00237     vector[j] = b[j];
00238    }
00239   }
00240   free ( b );
00241 }
00242 
00243 
00244 /*
00245 %F
00246 */
00247 static void ElmKpr(double *Kp, int *ia, double *avector)
00248 {
00249  int     i;           
00250 
00251  for( i = 0; i < NumNodes * NDof; i++ ){         
00252   Kp[i] = avector[ia[i]];
00253  }
00254 }
00255 
00256 /*
00257 %F
00258 */
00259 static void ElmKp(double *d, double *p, int *ia, int *ja, double *avector)
00260 {
00261  int     i,j,k,l,m;           
00262 
00263  for( i = 0; i < NumNodes * NDof; i++ ){  
00264   j = ia[i];
00265   l = ia[i+1];  
00266   for (k = j; k < l; k++){
00267    m=ja[k]; 
00268    d[i] += avector[k] * p[m];
00269   }
00270  }
00271 }
00272 
00273 /*
00274 %F
00275 */
00276 static void GCSolver(double *R, double *u, int *ia, int *ja, double *avector)
00277 {
00278  int    i,j,m;                      
00279  double alpha,beta,a,b;                
00280  double *rn,*p,*d,*Kp,*z;
00281  double error;
00282  int    iter;
00283  
00284  m = NumNodes * NDof;
00285  
00286  rn =  (double*)malloc(m*sizeof(double));
00287  p  =  (double*)malloc(m*sizeof(double));
00288  d  =  (double*)malloc(m*sizeof(double));
00289  Kp =  (double*)malloc(m*sizeof(double));
00290  z  =  (double*)malloc(m*sizeof(double));
00291  
00292  for( i = 0; i < m; i++ ){
00293   Kp[i] = 0.0;
00294  }
00295  
00296  /* monta matriz de precondicionamento diagonal
00297  */
00298  ElmKpr(Kp,ia,avector);
00299  
00300  for( i = 0; i < NumNodes; i++ ){
00301   if( NodeVector[i].dof.x == DISPLACEMENT ){
00302    Kp[NDof*i]+= ngr;
00303   }
00304   if( NodeVector[i].dof.y == DISPLACEMENT ){
00305    Kp[NDof*i+1]+= ngr;
00306   }
00307   if( NDof == 3 ) {
00308    if( NodeVector[i].dof.z == DISPLACEMENT ){
00309     Kp[NDof*i+2]+= ngr;
00310    }
00311   }
00312  }      
00313  
00314  for( j = 0; j < m; j++ ){
00315   if(Kp[j] != 0.0){
00316    Kp[j] = 1.0/Kp[j];
00317   }
00318   else{
00319    Kp[j] = 1.0;
00320   }
00321   rn[j] = R[j];
00322   z[j] = p[j] = Kp[j]*rn[j];
00323   d[j] = u[j] = 0.0;
00324  }
00325  
00326  error = 1.0; iter = 0;
00327  
00328  while((error>=cgtol)&&(iter<maxiter)){
00329   iter ++;
00330   
00331   error = 0.0;
00332   
00333   ElmKp(d,p,ia,ja,avector);
00334   
00335   for( i = 0; i < NumNodes; i++ ){
00336    if( NodeVector[i].dof.x == DISPLACEMENT ){
00337     d[NDof*i] = ngr*p[NDof*i];
00338    }
00339    if( NodeVector[i].dof.y == DISPLACEMENT ){
00340     d[NDof*i+1] = ngr*p[NDof*i+1];
00341    }
00342    if( NDof == 3 ) {
00343     if( NodeVector[i].dof.z == DISPLACEMENT ){
00344      d[NDof*i+2] = ngr*p[NDof*i+2];
00345     }
00346    }
00347   }
00348   
00349   a = b = 0.0;
00350   
00351   for (j = 0; j < m; j++){
00352    a+= z[j]*rn[j]; 
00353    b+= p[j]*d[j];
00354   }
00355   
00356   alpha = a/b;
00357   a = b = 0.0;
00358   
00359   for( j = 0; j < m; j++ ){
00360    u[j]+= alpha*p[j];
00361    rn[j]= R[j]-alpha*d[j];
00362    b+= z[j]*R[j];
00363    z[j]= Kp[j]*rn[j];
00364    a+= z[j]*rn[j];
00365   }
00366   
00367   beta=a/b;
00368   
00369   for( j = 0; j < m; j++ ){
00370    p[j]= z[j]+beta*p[j];
00371    R[j]= rn[j]; 
00372    d[j]= 0.0;
00373    error+= rn[j]*rn[j];
00374   }
00375   
00376   error=sqrt(error);
00377   
00378  }
00379  
00380  free ( rn );
00381  free ( p  );
00382  free ( d  );
00383  free ( Kp );
00384  free ( z  );
00385 }
00386 
00387 /*
00388 ** ------------------------------------------------------------------------
00389 ** Public functions:
00390 */
00391 
00392 /*
00393 %F
00394 */
00395 void BuildAVector( int *ia, int *ja, double *avector )
00396 {
00397  int    i,j,k,l,elm;                      
00398  double ke[24][24];
00399  int    u[24];
00400  int    index;
00401  
00402  /* monta matriz de rigidez dos elementos
00403     no formato csr
00404  */
00405  for( elm = 0; elm < NumElements; elm++ ){
00406   /* pega os graus de liberdade do elemento
00407   */
00408   ElmGetDof( ElmList[elm], u, &index );
00409   /* monta matriz de rigidez do elemento
00410   */
00411   ElmKMatrix( ElmList[elm], ke );
00412   /* coloca os termos da matriz do elemento
00413      no vetor de coeficientes avector
00414   */
00415   for(i = 0; i < index; i++){
00416    for(j = 0; j < index; j++){
00417     k = u[i];  
00418     l = u[j];
00419     BuildaVector( k, l, ke[i][j], ia, ja, avector );
00420    }
00421   }
00422  }
00423  /* aplica condições de contorno em avector
00424  */
00425  for( i = 0; i < NumNodes; i++ ){
00426   if( NodeVector[i].dof.x == DISPLACEMENT ){
00427    avector[ia[NDof*i]]+= ngr;
00428   }
00429   if( NodeVector[i].dof.y == DISPLACEMENT ){
00430    avector[ia[NDof*i+1]]+= ngr;
00431   }
00432   if( NDof == 3 ) {
00433    if( NodeVector[i].dof.z == DISPLACEMENT ){
00434     avector[ia[NDof*i+2]]+= ngr;
00435    }
00436   }
00437  }
00438 }       
00439 
00440 
00441 /*
00442 %F
00443 */
00444 void BFGS(double dtime, double *F, double *U, double *V,
00445           int *iteration, double *error, double error0, int loadstep,
00446           int nna, int nnu, int *ia, int *ja, double *avector )
00447 {
00448 /*
00449 Essa função busca minimizar o vetor resíduo
00450 com o método BFGS
00451 */
00452   int    i,j,k,n;
00453   double vp[3];
00454   eRestType dof[3];                     
00455   double b, c;                                                 
00456   double *q, *F0;
00457   double **w, **v;
00458   int    needite;
00459   int    stop = 0;
00460   int    matrix = 12;
00461   int    iversion = 4;
00462   int    nsys = 1;
00463   int    npnt = 0;
00464   
00465   n = NumNodes*NDof;
00466   
00467   q  = (double*)malloc(n*sizeof(double));
00468   F0 = (double*)malloc(n*sizeof(double));
00469   w  = (double**)malloc(n*sizeof(double*));
00470   v  = (double**)malloc(n*sizeof(double*));
00471   for(i=0; i < n; i++){
00472    w[i] = (double*)malloc(maxcor*sizeof(double));
00473    v[i] = (double*)malloc(maxcor*sizeof(double));
00474   }
00475  
00476   for( i = 0; i < NumNodes; i++ ) {
00477    dof[0] = NodeVector[i].dof.x;
00478    dof[1] = NodeVector[i].dof.y;
00479    dof[2] = NodeVector[i].dof.z;
00480    vp[0]  = NodeVector[i].dof.vpx;
00481    vp[1]  = NodeVector[i].dof.vpy;
00482    vp[2]  = NodeVector[i].dof.vpz;
00483    for( j = 0; j < NDof; j++ ) {
00484    /* Verifica a condição de contorno de deslocamento
00485     */
00486     if(dof[j] == DISPLACEMENT){
00487      U[NDof*i+j] = vp[j] * Config.loadfactor;
00488     }
00489    }
00490   }
00491  
00492   /* Calcula o vetor de forças desequilibradas
00493   */
00494   InternalForces( dtime, F, U, V );
00495 
00496   for( j = 0; j < n; j++ ){
00497    q[j] = F0[j] = V[j] = F[j];
00498   }
00499   k=0; 
00500  
00501   /* Calcula o vetor de incrementos de deslocamentos
00502   */
00503   if(Config.solver == 0){
00504 
00505    /* usa o método do gradiente conjugado
00506    */
00507    GCSolver(F, V, ia, ja, avector);
00508    
00509   }
00510   else{
00511  
00512    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
00513    #ifdef USE_SAMG
00514     SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
00515    #endif
00516   }
00517   
00518   *error = Config.tolerance;  needite   = 0;
00519   
00520   do {
00521    /* atualiza o vetor de deslocamentos
00522    */
00523    for( i = 0; i < NumNodes; i++ ) {
00524     U[NDof*i]   +=  V[NDof*i];    
00525     U[NDof*i+1] +=  V[NDof*i+1];  
00526     if( NDof == 3 ) {
00527      U[NDof*i+2] += V[NDof*i+2];  
00528     }
00529    }
00530    
00531    /* Calcula o vetor de forças desequilibradas
00532    */
00533    InternalForces( dtime, F, U, V); 
00534    
00535    *error = ComputeError( F, V, error0 );
00536   
00537    if( _count_it != NULL )
00538     (*_count_it) ( *iteration, *error, loadstep); 
00539     
00540    if( _fstop != NULL )
00541      (*_fstop) ( &stop ); 
00542      
00543    /* Check for another iteration
00544    */
00545    needite = NeedIteration( error, iteration, stop );
00546    
00547    printf( "\tStep: %d             Error: %5.3E\r", *iteration, *error );
00548    
00549    if(!needite) break;
00550    if(*error < Config.tolerance) break;
00551 
00552    b=c=0.0;
00553    for (j = 0; j < n; j++){
00554     q[j] -= F[j];
00555     b += V[j]*q[j];
00556     c += V[j]*F0[j];
00557    }
00558    for (j = 0; j < n; j++){
00559     v[j][k]= -(pow(fabs(b/c),0.5))*F0[j]-q[j];   
00560     w[j][k]= V[j]/b;                            
00561     V[j] = q[j] = F0[j] = F[j];
00562    }
00563    /* calcula a direção de busca*/
00564    SearchDirection(n, k, V, w, v, nna, nnu, ia, ja, avector);    
00565    k ++;
00566    if( k == maxcor ) k = 0;
00567   }while( needite); 
00568  
00569   free ( q );
00570   free ( F0 );
00571   for(i=0; i < n; i++){
00572    free( w[i] );
00573    free( v[i] );
00574   }
00575   free( w ); 
00576   free( v );    
00577  
00578 }
00579 
00580 /*
00581 %F
00582 */
00583 void NRM(double dtime, double *F, double *U, double *V,
00584          int *iteration, double *error, double error0, int loadstep,
00585          int nna, int nnu, int *ia, int *ja, double *avector )
00586 {
00587 /*
00588 Essa função busca minimizar o vetor resíduo
00589 com o método NRM
00590 */
00591   int    i,j,n;
00592   double vp[3];
00593   eRestType dof[3];                       
00594   int    needite = 0;
00595   int    stop = 0;
00596   int    matrix = 12;
00597   int    iversion = 4;
00598   int    nsys = 1;
00599   int    npnt = 0;
00600   
00601   n = NumNodes*NDof;
00602   
00603   do {
00604         
00605    for( i = 0; i < NumNodes; i++ ) {
00606     dof[0] = NodeVector[i].dof.x;
00607     dof[1] = NodeVector[i].dof.y;
00608     dof[2] = NodeVector[i].dof.z;
00609     vp[0]  = NodeVector[i].dof.vpx;
00610     vp[1]  = NodeVector[i].dof.vpy;
00611     vp[2]  = NodeVector[i].dof.vpz;
00612     for( j = 0; j < NDof; j++ ) {
00613     /* Verifica a condição de contorno de deslocamento
00614      */
00615      if(dof[j] == DISPLACEMENT){
00616       U[NDof*i+j] = vp[j] * Config.loadfactor;
00617      }
00618     }
00619    }
00620  
00621    /* Calcula o vetor de forças desequilibradas
00622    */
00623    InternalForces( dtime, F, U, V );
00624 
00625    for( j = 0; j < n; j++ ){
00626     V[j] = F[j];
00627    }
00628  
00629    /* Calcula o vetor de incrementos de deslocamentos
00630    */
00631   if(Config.solver == 0){
00632 
00633    /* usa o método do gradiente conjugado
00634    */
00635    GCSolver(F, V, ia, ja, avector);
00636   
00637   }
00638   else{
00639  
00640    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
00641    #ifdef USE_SAMG
00642     SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
00643    #endif
00644   }
00645  
00646    /* atualiza o vetor de deslocamentos
00647    */
00648    for( i = 0; i < NumNodes; i++ ) {
00649     U[NDof*i]   +=  V[NDof*i];    
00650     U[NDof*i+1] +=  V[NDof*i+1];  
00651     if( NDof == 3 ) {
00652      U[NDof*i+2] += V[NDof*i+2];  
00653     }
00654    }
00655    
00656    /* Calcula o vetor de forças desequilibradas
00657    */
00658    InternalForces( dtime, F, U, V); 
00659    
00660    *error = ComputeError( F, V, error0 );
00661   
00662    if( _count_it != NULL )
00663     (*_count_it) ( *iteration, *error, loadstep); 
00664     
00665    if( _fstop != NULL )
00666      (*_fstop) ( &stop ); 
00667      
00668    /* Check for another iteration
00669    */
00670    needite = NeedIteration( error, iteration, stop );
00671    
00672    printf( "\tStep: %d             Error: %5.3E\r", *iteration, *error );            
00673                  
00674   }while(needite); 
00675  
00676 }
00677 
00678 /*
00679 %F
00680 */
00681 void LINEAR(double dtime, double *F, double *U, double *V,
00682             int *iteration, double *error, double error0, int loadstep,
00683             int nna, int nnu, int *ia, int *ja, double *avector )
00684 {
00685   int    i,j;
00686   double vp[3];
00687   eRestType dof[3];                     
00688   int    stop = 0;
00689   int    matrix = 12;
00690   int    iversion = 4;
00691   int    nsys = 1;
00692   int    npnt = 0;
00693  
00694   for( i = 0; i < NumNodes; i++ ) {
00695    dof[0] = NodeVector[i].dof.x;
00696    dof[1] = NodeVector[i].dof.y;
00697    dof[2] = NodeVector[i].dof.z;
00698    vp[0]  = NodeVector[i].dof.vpx;
00699    vp[1]  = NodeVector[i].dof.vpy;
00700    vp[2]  = NodeVector[i].dof.vpz;
00701    for( j = 0; j < NDof; j++ ) {
00702    /* Verifica a condição de contorno de deslocamento
00703     */
00704     if(dof[j] == DISPLACEMENT){
00705      U[NDof*i+j] = vp[j] * Config.loadfactor;
00706     }
00707    }
00708   }
00709  
00710   /* Calcula o vetor de forças desequilibradas
00711   */
00712   InternalForces( dtime, F, U, V );
00713   
00714   for( j = 0; j < NumNodes*NDof; j++ ){
00715    V[j] = F[j];
00716   }
00717  
00718   /* Calcula o vetor de incrementos de deslocamentos
00719   */
00720   if(Config.solver == 0){
00721 
00722    /* usa o método do gradiente conjugado
00723    */
00724    GCSolver(F, V, ia, ja, avector);
00725    
00726   }
00727   else{
00728   
00729    /* chama o solver Samg para calcular o incremento dos deslocamentos*/
00730    #ifdef USE_SAMG
00731     SamgSolver( iversion, nna, nnu, matrix, nsys, npnt, ia, ja, avector, F, V );
00732    #endif
00733   }
00734  
00735   /* atualiza o vetor de deslocamentos
00736   */
00737   for( i = 0; i < NumNodes; i++ ) {
00738    U[NDof*i]   +=  V[NDof*i];    
00739    U[NDof*i+1] +=  V[NDof*i+1];  
00740    if( NDof == 3 ) {
00741     U[NDof*i+2] += V[NDof*i+2];  
00742    }
00743   }
00744   
00745   /* Calcula o vetor de forças desequilibradas
00746    */
00747   InternalForces( dtime, F, U, V); 
00748    
00749   *error = ComputeError( F, V, error0 );
00750   
00751   if( _count_it != NULL )
00752     (*_count_it) ( *iteration, *error, loadstep); 
00753     
00754   if( _fstop != NULL )
00755      (*_fstop) ( &stop );
00756 
00757 }
00758 
00759 /*
00760 %F
00761 */
00762 void InternalForces( double dtime, double *F, double *U, double *V )
00763 {
00764  int     i;
00765  sTensor stress[8], strain[8];
00766  double  iforce[24];
00767 
00768 /* Initialize the internal forces
00769  */
00770  for( i = 0; i < NumNodes; i++ ) {
00771   if( NodeVector[i].rezone == NONE ) {
00772    if( NodeVector[i].dof.x == FORCE ) F[NDof*i] = NodeVector[i].dof.vpx * Config.loadfactor;
00773    else                               F[NDof*i] = 0.0;
00774 
00775    if( NodeVector[i].dof.y == FORCE ) F[NDof*i+1] = NodeVector[i].dof.vpy * Config.loadfactor;
00776    else                               F[NDof*i+1] = 0.0;
00777 
00778    if( NDof == 3 ) {
00779     if( NodeVector[i].dof.z == FORCE ) F[NDof*i+2] = NodeVector[i].dof.vpz * Config.loadfactor;
00780     else                               F[NDof*i+2] = 0.0;
00781    }
00782   }
00783  }
00784 
00785 /* Loop over the elements
00786  */
00787  for( i = 0; i < NumElements; i++ ) {
00788  /* Check to see if the element was not rezoned
00789   */
00790   if( ElmList[i]->rezone != NONE )
00791    continue;
00792 
00793  /* Compute element stress strain
00794   */
00795   ElmStressStrain( ElmList[i], dtime, U, 0L, stress, strain );
00796 
00797  /* Correct stresses for the larger displacements case
00798   */
00799   if( IsGeomNonLinear && (ElmList[i]->rezone != DONE) )
00800    ElmUpdateStress( ElmList[i], dtime, V, stress );
00801 
00802  /* Compute element internal forces
00803   */
00804   ElmInterForce( ElmList[i], stress, iforce );
00805 
00806  /* Assemble in the global vector
00807   */
00808   ElmAssVector( ElmList[i], F, iforce );
00809  }
00810 
00811 } /* End of InternalForces */
00812 
00813 /*
00814 %F
00815 */
00816 int DisplacementVelocity( int iteration, double alpha, double dtime,
00817                                          double *FVector, double *VVector,
00818                                          double *UVector, double *MVector )
00819 {
00820  int         i, j;
00821  double      a, b, df, disp, veloc;
00822  double      vp[3];
00823  eRestType   dof[3];
00824  
00825  /* Cumpute the auxiliares constantes
00826   */
00827  a = 2.0 - (alpha * dtime);
00828  b = 2.0 + (alpha * dtime);
00829  /*teste adicionado por Gisele*/
00830  pfs_iter = iteration;
00831 
00832  /* Loop over the nodes
00833   */
00834  for( i = 0; i < NumNodes; i++ ) 
00835  {
00836   pfs_node = i;
00837   /* Check to see if the node was not rezoned
00838    */
00839   if( NodeVector[i].rezone != NONE )
00840    continue;
00841 
00842   /* Fill the auxiliare vector for the prescribed value
00843    */
00844   dof[0] = NodeVector[i].dof.x;
00845   dof[1] = NodeVector[i].dof.y;
00846   dof[2] = NodeVector[i].dof.z;
00847   vp[0]  = NodeVector[i].dof.vpx;
00848   vp[1]  = NodeVector[i].dof.vpy;
00849   vp[2]  = NodeVector[i].dof.vpz;
00850 
00851   /* Inicialize total displacement and total velocity
00852    */ 
00853   disp  = 0.0;
00854   veloc = 0.0;
00855 
00856   /* case: node with any constrain */  
00857   if((dof[0] == OBJECT) || (dof[1] == OBJECT) || (dof[2] == OBJECT))
00858   {
00859     /* id node constrain */
00860     int idNodeConst = NodeVector[i].constrain.id - 1;
00861     /* pointer to id element constrain */
00862     void* ConstrElm = &(NodeVector[i].constrain.curr_elm);
00863 
00864     double fl[3];
00865     double vl[3];
00866     double ml = MVector[NDof*i];
00867 
00868     sCoord p;
00869 
00870     if( iteration == 0 ) 
00871     {
00872       if( !ConstToLocal(ConstList[idNodeConst], &NodeVector[i].coord,
00873                         ConstrElm, vp, fl) ) 
00874       {
00875         return 0;
00876       } 
00877 
00878       for(j = 0; j < NDof; j++) 
00879         vl[j] = 0.01 * dtime * (fl[j] / (2.0 * ml));
00880 
00881       if( !ConstToGlobal(ConstList[idNodeConst], &NodeVector[i].coord,
00882                          ConstrElm, vl, &VVector[NDof*i]) )
00883         return 0;
00884 
00885       /* Usado somente para a implementação ESPAÇO PARAMÉTRICO */
00886       for(j = 0; j < NDof; j++) 
00887         UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
00888     }
00889     else
00890     {
00891       /* O ponto p calculado abaixo tem que estar sobre a curva -> ConstList.
00892        * Se nao estiver nao sera possivel: ConstToLocal e ConstToGlobal.
00893        */
00894       p.x = NodeVector[i].coord.x + UVector[NDof*i];
00895       p.y = NodeVector[i].coord.y + UVector[NDof*i+1];
00896       if(NDof == 3) 
00897         p.z = NodeVector[i].coord.z + UVector[NDof*i+2];
00898       else
00899         p.z = 0.0;
00900       if( !ConstToLocal(ConstList[idNodeConst], &p, ConstrElm,
00901                         &FVector[NDof*i], fl) ) return 0;
00902       if( !ConstToLocal(ConstList[idNodeConst], &p, ConstrElm,
00903                         &VVector[NDof*i], vl) ) return 0;
00904       /* Integração.
00905        */
00906       for(j = 0; j < NDof; j++) 
00907         vl[j] = ((a / b) * vl[j]) + (2.0 * dtime * (fl[j] / (b * ml)));
00908 
00909       /* Projetando as grandezas no elemento corrente da restricao
00910        */
00911       fl[2] = vl[2] = 0.0;
00912       if(NDof <= 2)
00913         fl[1] = vl[1] = 0.0;
00914 
00915       {
00916         double UVecPrev[3];   /* UVector no passo anterior.             */
00917         sCoord pl;            /* Ponto sobre a restrição.               */
00918         sCoord delta_u;       /* deslocamento no elemento da restrição. */
00919 
00920         /* Calcula o deslocamento ("delta") no espaço paramétrico.
00921          */
00922         delta_u.x = dtime * vl[0];
00923 
00924         if(NDof == 3)
00925           delta_u.y = dtime * vl[1];
00926         else
00927           delta_u.y = 0.0;       /* dtime * vl[1] */
00928 
00929         delta_u.z = 0.0;         /* dtime * vl[2] */
00930            
00931         if( !ConstSlide(ConstList[idNodeConst], &p, ConstrElm, 
00932                         &delta_u, vl, &VVector[NDof*i], &pl) ) 
00933         {
00934          /* ERROR */
00935           printf( "DisplacementVelocity: Node didn't slide\n" );
00936          
00937         }
00938 
00939         /* Guarda o UVector antes de atualizar ele para atualizar o 
00940          * VVector.
00941          */
00942         for(j = 0; j < NDof; j++) 
00943           UVecPrev[j] = UVector[NDof*i+j];
00944 
00945         /* Calcula o UVector. 
00946          */
00947         UVector[NDof*i]   = pl.x - NodeVector[i].coord.x;
00948         UVector[NDof*i+1] = pl.y - NodeVector[i].coord.y; 
00949         if(NDof == 3) 
00950           UVector[NDof*i+2] = pl.z - NodeVector[i].coord.z; 
00951 
00952         /* Calcula o VVector.
00953          */    
00954         for(j = 0; j < NDof; j++) 
00955           VVector[NDof*i+j] = (UVector[NDof*i+j] - UVecPrev[j]) / dtime;
00956       }
00957     }
00958   }
00959 
00960  /* Loop over the D.O.F. for each node
00961   */
00962   for( j = 0; j < NDof; j++ ) {
00963   /* Check the D.O.F. condition
00964    */
00965    if(MVector[NDof*i+j] != 0.0){
00966            
00967     switch( dof[j] ) {
00968      case FORCE:
00969       if( iteration == 0 )
00970        df = vp[j];
00971       else
00972        df = FVector[NDof*i+j];
00973     
00974       if( iteration == 0 )
00975         VVector[NDof*i+j] = 0.01 * dtime * (df / (2.0 * MVector[NDof*i+j]));
00976       else
00977         VVector[NDof*i+j] = ((a / b) * VVector[NDof*i+j]) +
00978                            (2.0 * dtime * (df / (b * MVector[NDof*i+j])));
00979     
00980       UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
00981       break;
00982     
00983      case DISPLACEMENT:
00984       VVector[NDof*i+j] = 0.0;
00985       UVector[NDof*i+j] = vp[j] * Config.loadfactor;
00986       /* Com o nó piloto. */
00987       if(iteration == 0)
00988       {
00989         /* O nó tem que estar sobre uma das restrições.
00990          */
00991         if(NodeVector[i].constrain.id) 
00992         {
00993           /* O nó não pode ser o nó piloto.
00994            */
00995           if(!NodeVector[i].pilot) 
00996           {
00997             NodeVector[i].dof.x = OBJECT;
00998             NodeVector[i].dof.y = OBJECT;
00999             NodeVector[i].dof.z = OBJECT;
01000           }
01001         }
01002       }
01003       break;
01004     
01005      case VELOCITY:
01006       VVector[NDof*i+j]  = vp[j];
01007       UVector[NDof*i+j] += dtime * VVector[NDof*i+j];
01008       break;
01009     
01010      default:
01011       break;
01012     }
01013    }
01014 
01015    if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 0) )
01016     disp += (UVector[NDof*i+j] * UVector[NDof*i+j]);
01017    else if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 1) )
01018     veloc += (VVector[NDof*i+j] * VVector[NDof*i+j]);
01019   }
01020 
01021   if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 0) )
01022    XGPSendPoint( NodeVector[i].curve, (double)iteration, sqrt( disp ) );
01023   else if( (NodeVector[i].dspIteration == DSP_YES) && (GpType == 1) )
01024    XGPSendPoint( NodeVector[i].curve, (double)iteration, sqrt( veloc ) );
01025  }
01026    return 1;
01027 } /* End of DisplacementVelocity */
01028 
01029 
01030 /*
01031 %F This function computes the mass vector for the model.
01032 */
01033 void MassVector( double *MVector )
01034 {
01035  int    i;
01036  double mass[24];
01037 
01038 /* Initialize the mass vector
01039  */
01040  for( i = 0; i < NDof*NumNodes; i++ )
01041   MVector[i] = 0.0;
01042 
01043 /* Loop over the elements
01044  */
01045  for( i = 0; i < NumElements; i++ ) {
01046  /* Check to see if the element was rezoned
01047   */
01048   if( ElmList[i]->rezone == DONE )
01049    continue;
01050 
01051  /* Compute the element mass matrix
01052   */
01053   ElmMass( ElmList[i], mass );
01054 
01055  /* Assemble in to the global vector
01056   */
01057   ElmAssVector( ElmList[i], MVector, mass );
01058  }
01059 
01060 } /* End of MassVector */
01061 
01062 
01063 /*
01064 %F
01065 */
01066 int DoRezone( int step, double *FVector )
01067 {
01068  int i, j, id, numnodes;
01069  int inc[8];
01070 
01071 /* Check to see if the rezone descriptor exists
01072  */
01073  if( Rezone == 0L )
01074   return( 0 );
01075 
01076 /* Update element rezone status for the current step
01077  */
01078  for( i = 0; i < Rezone[step-1].numelm; i++ ) {
01079   id = Rezone[step-1].elm[i] - 1;
01080   if( ElmList[id]->rezone == NONE ) ElmList[id]->rezone = TODO;
01081   else                              ElmList[id]->rezone = DONE;
01082  }
01083 
01084 /* Update node flag
01085  */
01086  for( i = 0; i < NumNodes; i++ )
01087   NodeVector[i].rezone = DONE;
01088 
01089  for( i = 0; i < NumElements; i++ ) {
01090   if( ElmList[i]->rezone == NONE ) {
01091    ElmConnect( ElmList[i], inc );
01092    ElmNumNodes( ElmList[i], &numnodes );
01093    for( j = 0; j < numnodes; j++ )
01094     NodeVector[inc[j]-1].rezone = NONE;
01095   }
01096  }
01097 
01098 /* Update prescribed values
01099  */
01100  UpdatePrescribedValues( FVector );
01101 
01102 /* Set element rezone state to DONE
01103  */
01104  for( i = 0; i < NumElements; i++ )
01105   if( ElmList[i]->rezone == TODO )
01106    ElmList[i]->rezone = DONE;
01107 
01108  return( 1 );
01109 
01110 } /* End of DoRezone */
01111 
01112 
01113 /*
01114 %F
01115 */
01116 void PercolationForces( double *F )
01117 {
01118  int    i;
01119  double pforce[24];
01120 
01121 /* Loop over the elements
01122  */
01123  for( i = 0; i < NumElements; i++ ) {
01124  /* Check to see if the element was not rezoned
01125   */
01126   if( ElmList[i]->rezone != NONE )
01127    continue;
01128 
01129  /* Compute element percolation forces
01130   */
01131   ElmPercForce( ElmList[i], pforce );
01132 
01133  /* Assemble in the global vector
01134   */
01135   ElmAssVector( ElmList[i], F, pforce );
01136  }
01137 
01138 } /* End of PercolationForces */
01139 
01140 
01141 /* =======================================================  End of File  */
01142 

Generated on Tue Oct 23 11:23:29 2007 for Relax by  doxygen 1.5.3