q4.c

Go to the documentation of this file.
00001 /*
00002 %M This modules contains the Q4 element sub-class methods and definitions
00003 %a Joao Luiz Elias Campos.
00004 %d September 7th, 1998.
00005 %r $Id: q4.c,v 1.4 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:  28-Apr-2005    Alexandre A. Del Savio
00013 *    Foram substituídas todas as alocações dinâmicas feitas com malloc 
00014 *    por calloc.
00015 *
00016 *  Modified:  23-Fev-2006    Juan Pablo Ibañez
00017 *    Modificada a funcão Q4ReadInitStress que passa a retornar 
00018 *    um valor int. 
00019 *
00020 *
00021 *  Modified:  Agosto-06  André Luis Muller
00022 *    Criada a função _Q4ElementCenter que retorna as coordenadas do centro de
00023 *    um elemento do tipo Q4.
00024 *    Adicionado a função Q4StressStrain o cálculo da poro pressão e o 
00025 *    cálculo da tensão efetiva.
00026 *
00027 *  Modified:  Setembro-06 André Luis Muller
00028 *    Modificação na função Q4InterForce para possibilitar
00029 *    a condição de tensões iniciais.
00030 *
00031 *    Modificação na função Q4New. Inicialização das tensões iniciais
00032 *
00033 *  Modified:  07-06 André Luis Muller
00034 *    Modificação na função Q4WriteGaussResults para possibilitar
00035 *    a escolha das respostas a serem escritas no arquivo de resultados.
00036 */
00037 
00038 /*
00039 ** ------------------------------------------------------------------------
00040 ** Global variables and symbols:
00041 */
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <math.h>
00045 #include <string.h>
00046 
00047 #include "rio.h"
00048 #include "load.h"
00049 #include "elm.h"
00050 #include "node.h"
00051 #include "material.h"
00052 #include "load.h"
00053 #include "xgplib.h"
00054 #include "alg.h"
00055 
00056 /*
00057 ** ------------------------------------------------------------------------
00058 ** Local variables and symbols:
00059 */
00060 
00061 /*
00062 %T Q4 element data definition
00063 */
00064 typedef struct _q4elm {
00065  int    matid;                /* Material identification          */
00066  int    tckid;                /* Element thickness identification */
00067  int    NumNodes;             /* Number of element nodes          */
00068  int    NumTensComp;          /* Number of tension components     */
00069  int    inc[4];               /* Element incidence                */
00070  double istr[4][3];           /* Element initial stress           */
00071  double effdef[4];            /* Effective deformation            */
00072  double prof;                 /* Element profile                  */
00073 } sQ4Data;
00074 
00075 
00076 /*
00077 %V Gauss point coordinates and its weights
00078 */
00079 static double _GPoint[2]  = { -0.577350269189626, 0.577350269189626 };
00080 static double _GWeight[2] = {  1.000000000000000, 1.000000000000000 };
00081 
00082 
00083 /*
00084 %V Transformation matrix
00085 */
00086 static double _TRMatrix[4][4] = {
00087                                  {  1.116025404,  0.250000000,
00088                                     0.250000000, -0.616025404 },
00089                                  {  0.250000000,  1.116025404,
00090                                    -0.616025404,  0.250000000 },
00091                                  { -0.616025404,  0.250000000,
00092                                     0.250000000,  1.116025404 },
00093                                  {  0.250000000, -0.616025404,
00094                                     1.116025404,  0.250000000 }
00095                                 };
00096 
00097 /*
00098 %V Element edges ids.
00099 */
00100 static int _Edges[4][2] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 } };
00101 
00102 static double GForce = 9.85;
00103 
00104 /*
00105 ** ------------------------------------------------------------------------
00106 ** Local functions:
00107 */
00108 static void   _Q4GetCoord       ( sElement *, sCoord [] );
00109 static void   _Q4ShapeFunc      ( double, double, double [] );
00110 static void   _Q4Jacobian       ( double, double, sCoord [], double *,
00111                                   double [2][2] );
00112 static void   _Q4BMatrix        ( double, double, sCoord [], double [3][8] );
00113 static void   _Q4DerivShp       ( double, double, sDerivRST [] );
00114 static void   _Q4GetDisplacement( sElement *, double *, double [] );
00115 static double _Q4MinHeight      ( sCoord * );
00116 static double _Q4CalcLength     ( sCoord *, sCoord * );
00117 static void   _Q4ElementCenter  ( sElement *, sCoord [] );
00118 static double _Q4PoroPressure   ( sElement *elm, double lambda );
00119 
00120 /*
00121 %F This function gets the element center.
00122 %i Element descriptor.
00123 %o Element center.
00124 */
00125 static void _Q4ElementCenter( sElement *elm, sCoord coord[1] )
00126 {
00127  sQ4Data *data = 0L;
00128  int      i, node;
00129  
00130  coord[0].x = 0.0;
00131  coord[0].y = 0.0;
00132  coord[0].z = 0.0;
00133 
00134  /* Element element data
00135  */
00136  data = (sQ4Data *)elm->data;
00137  
00138  for( i = 0; i < data->NumNodes; i++ ) {
00139   node = data->inc[i]-1;
00140   coord[0].x += NodeVector[node].coord.x;
00141   coord[0].y += NodeVector[node].coord.y;
00142  }
00143  /* Compute element center
00144  */
00145  coord[0].x /= data->NumNodes;
00146  coord[0].y /= data->NumNodes;
00147 } /* End of _Q4ElementCenter */
00148 
00149 /*
00150 %F This function computes the length of a given segment.
00151 */
00152 static double _Q4CalcLength( sCoord *pt1, sCoord *pt2 )
00153 {
00154  double dx = pt2->x - pt1->x;
00155  double dy = pt2->y - pt1->y;
00156  double dz = pt2->z - pt1->z;
00157 
00158  return sqrt( (dx * dx) + (dy * dy) + (dz * dz) );
00159 
00160 } /* End of _BRICK8CalcLength */
00161 
00162 /*
00163 %F This function computes the minimun height for the Q4 element.
00164 */
00165 static double _Q4MinHeight( sCoord *coord )
00166 {
00167  double minlen;
00168  int    i;
00169 
00170 /* For the first element edge.
00171  */
00172  minlen = _Q4CalcLength( &coord[_Edges[0][0]], &coord[_Edges[0][1]] );
00173 
00174 /* For the remain element edge
00175  */
00176  for( i = 1; i < 4; i++ ) {
00177  /* Compute the edge length
00178   */
00179   double len = _Q4CalcLength( &coord[_Edges[i][0]], &coord[_Edges[i][1]] );
00180 
00181  /* Get the smallest.
00182   */
00183   if( minlen > len )
00184    minlen = len;
00185  }
00186 
00187  return minlen;
00188 
00189 } /* End of _Q4MinHeight */
00190 
00191 
00192 /*
00193 %F This function gets the element coordinates.
00194 %i Element descriptor.
00195 %o Element coordinares.
00196 */
00197 static void _Q4GetCoord( sElement *elm, sCoord coord[3] )
00198 {
00199  sQ4Data *data = 0L;
00200  int      i;
00201 
00202 /* Element element data
00203  */
00204  data = (sQ4Data *)elm->data;
00205 
00206 /* Get element coordinates
00207  */
00208  for( i = 0; i < 4; i++ ) {
00209   coord[i].x = elm->nodes[data->inc[i]-1].coord.x;
00210   coord[i].y = elm->nodes[data->inc[i]-1].coord.y;
00211   coord[i].z = 0.0;
00212  }
00213 
00214 } /* End of _Q4GetCoord */
00215 
00216 
00217 /*
00218 %F This function get the element nodal displacement from the global 
00219    vector.
00220 */
00221 static void _Q4GetDisplacement( sElement *elm, double *U, double ue[6] )
00222 {
00223  sQ4Data *data = 0L;
00224  int      i;
00225 
00226 /* Get element descriptor
00227  */
00228  data = (sQ4Data *)elm->data;
00229 
00230 /* Fill element displacement vector
00231  */
00232  for( i = 0; i < data->NumNodes; i++ ) {
00233   ue[2*i]   = U[2*(data->inc[i]-1)];
00234   ue[2*i+1] = U[2*(data->inc[i]-1)+1];
00235  }
00236 
00237 } /* End of _Q4GetDisplacement */
00238 
00239 
00240 /*
00241 %F This function computes the stress x strain matrix for the Q4 element.
00242 */
00243 static void _Q4BMatrix( double r, double s, sCoord coord[4], double bm[3][8] )
00244 {
00245  double    detjac;
00246  double    jac[2][2], ijac[2][2];
00247  sDerivRST dshp[4];
00248  int       i;
00249 
00250 /* Initialize B matrix
00251  */
00252  for( i = 0; i < 8; i++ )
00253   bm[0][i] = bm[1][i] = bm[2][i] = 0.0;
00254 
00255 /* Compute the element jacobian matrix
00256  */
00257  _Q4Jacobian( r, s, coord, &detjac, jac );
00258 
00259 /* Compute the inverse
00260  */
00261  ijac[0][0] =   jac[1][1] / detjac;
00262  ijac[1][0] = - jac[1][0] / detjac;
00263  ijac[0][1] = - jac[0][1] / detjac;
00264  ijac[1][1] =   jac[0][0] / detjac;
00265 
00266 /* Compute shape functions derivatives
00267  */
00268  _Q4DerivShp( r, s, dshp );
00269 
00270 /* Compute the B matrix coefficientes
00271  */
00272  for( i = 0; i < 4; i++ ) {
00273   bm[0][2*i]   = (ijac[0][0] * dshp[i].r) + (ijac[0][1] * dshp[i].s);
00274   bm[1][2*i+1] = (ijac[1][0] * dshp[i].r) + (ijac[1][1] * dshp[i].s);
00275   bm[2][2*i]   = bm[1][2*i+1];
00276   bm[2][2*i+1] = bm[0][2*i];
00277  }
00278 
00279 } /* End of _Q4BMatrix */
00280 
00281 
00282 /*
00283 %F This function computes the jacobian matrix for the quadrilateral
00284    Q4 element.
00285 */
00286 static void _Q4Jacobian( double r, double s, sCoord coord[4], double *detjac,
00287                          double jac[2][2] )
00288 {
00289  sDerivRST dmap[4];
00290  int       i;
00291 
00292 /* Compute the map derivatives
00293  */
00294  _Q4DerivShp( r, s, dmap );
00295 
00296 /* Compute the jacobian matrix
00297  */
00298  for( i = 0; i < 2; i++ )
00299   jac[i][0] = jac[i][1] = 0.0;
00300 
00301  for( i = 0; i < 4; i++ ) {
00302   jac[0][0] += dmap[i].r * coord[i].x;
00303   jac[0][1] += dmap[i].r * coord[i].y;
00304   jac[1][0] += dmap[i].s * coord[i].x;
00305   jac[1][1] += dmap[i].s * coord[i].y;
00306  }
00307 
00308 /* Determiant
00309  */
00310  (*detjac) = (jac[0][0] * jac[1][1]) - (jac[0][1] * jac[1][0]);
00311 
00312 } /* End of _Q4Jacobian */
00313 
00314 
00315 /*
00316 %F This function computes the shape functions for the quadrilateral
00317    Q4 element.
00318 */
00319 static void _Q4ShapeFunc( double r, double s, double shape[4] )
00320 {
00321 /* Compute shape functions
00322  */
00323  shape[0] = 0.25 * (1.0 - r) * (1.0 - s);
00324  shape[1] = 0.25 * (1.0 + r) * (1.0 - s);
00325  shape[2] = 0.25 * (1.0 + r) * (1.0 + s);
00326  shape[3] = 0.25 * (1.0 - r) * (1.0 + s);
00327 
00328 } /* End of _Q4ShapeFunc */
00329 
00330 
00331 /*
00332 %F This function computes the shape functions derivatives for the
00333    quadrilateral 4 node element.
00334 */
00335 static void _Q4DerivShp( double r, double s, sDerivRST dshp[4] )
00336 {
00337 /* Compute shape functions derivatives
00338  */
00339  dshp[0].r = -0.25 * (1.0 - s);
00340  dshp[1].r =  0.25 * (1.0 - s);
00341  dshp[2].r =  0.25 * (1.0 + s);
00342  dshp[3].r = -0.25 * (1.0 + s);
00343 
00344  dshp[0].s = -0.25 * (1.0 - r);
00345  dshp[1].s = -0.25 * (1.0 + r);
00346  dshp[2].s =  0.25 * (1.0 + r);
00347  dshp[3].s =  0.25 * (1.0 - r);
00348 
00349 } /* End of _INFINITEDerivShp */
00350 
00351 
00352 /*
00353 ** ------------------------------------------------------------------------
00354 ** Subclass methods:
00355 */
00356 static void   Q4New( int, int, int, int, sElement **, sElement **, sNode * );
00357 static void   Q4Free                  ( sElement * );
00358 static void   Q4Read                  ( sElement * );
00359 static int    Q4ReadInitStress        ( sElement * );
00360 static void   Q4ReadProfile           ( sElement * );
00361 static void   Q4MassMatrix            ( sElement *, double * );
00362 
00363 static double Q4RigidCoeff            ( sElement * );
00364 static void   Q4Connect               ( sElement *, int * );
00365 static void   Q4NumNodes              ( sElement *, int * );
00366 static void   Q4Gravity               ( sElement *, double *, double *,
00367                                                     double * );
00368 static void   Q4AssVector             ( sElement *, double *, double * );
00369 static void   Q4TimeStep              ( sElement *, double * );
00370 static void   Q4InterForce            ( sElement *, sTensor *, double * );
00371 static void   Q4StressStrain          ( sElement *, double, double *, double *,
00372                                                     sTensor *, sTensor * );
00373 static void   Q4WriteStress           ( sElement *, FILE *, double *,
00374                                                             double * );
00375 static void   Q4WriteGaussResult      ( sElement *, FILE *, FILE * );
00376 static void   Q4WriteGaussVectorResult( sElement *, int, FILE *, FILE * );
00377 static void   Q4WriteNodalResult      ( sElement *, FILE *, FILE * );
00378 static void   Q4UpdateStress          ( sElement *, double, double *,
00379                                                             sTensor * );
00380 static void   Q4PercForces            ( sElement *, double * );
00381 static void   Q4SetPressure           ( sElement *, double );
00382 static void   Q4SetInitStress         ( sElement *, sTensor * );
00383 static void   Q4ViscoForce            ( sElement *, double, sTensor *,
00384                                         double * );
00385 static void Q4KMatrix( sElement *, double [24][24] );                                                                         
00386 static void Q4GetDof( sElement *, int [24], int * );
00387 
00388 /*
00389 %F This method allocates memory for a Q4 element and fills its data with 
00390    the specific data.
00391 %i Element label (number)
00392 %o Element descriptor.
00393 */
00394 static void Q4New( int label, int matid, int intord, int tckid, 
00395                    sElement **elm, sElement **elist, sNode *nodes )
00396 {
00397  sQ4Data *data = 0L;
00398  int      i;
00399 
00400 /* Get memory for the element descriptor
00401  */
00402  (*elm) = (sElement *)calloc(1, sizeof(sElement));
00403 
00404 /* Get memory for the Q4 element data
00405  */
00406  data = (sQ4Data *)calloc(1, sizeof(sQ4Data));
00407 
00408 /* Fill Q4 element data
00409  */
00410  data->matid       = matid;
00411  data->tckid       = tckid;
00412  data->NumNodes    = 4;
00413  data->NumTensComp = 4;
00414  data->prof        = 0.0;
00415  for( i = 0; i < 4; i++ )
00416   data->effdef[i] = 0.0;
00417 
00418  for( i =0; i < 4; i++){
00419   data->istr[i][0] = 0.0;
00420   data->istr[i][1] = 0.0;
00421   data->istr[i][2] = 0.0;
00422  }
00423 
00424 /* Fill element descriptor
00425  */
00426  (*elm)->type    = Q4;
00427  (*elm)->rezone  = NONE;
00428  (*elm)->display = DSP_NO;
00429  (*elm)->curve   = 0;
00430  (*elm)->label   = label;
00431  (*elm)->data    = (void *)data;
00432  (*elm)->nodes   = nodes;
00433 
00434 /* Add to the element list
00435  */
00436  elist[label-1] = (*elm);
00437 
00438 } /* End of Q4New */
00439 
00440 
00441 /*
00442 %F This method frees the Q4 element data for a given element.
00443 %i Element descriptor.
00444 */
00445 static void Q4Free( sElement *elm )
00446 {
00447  sQ4Data *data = 0L;
00448 
00449 /* Get Q4 element data
00450  */
00451  data = (sQ4Data *)elm->data;
00452 
00453 /* Release allocated memory
00454  */
00455  free( data );
00456 
00457 /* Reset element data
00458  */
00459  elm->data = 0L;
00460 
00461 } /* End of Q4Free */
00462 
00463 
00464 /*
00465 %F This method reads the Q4 element information.
00466 %i Element descriptor.
00467 */
00468 static void Q4Read( sElement *elm )
00469 {
00470  sQ4Data *data = 0L;
00471  int      i1, i2, i3, i4;
00472 
00473 /* Get the element data
00474  */
00475  data = (sQ4Data *)elm->data;
00476 
00477 /* Read the element incidence
00478  */
00479  fscanf( nf, "%d %d %d %d", &i1, &i2, &i3, &i4 );
00480 
00481 /* Fill element information
00482  */
00483  data->inc[0] = i1;
00484  data->inc[1] = i2;
00485  data->inc[2] = i3;
00486  data->inc[3] = i4;
00487 
00488 } /* End of Q4Read */
00489 
00490 
00491 /*
00492 %F This method reads the Q4 initial stress
00493 */
00494 static int Q4ReadInitStress( sElement *elm )
00495 {
00496  int      i, numpg = 4;
00497  double   sxx, syy, sxy ,szz, sxz, syz;
00498  sQ4Data *data = 0L;
00499 
00500 /* Get element data
00501  */
00502  data = (sQ4Data *)elm->data;
00503 
00504 /* Read the number of integration points and check to see if is compatible
00505  * whith the element type.
00506  
00507  /*fscanf( nf, "%d", &numpg );*/
00508  if( numpg != 4 ) {
00509   printf( "\n\nNumber of gauss points must be equal to four.\n\n" );
00510   return 0;
00511  }
00512 
00513 /* Read the initial stress information
00514  */
00515  fscanf( nf, "%lf %lf %lf %lf %lf %lf", &sxx, &syy, &szz, &sxy, &sxz, &syz);
00516  for( i = 0; i < numpg; i++ ) {
00517   data->istr[i][0] = sxx;
00518   data->istr[i][1] = syy;
00519   data->istr[i][2] = sxy;
00520  }
00521 
00522  return 1;
00523 
00524 } /* End of Q4ReadInitStress */
00525 
00526 /*
00527 %F This method reads the Q4 profile
00528 */
00529 static void Q4ReadProfile( sElement *elm )
00530 {
00531  double prof;
00532  sQ4Data *data = 0L;
00533 
00534 /* Get element data
00535  */
00536  data = (sQ4Data *)elm->data;
00537 
00538 /* Read the element profile
00539  */
00540  fscanf( nf, "%lf ", &prof);
00541  data->prof = prof;
00542 
00543 } /* End of Q4ReadProfile */
00544 
00545 /*
00546 %F This method computes the mass matrix for the Q4 element.
00547 %i Element descriptor.
00548 %o Element mass matrix.
00549 */
00550 static void Q4MassMatrix( sElement *elm, double *mass )
00551 {
00552  sQ4Data *data = 0L;
00553  sCoord   coord[4];
00554  double   shape[4], jac[2][2];
00555  double   dens, detjac, coeff;
00556  int      i, j, k, l;
00557 
00558 /* Initialize mass vector
00559  */
00560  for( i = 0; i < 8; i++ )
00561   mass[i] = 0.0;
00562 
00563 /* Get element coordinates
00564  */
00565  _Q4GetCoord( elm, coord );
00566 
00567 /* Get material density
00568  */
00569  data  = (sQ4Data *)elm->data;
00570  MatDensity( MatList[data->matid-1], &dens );
00571 
00572 /* Calculate the element node contribution for the element mass
00573  */
00574  for( j = 0; j < 2; j++ ) {
00575   for( i = 0; i < 2; i++ ) {
00576   /* Compute shape functions
00577    */
00578    _Q4ShapeFunc( _GPoint[i], _GPoint[j], shape );
00579 
00580   /* Compute the jacobian matrix
00581    */
00582    _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &detjac, jac );
00583 
00584   /* Rigidity coefficient
00585    */
00586    coeff = dens * detjac * _GWeight[i] * _GWeight[j];
00587 
00588   /* Compute mass
00589    */
00590    for( k = 0; k < 4; k++ ) {
00591     for( l = 0; l < 4; l++ ) {
00592      mass[2*k]   += coeff * shape[k] * shape[l];
00593      mass[2*k+1] += coeff * shape[k] * shape[l];
00594     }
00595    }
00596 
00597   }
00598  }
00599  
00600 } /* End of Q4MassMatrix */
00601 
00602 
00603 /*
00604 %F This functions computes the element rigidity coefficient.
00605 %i Element descriptor.
00606 %o Element rigidity coefficient.
00607 */
00608 static double Q4RigidCoeff( sElement *elm )
00609 {
00610  sCoord coord[4];
00611  double shape[4], jac[2][2];
00612  double detjac, area = 0.0;
00613  int    i, j;
00614 
00615 /* Get element coordinates
00616  */
00617  _Q4GetCoord( elm, coord );
00618 
00619 /* Calculate the element node contribution for the element area
00620  */
00621  for( j = 0; j < 2; j++ ) {
00622   for( i = 0; i < 2; i++ ) {
00623   /* Compute shape functions
00624    */
00625    _Q4ShapeFunc( _GPoint[i], _GPoint[j], shape );
00626 
00627   /* Compute the jacobian matrix
00628    */
00629    _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &detjac, jac );
00630 
00631   /* Rigidity coefficient
00632    */
00633    area += detjac * _GWeight[i] * _GWeight[j];
00634   }
00635  }
00636 
00637  return( area );
00638 
00639 } /* End of Q4RigidCoeff */
00640 
00641 
00642 /*
00643 %F This function computes the equivalent load applied to the element 
00644    face.
00645 */
00646 static void Q4Load( sElement *elm, eLoadType ltype, 
00647                     int key, int noi, int noj, int nok, int *nol,
00648                     double *q1x, double *q1y, double *q1z, 
00649                     double *q2x, double *q2y, double *q2z, 
00650                     double *q3x, double *q3y, double *q3z, 
00651                     double *q4x, double *q4y, double *q4z )
00652 
00653 {
00654  double l, aux, teta;
00655  double v1x = (*q1x);
00656  double v1y = (*q1y);
00657  double v2x = (*q2x);
00658  double v2y = (*q2y);
00659 
00660 /* Check for the local system
00661  */ 
00662  if( key ) {
00663   teta = atan2((elm->nodes[noj-1].coord.y - elm->nodes[noi-1].coord.y),
00664                (elm->nodes[noj-1].coord.x - elm->nodes[noi-1].coord.x));
00665 
00666   aux = (v1x * cos(teta)) - (v1y * sin(teta));
00667   v1y = (v1x * sin(teta)) + (v1y * cos(teta));
00668   v1x = aux;
00669 
00670   aux = (v2x * cos(teta)) - (v2y * sin(teta));
00671   v2y = (v2x * sin(teta)) + (v2y * cos(teta));
00672   v2x = aux;
00673  }
00674 
00675 /* Compute the element edge lenght
00676  */
00677  l = sqrt(((elm->nodes[noi-1].coord.x - elm->nodes[noj-1].coord.x)  *
00678            (elm->nodes[noi-1].coord.x - elm->nodes[noj-1].coord.x)) +
00679           ((elm->nodes[noi-1].coord.y - elm->nodes[noj-1].coord.y)  *
00680            (elm->nodes[noi-1].coord.y - elm->nodes[noj-1].coord.y)));
00681 
00682 /* Compute the equivalent forces
00683  */
00684  if( ltype == UNIFORM ) {
00685   v1x *= l / 2.0;
00686   v1y *= l / 2.0;
00687 
00688   (*q1x) = v1x;
00689   (*q1y) = v1y;
00690 
00691   (*q2x) = v1x;
00692   (*q2y) = v1y;
00693  }
00694  else {
00695   (*q1x) = ((2.0 * v1x * l) / 6.0) + ((v2x * l) / 6.0);
00696   (*q1y) = ((2.0 * v1y * l) / 6.0) + ((v2y * l) / 6.0);
00697 
00698   (*q2x) = ((2.0 * v2x * l) / 6.0) + ((v1x * l) / 6.0);
00699   (*q2y) = ((2.0 * v2y * l) / 6.0) + ((v1y * l) / 6.0);
00700  }
00701 
00702 } /* End of Q4Load */
00703 
00704 
00705 /*
00706 %F
00707 */
00708 static void Q4Connect( sElement *elm, int *conn )
00709 {
00710  int      i;
00711  sQ4Data *data = 0L; 
00712 
00713  data = (sQ4Data *)elm->data;
00714 
00715  for( i = 0; i < data->NumNodes; i++ )
00716   conn[i] = data->inc[i];
00717 
00718 } /* End of Q4Connect */
00719 
00720 
00721 /*
00722 %F
00723 */
00724 static void Q4NumNodes( sElement *elm, int *nnodes )
00725 {
00726  sQ4Data *data = (sQ4Data *)elm->data;
00727 
00728  (*nnodes) = data->NumNodes;
00729 
00730 } /* End of Q4NumNodes */
00731 
00732 
00733 /*
00734 %F
00735 */
00736 static void Q4Gravity( sElement *elm, double *qx, double *qy, double *qz )
00737 {
00738  sQ4Data *data = 0;
00739  sCoord   coord[4];
00740  double   area, mass, gamma;
00741  int      matid;
00742 
00743 /* Get element data
00744  */
00745  data = (sQ4Data *)elm->data;
00746 
00747 /* Get element coordinates
00748  */
00749  _Q4GetCoord( elm, coord );
00750 
00751 /* Compute element area
00752  */
00753  area = Q4RigidCoeff( elm );
00754 
00755 /* Get material id, and the material density property
00756  */
00757  matid = data->matid;
00758  MatDensity( MatList[matid-1], &gamma );
00759  
00760 /* Compute the gravitational load
00761  */
00762  mass = (gamma * area) / 4.0;
00763 
00764  (*qx) = mass * GravForce.gx;
00765  (*qy) = mass * GravForce.gy;
00766  (*qz) = mass * GravForce.gz;
00767 
00768 } /* End of Q4Gravity */
00769 
00770 
00771 /*
00772 %F
00773 */
00774 static void Q4AssVector( sElement *elm, double *GMatrix, double *matrix )
00775 {
00776  int      i;
00777  int      conn[4];
00778  sQ4Data *data;
00779 
00780 /* Get the element data
00781  */
00782  data = (sQ4Data *)elm->data;
00783 
00784 /* Get element connectivity
00785  */
00786  ElmConnect( elm, conn );
00787 
00788 /* Assemble matrix
00789  */
00790  for( i = 0; i < data->NumNodes; i++ ) {
00791   GMatrix[2*(conn[i]-1)]   += matrix[2*i];
00792   GMatrix[2*(conn[i]-1)+1] += matrix[2*i+1];
00793  }
00794  
00795 } /* End of Q4AssVector */
00796 
00797 
00798 /*
00799 %F
00800 */
00801 
00802 
00803 static void Q4StressStrain( sElement *elm, double dt, double *U, double *yield,
00804                                            sTensor *stre, sTensor *stra )
00805 {
00806  sQ4Data    *data = 0L;
00807  sMaterial  *mat  = 0L;
00808  sCoord      coord[4];
00809  double      cm[6][6];
00810  double      bm[3][8];
00811  double      ue[8];
00812  double      def[3], str[5];
00813  double      pf = 1.0;
00814  int         i, j, k, l, npg;
00815  double     poropressure;
00816  double     lambda;
00817  double     nu;
00818 
00819 /* Initialize stress and strain vector
00820  */
00821  for( i = 0; i < 4; i++ ) {
00822   stre[i].xx = stre[i].xy = stre[i].xz = 
00823                stre[i].yy = stre[i].yz = 
00824                             stre[i].zz = 0.0;
00825   if( stra != 0L ) {
00826    stra[i].xx = stra[i].xy = stra[i].xz = 
00827                 stra[i].yy = stra[i].yz = 
00828                              stra[i].zz = 0.0;
00829   }
00830  }
00831 
00832 /* Get element descriptor
00833  */
00834  data = (sQ4Data *)elm->data;
00835 
00836 /* Get Material object
00837  */
00838  mat = MatList[data->matid-1];
00839 
00840 /* Get element coordinates
00841  */
00842  _Q4GetCoord( elm, coord );
00843 
00844 /* Get element displacement
00845  */
00846  _Q4GetDisplacement( elm, U, ue );
00847  
00848 /* Get poisson coeff.
00849  */
00850  MatNuParameter( mat, &nu );
00851 
00852 
00853 /* Get element lambda
00854  */
00855  lambda = MatList[data->matid-1]->Lambda;
00856  
00857  if(lambda>0.0){
00858   poropressure = _Q4PoroPressure(elm,lambda );
00859  }
00860 /* Compute stress and strain for each gauss point
00861  */
00862  npg = 0;
00863  for( j = 0; j < 2; j++ ) {
00864   for( i = 0; i < 2; i++ ) {
00865   /* Update the material parameter
00866    */
00867    MatUpdateParameter( mat, data->effdef[npg] );
00868 
00869   /* Get material constitutive matrix
00870    */
00871    MatConstitutiveMatrix( mat, cm );
00872 
00873   /* Get element stress x strain matrix
00874    */
00875    _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
00876 
00877   /* Compute the deformations
00878    */
00879    for( k = 0; k < 3; k++ ) {
00880     def[k] = 0.0;
00881     for( l = 0; l < (2*data->NumNodes); l++ )
00882      def[k] += bm[k][l] * ue[l];
00883    }
00884 
00885   /* Compute the element stress
00886    */
00887    for( k = 0; k < 3; k++ ) {
00888     str[k] = 0.0;
00889     for( l = 0; l < 3; l++ )
00890      str[k] += cm[k][l] * def[l];
00891     str[k] += data->istr[npg][k];
00892    }
00893    str[3] = str[4] = 0.0;
00894 
00895    if(lambda>0.0){
00896     /* Compute efective stress
00897     */
00898     for( k = 0; k < 2; k++ ) {
00899      str[k] += poropressure;
00900     }
00901     /* Correct stress based on the material model
00902     */
00903     MatUpdateStress( mat, dt, &pf, &data->effdef[npg], str, def );
00904     /* Compute total stress
00905     */
00906     for( k = 0; k < 2; k++ ) {
00907      str[k] -= poropressure;
00908     }
00909    }
00910    else{
00911     /* Correct stress based on the material model
00912     */
00913     MatUpdateStress( mat, dt, &pf, &data->effdef[npg], str, def );
00914    }
00915 
00916   /* Set stress values
00917    */
00918    stre[npg].xx = str[0];
00919    stre[npg].yy = str[1];
00920    stre[npg].xy = str[2];
00921    stre[npg].rf = str[4];
00922    
00923  /* Compute off plane stress
00924   */
00925    ElementOffPlaneStress( nu, &stre[npg] );
00926 
00927   /* Set strain values
00928    */
00929    if( stra != 0L ) {
00930     stra[npg].xx = def[0];
00931     stra[npg].yy = def[1];
00932     stra[npg].xy = def[2];
00933    }
00934 
00935   /* Set yield parameter
00936    */
00937    if( yield != 0L )
00938     yield[npg] = (pf > 0.0) ? 0.0 : 1.0;
00939 
00940   /* Update gauss point number
00941    */
00942    npg++;
00943 
00944   }
00945  }
00946 
00947 } /* End of Q4StressStrain */
00948 
00949 static double _Q4PoroPressure( sElement *elm, double lambda )
00950 {
00951  sQ4Data   *data = 0L;
00952  sMaterial *mat  = 0L;
00953  double     poropressure;
00954  double     gamma;
00955  double     distance;
00956  
00957  /* Get element descriptor
00958  */
00959  data = (sQ4Data *)elm->data;
00960 
00961  /* Get Material object
00962  */
00963  mat = MatList[data->matid-1];
00964  
00965  /* Get element gamma
00966   */
00967  MatDensity( mat, &gamma );
00968  
00969  /* Get element prof
00970   */
00971  distance = data->prof;
00972  
00973  /* Compute the poropressure
00974   */ 
00975  poropressure = lambda*gamma*GForce*distance*Config.loadfactor;
00976  
00977  return (poropressure);
00978 } /* End of _Q4PoroPressure */
00979 
00980 /*
00981 %F This function computes the internal forces for the Q4 element
00982 */
00983 static void Q4InterForce( sElement *elm, sTensor *stress, double *intforce )
00984 {
00985  int      i, j, k, l, npg;
00986  double   coeff;
00987  double   bm[3][8], str[3], jac[2][2], iforce[8];
00988  sCoord   coord[4];
00989  sQ4Data *data = 0L;
00990 
00991 /* Get element descriptor
00992  */
00993  data = (sQ4Data *)elm->data;
00994 
00995 /* Get element coordinates
00996  */
00997  _Q4GetCoord( elm, coord );
00998 
00999 /* Initialize element internal forces vector
01000  */
01001  for( i = 0; i < (2*data->NumNodes); i++ )
01002   intforce[i] = 0.0;
01003 
01004 /* Compute internal force for each gauss point
01005  */
01006 /* Check for the initial stress
01007  */
01008  if( stress == 0L ) {
01009   npg = 0;
01010   for( j = 0; j < 2; j++ ) {
01011    for( i = 0; i < 2; i++ ) {
01012    /* Compute element B matrix
01013    */
01014     _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
01015 
01016    /* Compute rigidity coefficient
01017    */
01018     _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &coeff, jac );
01019 
01020     coeff *= _GWeight[i] * _GWeight[j];
01021 
01022     for( k = 0; k < (2*data->NumNodes); k++ ) {
01023      iforce[k] = 0.0;
01024      for( l = 0; l < 3; l++ )
01025       iforce[k] += bm[l][k] * data->istr[npg][l];
01026      iforce[k] *= coeff;
01027     }
01028     /* Add in the element vector
01029     */
01030     for( k = 0; k < (2*data->NumNodes); k++ )
01031      intforce[k] += iforce[k];
01032     npg++;
01033    }
01034   }
01035   return;
01036  }
01037  npg = 0;
01038  for( j = 0; j < 2; j++ ) {
01039   for( i = 0; i < 2; i++ ) {
01040   /* Compute element B matrix
01041   */
01042    _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
01043 
01044   /* Compute rigidity coefficient
01045   */
01046    _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &coeff, jac );
01047 
01048    coeff *= _GWeight[i] * _GWeight[j];
01049 
01050   /* Get element stress
01051    */
01052    str[0] = stress[npg].xx;
01053    str[1] = stress[npg].yy;
01054    str[2] = stress[npg].xy;
01055 
01056   /* Compute element internal forces for the current gauss point
01057    */
01058    for( k = 0; k < (2*data->NumNodes); k++ ) {
01059     iforce[k] = 0.0;
01060     for( l = 0; l < 3; l++ )
01061      iforce[k] += bm[l][k] * str[l];
01062     iforce[k] *= coeff;
01063    } 
01064 
01065   /* Add in the element vector
01066    */
01067    for( k = 0; k < (2*data->NumNodes); k++ )
01068     intforce[k] += iforce[k];
01069 
01070   /* Update gauss point number
01071    */
01072    npg++;
01073 
01074   }
01075  }
01076 
01077  for( i = 0; i < (2*data->NumNodes); i++ )
01078   intforce[i] *= -1.0;
01079  
01080 } /* End of Q4InterForce */
01081 
01082 
01083 /*
01084 %F
01085 */
01086 static void Q4WriteStress( sElement *elm, FILE *out, double *U, double *V )
01087 {
01088  int     i;
01089  sTensor  stress[4];
01090  sTensor  strain[4];
01091  sTensor  strd[4];
01092  double   yield[4];
01093  double   iso;
01094 
01095 /* Check to see if the element was rezoned
01096  */
01097  if( elm->rezone == DONE ) {
01098   int i;
01099 
01100  /* Set the stress and strain vectors to 0
01101   */
01102   for( i = 0; i < 4; i++ ) {
01103    stress[i].xx = stress[i].xy = stress[i].xz = 
01104                   stress[i].yy = stress[i].yz = 
01105                                  stress[i].zz = 0.0;
01106    strd[i].xx = strd[i].xy = strd[i].xz = 
01107                 strd[i].yy = strd[i].yz = 
01108                              strd[i].zz = 0.0;
01109    strain[i].xx = strain[i].xy = strain[i].xz = 
01110                   strain[i].yy = strain[i].yz = 
01111                                  strain[i].zz = 0.0;
01112    yield[i] = 0.0;
01113   }
01114  }
01115  else {
01116  /* Compute the element stress and strain
01117   */
01118   Q4StressStrain( elm, 0.0, U, yield, stress, strain );
01119  }
01120 
01121 /* Compute desviatory stress
01122  */
01123  for( i = 0; i < 4; i++ ) {
01124   iso = (stress[i].xx + stress[i].yy + stress[i].zz)/3.0;
01125   strd[i].xx = stress[i].xx - iso;
01126   strd[i].yy = stress[i].yy - iso;
01127  }
01128 
01129 /* Write element stress and strain
01130  */
01131  fwrite( stress, sizeof(sTensor), 4, out );
01132  fwrite( strain, sizeof(sTensor), 4, out );
01133  fwrite( strd, sizeof(sTensor), 4, out );
01134  fwrite( yield, sizeof(double), 4, out );
01135 
01136 } /* End of Q4WriteStress */
01137 
01138 
01139 /*
01140 %F
01141 */
01142 static void Q4WriteNodalResult( sElement *elm, FILE *out, FILE *tmp )
01143 {
01144  sTensor  strgau[4],strndl[4];
01145  sTensor  strdgau[4],strdndl[4];
01146  sTensor  defgau[4],defndl[4];
01147  sPTensor pstress, pstrain;
01148  double   yieldg[4], yieldn[4];
01149  int      i, j;
01150  double   iso[4];
01151 
01152 /* Read results from temporary file
01153  */
01154  fread( strgau, sizeof(sTensor), 4, tmp );
01155  fread( defgau, sizeof(sTensor), 4, tmp );
01156  fread( strdgau, sizeof(sTensor), 4, tmp );
01157  fread( yieldg, sizeof(double), 4, tmp );
01158 
01159 /* Compute the nodal results
01160  */
01161  for( i = 0; i < 4; i++ ) {
01162   strndl[i].xx = strndl[i].xy = strndl[i].xz =
01163                  strndl[i].yy = strndl[i].yz =
01164                                 strndl[i].zz = 0.0;
01165   strdndl[i].xx = strdndl[i].xy = strdndl[i].xz =
01166                   strdndl[i].yy = strdndl[i].yz =
01167                                   strdndl[i].zz = 0.0;
01168   defndl[i].xx = defndl[i].xy = defndl[i].xz = 
01169                  defndl[i].yy = defndl[i].yz =
01170                                 defndl[i].zz = 0.0;
01171   yieldn[i] = 0.0;
01172 
01173   for( j = 0; j < 4; j++ ) {
01174    strndl[i].xx  += _TRMatrix[i][j] * strgau[j].xx;
01175    strndl[i].yy  += _TRMatrix[i][j] * strgau[j].yy;
01176    strndl[i].zz  += _TRMatrix[i][j] * strgau[j].zz;
01177    strndl[i].xy  += _TRMatrix[i][j] * strgau[j].xy;
01178    strdndl[i].xx += _TRMatrix[i][j] * strdgau[j].xx;
01179    strdndl[i].yy += _TRMatrix[i][j] * strdgau[j].yy;
01180    defndl[i].xx  += _TRMatrix[i][j] * defgau[j].xx;
01181    defndl[i].yy  += _TRMatrix[i][j] * defgau[j].yy;
01182    defndl[i].xy  += _TRMatrix[i][j] * defgau[j].xy;
01183    yieldn[i]     += _TRMatrix[i][j] * yieldg[j];
01184    iso[i] = (strndl[i].xx + strndl[i].yy + strndl[i].zz)/3.0;
01185   }
01186  }
01187 
01188 /* Write results on output file
01189  */
01190  fprintf( out, "%d\n", elm->label );
01191  for( i = 0; i < 4; i++ ) {
01192   PrincipalTensor( &strndl[i], &pstress );
01193   PrincipalTensor( &defndl[i], &pstrain );
01194   fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\t%+10.5e\t", strndl[i].xx,
01195                                                         strndl[i].yy,
01196                                                         strndl[i].zz,
01197                                                         strndl[i].xy );
01198   fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\t", pstress.dir1,
01199                                                pstress.dir2,
01200                                                pstress.dir3 );
01201   fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\t", strdndl[i].xx,
01202                                                strdndl[i].yy,
01203                                                iso[i]);
01204   fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\t", defndl[i].xx,
01205                                                defndl[i].yy,
01206                                                defndl[i].xy );
01207   fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\t", pstrain.dir1,
01208                                                pstrain.dir2,
01209                                                pstrain.dir3 );
01210   fprintf( out, "%+10.5e\n", yieldn[i] );
01211  }
01212 
01213 } /* End of Q4WriteNodalResult */
01214 
01215 
01216 /*
01217 %F
01218 */
01219 static void Q4WriteGaussResult( sElement *elm, FILE *out, FILE *tmp )
01220 {
01221  sTensor  stress[4];
01222  sTensor  strain[4];
01223  sTensor  strd[4],estr[4];
01224  sPTensor pstress, pstrain, epsts, dpsts;
01225  double   yield[4];
01226  int      i,j;
01227  double   iso, piso;
01228  double   lambda;
01229  double   poropressure = 0.0;
01230  sMaterial *mat  = 0L;
01231  sQ4Data   *data = 0L;
01232 
01233 /* Read results from temporary file
01234  */
01235  fread( stress, sizeof(sTensor), 4, tmp );
01236  fread( strain, sizeof(sTensor), 4, tmp );
01237  fread( strd, sizeof(sTensor), 4, tmp );
01238  fread( yield, sizeof(double), 4, tmp );
01239  
01240  /* Get element descriptor
01241  */
01242  data = (sQ4Data *)elm->data;
01243 
01244 /* Get Material object
01245  */
01246  mat = MatList[data->matid-1];
01247  
01248  /* Get element lambda
01249  */
01250  lambda = MatList[data->matid-1]->Lambda;
01251  
01252  if(lambda>0.0){
01253   poropressure = _Q4PoroPressure(elm,lambda);
01254   /* Compute efective stress
01255   */
01256   for( i = 0; i < 4; i++ ) {
01257    estr[i].xx = stress[i].xx + poropressure;
01258    estr[i].yy = stress[i].yy + poropressure;
01259    estr[i].xy = stress[i].xy;
01260   } 
01261  }
01262  else{
01263   for( i = 0; i < 4; i++ ) {
01264    estr[i].xx = stress[i].xx;
01265    estr[i].yy = stress[i].yy;
01266    estr[i].xy = stress[i].xy;
01267   }
01268  }
01269 
01270 /* Write results on output file
01271  */
01272  fprintf( out, "%d\t%d\n", elm->label, 4 );
01273  for( i = 0; i < 4; i++ ) {
01274   /* Compute principal stress and strain
01275   */
01276   PrincipalTensor( &stress[i], &pstress );
01277   PrincipalTensor( &strain[i], &pstrain );
01278   iso = (stress[i].xx + stress[i].yy + stress[i].zz)/3.0;
01279   /* Compute desviatory principal stress
01280   */
01281   piso = (pstress.dir1 + pstress.dir2 + pstress.dir3)/3.0;
01282   dpsts.dir1 = pstress.dir1 - piso;
01283   dpsts.dir3 = pstress.dir3 - piso;
01284   /* Computes the principal efetive stress
01285   */
01286   PrincipalTensor( &estr[i], &epsts );
01287   
01288   /* Write results on output file
01289   */
01290   
01291   for( j = 0; j < Config.numgaussresults; j++){
01292    if((strcmp( Config.gaussresults[j], "Yield" ) == 0))
01293     fprintf( out, "%+10.5e\t", yield[i] );
01294    else if((strcmp( Config.gaussresults[j], "Rf" ) == 0))
01295     fprintf( out, "%+10.5e\t", stress[i].rf );
01296    else if((strcmp( Config.gaussresults[j], "Sxx" ) == 0))
01297     fprintf( out, "%+10.5e\t", stress[i].xx );
01298    else if((strcmp( Config.gaussresults[j], "Syy" ) == 0))
01299     fprintf( out, "%+10.5e\t", stress[i].yy );
01300    else if((strcmp( Config.gaussresults[j], "Sxy" ) == 0))
01301     fprintf( out, "%+10.5e\t", stress[i].xy );
01302    else if((strcmp( Config.gaussresults[j], "Pf" ) == 0))
01303     fprintf( out, "%+10.5e\t", poropressure );
01304    else if((strcmp( Config.gaussresults[j], "SExx" ) == 0))
01305     fprintf( out, "%+10.5e\t", estr[i].xx );
01306    else if((strcmp( Config.gaussresults[j], "SEyy" ) == 0))
01307     fprintf( out, "%+10.5e\t", estr[i].yy );
01308    else if((strcmp( Config.gaussresults[j], "Siso" ) == 0))
01309     fprintf( out, "%+10.5e\t", iso );
01310    else if((strcmp( Config.gaussresults[j], "SDxx" ) == 0))
01311     fprintf( out, "%+10.5e\t", strd[i].xx );
01312    else if((strcmp( Config.gaussresults[j], "SDyy" ) == 0))
01313     fprintf( out, "%+10.5e\t", strd[i].yy );
01314    else if((strcmp( Config.gaussresults[j], "S1" ) == 0))
01315     fprintf( out, "%+10.5e\t", pstress.dir1 );
01316    else if((strcmp( Config.gaussresults[j], "S3" ) == 0))
01317     fprintf( out, "%+10.5e\t", pstress.dir3 );
01318    else if((strcmp( Config.gaussresults[j], "SE1" ) == 0))
01319     fprintf( out, "%+10.5e\t", epsts.dir1 );
01320    else if((strcmp( Config.gaussresults[j], "SE3" ) == 0))
01321     fprintf( out, "%+10.5e\t", epsts.dir3 );
01322    else if((strcmp( Config.gaussresults[j], "SD1" ) == 0))
01323     fprintf( out, "%+10.5e\t", dpsts.dir1 );
01324    else if((strcmp( Config.gaussresults[j], "SD3" ) == 0))
01325     fprintf( out, "%+10.5e\t", dpsts.dir3 );
01326    else if((strcmp( Config.gaussresults[j], "Exx" ) == 0))
01327     fprintf( out, "%+10.5e\t", strain[i].xx );
01328    else if((strcmp( Config.gaussresults[j], "Eyy" ) == 0))
01329     fprintf( out, "%+10.5e\t", strain[i].yy );
01330    else if((strcmp( Config.gaussresults[j], "Exy" ) == 0))
01331     fprintf( out, "%+10.5e\t", strain[i].xy );
01332    else if((strcmp( Config.gaussresults[j], "E1" ) == 0))
01333     fprintf( out, "%+10.5e\t", pstrain.dir1 );
01334    else if((strcmp( Config.gaussresults[j], "E3" ) == 0))
01335     fprintf( out, "%+10.5e\t", pstrain.dir3 );
01336    else if((strcmp( Config.gaussresults[j], "Ev" ) == 0))
01337     fprintf( out, "%+10.5e\t", (pstrain.dir1+pstrain.dir2+pstrain.dir3) );
01338    else if((strcmp( Config.gaussresults[j], "K0" ) == 0)){
01339     if(estr[i].yy != 0.0){
01340      fprintf( out, "%+10.5e\t", (estr[i].xx/estr[i].yy) );
01341     }
01342     else{
01343      fprintf( out, "%+10.5e\t", 0.0 );
01344     }
01345    }
01346   }
01347  }
01348 
01349 } /* End of Q4WriteGaussResult */
01350 
01351 
01352 /*
01353 %F
01354 */
01355 static void Q4WriteGaussVectorResult( sElement *elm, int version, FILE *out,
01356                                       FILE *tmp )
01357 {
01358  sTensor  stress[4];
01359  sTensor  strain[4];
01360  sTensor  strd[4];
01361  sPTensor pstress, pstrain;
01362  double   yield[4];
01363  int      i;
01364 
01365 /* Read results from temporary file
01366  */
01367  fread( stress, sizeof(sTensor), 4, tmp );
01368  fread( strain, sizeof(sTensor), 4, tmp );
01369  fread( strd, sizeof(sTensor), 4, tmp );
01370  fread( yield, sizeof(double), 4, tmp );
01371 
01372 /* Write results on output file
01373  */
01374  fprintf( out, "%d\t%d\n", elm->label, 4 );
01375  for( i = 0; i < 4; i++ ) {
01376   PrincipalTensor( &stress[i], &pstress );
01377   PrincipalTensor( &strain[i], &pstrain );
01378 
01379   if( version > 1 ) {
01380    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.dir1, pstrain.dir1 );
01381    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.dir2, pstrain.dir2 );
01382    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.dir3, pstrain.dir3 );
01383    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos1x, pstrain.cos1x );
01384    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos2x, pstrain.cos2x );
01385    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos3x, pstrain.cos3x );
01386    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos1y, pstrain.cos1y );
01387    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos2y, pstrain.cos2y );
01388    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos3y, pstrain.cos3y );
01389    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos1z, pstrain.cos1z );
01390    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos2z, pstrain.cos2z );
01391    fprintf( out, "%+10.5e\t%+10.5e\n", pstress.cos3z, pstrain.cos3z );
01392   }
01393   else {
01394    if( pstress.dir1 > 0.0 )
01395     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstress.dir1*pstress.cos1x),
01396                                                  (pstress.dir1*pstress.cos1y),
01397                                                   0.0 );
01398    else
01399     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01400 
01401    if( pstress.dir1 < 0.0 )
01402     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstress.dir1*pstress.cos1x),
01403                                                  (pstress.dir1*pstress.cos1y),
01404                                                   0.0 );
01405    else
01406     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01407 
01408    if( pstress.dir3 > 0.0 )
01409     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstress.dir3*pstress.cos3x),
01410                                                  (pstress.dir3*pstress.cos3y),
01411                                                   0.0 );
01412    else
01413     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01414 
01415    if( pstress.dir3 < 0.0 )
01416     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstress.dir3*pstress.cos3x),
01417                                                  (pstress.dir3*pstress.cos3y),
01418                                                   0.0 );
01419    else
01420     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01421 
01422    if( pstrain.dir1 > 0.0 )
01423     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstrain.dir1*pstrain.cos1x),
01424                                                  (pstrain.dir1*pstrain.cos1y),
01425                                                   0.0 );
01426    else
01427     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01428 
01429    if( pstrain.dir1 < 0.0 )
01430     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstrain.dir1*pstrain.cos1x),
01431                                                  (pstrain.dir1*pstrain.cos1y),
01432                                                   0.0 );
01433    else
01434     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01435 
01436    if( pstrain.dir3 > 0.0 )
01437     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstrain.dir3*pstrain.cos3x),
01438                                                  (pstrain.dir3*pstrain.cos3y),
01439                                                   0.0 );
01440    else
01441     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01442 
01443    if( pstrain.dir3 < 0.0 )
01444     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", (pstrain.dir3*pstrain.cos3x),
01445                                                  (pstrain.dir3*pstrain.cos3y),
01446                                                   0.0 );
01447    else
01448     fprintf( out, "%+10.5e\t%+10.5e\t%+10.5e\n", 0.0, 0.0, 0.0 );
01449   }
01450  }
01451 
01452 } /* End of Q4WriteGaussVectorResult */
01453 
01454 
01455 /*
01456 %F This function update the element stress to reflect the effects of
01457    the larges displacements.
01458 */
01459 static void Q4UpdateStress( sElement *elm, double dtime, double *V,
01460                                                         sTensor *stre )
01461 {
01462  sQ4Data *data = 0L;
01463  sCoord    coord[4];
01464  double    bm[3][8];
01465  double    ve[8];
01466  double    sxx, syy, rot;
01467  int       i, j, k, npg;
01468 
01469 /* Get element descriptor
01470  */
01471  data = (sQ4Data *)elm->data;
01472 
01473 /* Get element coordinates
01474  */
01475  _Q4GetCoord( elm, coord );
01476 
01477 /* Get element displacement increment
01478  */
01479  _Q4GetDisplacement( elm, V, ve );
01480 
01481 /* Compute the displacement increment
01482  */
01483  for( i = 0; i < 8; i++ )
01484   ve[i] *= dtime;
01485 
01486 /* Update the element stress for each gauss point
01487  */
01488  npg = 0;
01489  for( j = 0; j < 2; j++ ) {
01490   for( i = 0; i < 2; i++ ) {
01491   /* Get element stress x strain matrix
01492    */
01493    _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
01494 
01495   /* Compute rotation factor
01496    */
01497    rot = 0.0;
01498    for( k = 0; k < 8; k++ )
01499     rot += bm[2][i] * ve[i] * pow( -1.0, (double)(i+1) );
01500    rot *= 0.5;
01501 
01502   /* Compute the element stress
01503    */
01504    sxx = stre[npg].xx;
01505    syy = stre[npg].yy;
01506 
01507    stre[npg].xx -= 2.0 * stre[npg].xy * rot;
01508    stre[npg].yy += 2.0 * stre[npg].xy * rot;
01509    stre[npg].xy += (sxx - syy) * rot;
01510 
01511   /* Update gauss point number
01512    */
01513    npg++;
01514 
01515   }
01516  }
01517 
01518 } /* End of Q4UpdateStress */
01519 
01520 
01521 /*
01522 %F
01523 */
01524 static void Q4TimeStep( sElement *elm, double *dt )
01525 {
01526  sCoord     coord[4];
01527  double     hmin, dtime;
01528  sQ4Data   *data = 0L;
01529  sMaterial *mat  = 0L;
01530 
01531 /* Get element coordinates
01532  */
01533  _Q4GetCoord( elm, coord );
01534 
01535 /* Compute the element minimum height
01536  */
01537  hmin = _Q4MinHeight( coord );
01538 
01539 /* Get element data
01540  */
01541  data = (sQ4Data *)elm->data;
01542 
01543 /* Get material object
01544  */
01545  mat = MatList[data->matid-1];
01546 
01547 /* Compute the time step according the material type
01548  */
01549  MatTimeStep( mat, &dtime );
01550 
01551 /* Compute the time step
01552  */
01553  if( mat->type == KELVIN ) (*dt) = dtime;
01554  else                      (*dt) = hmin * dtime;
01555 
01556 } /* End of Q4TimeStep */
01557 
01558 
01559 /*
01560 %F
01561 */
01562 static void Q4PercForces( sElement *elm, double *pforce )
01563 {
01564  sCoord     coord[4];
01565  sQ4Data   *data = 0L;
01566  sMaterial *mat  = 0L;
01567  double     bm[3][8], phi[4], jac[2][2], shape[4];
01568  double     detjac;
01569  sTensor    grad;
01570  int        i, j, k;
01571 
01572 /* Get element coordinates
01573  */
01574  _Q4GetCoord( elm, coord );
01575 
01576 /* Get element data
01577  */
01578  data = (sQ4Data *)elm->data;
01579 
01580 /* Get material object
01581  */
01582  mat = MatList[data->matid-1];
01583 
01584 /* Get element pressure
01585  */
01586  for( i = 0; i < data->NumNodes; i++ )
01587   phi[i] = elm->nodes[data->inc[i]-1].dof.psi + coord[i].y;
01588 
01589  for( i = 0; i < 8; i++ )
01590   pforce[i] = 0.0;
01591 
01592 /* Compute percolation forces
01593  */
01594  for( j = 0; j < 2; j++ ) {
01595   for( i = 0; i < 2; i++ ) {
01596   /* Get element stress x strain matrix
01597    */
01598    _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
01599 
01600   /* Get element jacobiam
01601    */
01602    _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &detjac, jac );
01603 
01604    detjac *= _GWeight[i] * _GWeight[j] * mat->Rhof;
01605 
01606   /* Get element shape functions
01607    */
01608    _Q4ShapeFunc( _GPoint[i], _GPoint[j], shape );
01609 
01610   /* Compute gradient
01611    */
01612    grad.xx = grad.yy = 0.0;
01613    for( k = 0; k < 4; k++ ) {
01614     grad.xx += bm[0][2*k] * phi[k];
01615     grad.yy += bm[1][2*k+1] * phi[k];
01616    }
01617 
01618    for( k = 0; k < 4; k++ ) {
01619     pforce[2*k]   += detjac * shape[k] * grad.xx;
01620     pforce[2*k+1] += detjac * shape[k] * grad.yy;
01621    }
01622 
01623   }
01624  }
01625 
01626 } /* End of Q4PercForces */
01627 
01628 
01629 /*
01630 %F
01631 */
01632 static void Q4SetPressure( sElement *elm, double pot )
01633 {
01634  sCoord   coord[4];
01635  sQ4Data *data = 0L;
01636  int      i, id;
01637 
01638 /* Get element coordinates
01639  */
01640  _Q4GetCoord( elm, coord );
01641 
01642 /* Get element data
01643  */
01644  data = (sQ4Data *)elm->data;
01645 
01646 /* Compute and set the pressure for the element node
01647  */
01648  for( i = 0; i < 4; i++ ) {
01649   id = data->inc[i] - 1;
01650   elm->nodes[id].dof.psi = pot - coord[i].y;
01651  }
01652 
01653 } /* End of Q4SetPressure */
01654 
01655 /*
01656 %F
01657 */
01658 static void Q4SetInitStress( sElement *elm, sTensor *istress )
01659 {
01660  sQ4Data *data = 0L;
01661  int      i;
01662 
01663 /* Get element data
01664  */
01665  data = (sQ4Data *)elm->data;
01666 
01667 /* Set initial stress
01668  */
01669  for( i = 0; i < 4; i++ ) {
01670   data->istr[i][0] = istress[i].xx;
01671   data->istr[i][1] = istress[i].yy;
01672   data->istr[i][2] = istress[i].xy;
01673  }
01674 
01675 } /* End of Q4SetInitStress */
01676 
01677 /*
01678 %F
01679 */
01680 static void Q4ViscoForce( sElement *elm, double timeStep, sTensor *stress,
01681                           double *vforce )
01682 {
01683  int        i, j, k, l, npg;
01684  double     coeff;
01685  double     bm[3][8], jac[2][2], cm[6][6];
01686  double     stav[3], strv[4], force[8];
01687  sTensor    vsta;
01688  sCoord     coord[4];
01689  sQ4Data   *data = 0L;
01690  sMaterial *mat  = 0L;
01691 
01692 /* Get element descriptor
01693  */
01694  data = (sQ4Data *)elm->data;
01695 
01696 /* Get material object
01697  */
01698  mat = MatList[data->matid-1];
01699 
01700 /* Initialize element visco forces vector
01701  */
01702  for( i = 0; i < (2*data->NumNodes); i++ )
01703   vforce[i] = 0.0;
01704 
01705 /* Check to see if the material is a visco one
01706  */
01707  if( !MaterialIsVisco( mat ) )
01708   return;
01709 
01710 /* Get element coordinates
01711  */
01712  _Q4GetCoord( elm, coord );
01713 
01714 /* Get material constitutive matrix
01715  */
01716  MatConstitutiveMatrix( mat, cm );
01717 
01718 /* Compute visco force for each gauss point
01719  */
01720  npg = 0;
01721  for( j = 0; j < 2; j++ ) {
01722   for( i = 0; i < 2; i++ ) {
01723   /* Compute element B matrix
01724    */
01725    _Q4BMatrix( _GPoint[i], _GPoint[j], coord, bm );
01726 
01727   /* Compute rigidity coefficient
01728    */
01729    _Q4Jacobian( _GPoint[i], _GPoint[j], coord, &coeff, jac );
01730 
01731    coeff *= _GWeight[i] * _GWeight[j];
01732 
01733   /* Compute visco stress
01734    */
01735    MatViscoStrain( mat, timeStep, &stress[npg], &vsta );
01736 
01737   /* Get viscos strain components
01738    */
01739    stav[0] = vsta.xx;
01740    stav[1] = vsta.yy;
01741    stav[2] = vsta.xy;
01742    stav[3] = 0.0;
01743 
01744   /* Compute viscos stress
01745    */
01746    for( k = 0; k < 3; k++ ) {
01747     strv[k] = 0.0;
01748     for( l = 0; l < 3; l++ )
01749      strv[k] += cm[k][l] * stav[l];
01750    }
01751    strv[3] = 0.0;
01752 
01753   /* Compute element visco forces for the current gauss point
01754    */
01755    for( k = 0; k < (2*data->NumNodes); k++ ) {
01756     force[k] = 0.0;
01757     for( l = 0; l < 3; l++ )
01758      force[k] += bm[l][k] * strv[l];
01759     force[k] *= coeff;
01760    } 
01761 
01762   /* Add in the element vector
01763    */
01764    for( k = 0; k < (2*data->NumNodes); k++ )
01765     vforce[k] += force[k];
01766 
01767   /* Update gauss point number
01768    */
01769    npg++;
01770 
01771   }
01772  }
01773 
01774 } /* End of Q4ViscoForce */
01775 
01776 /*============================ Q4KMatrix ===========================*/
01777 
01778 static void Q4KMatrix( sElement *elm, double k[24][24] )
01779 {
01780  int    r, s;           
01781  int    i, j, l;           
01782  sCoord  coord[4];          
01783  double jac[2][2];         
01784  double detjac;            
01785  double C[6][6];          
01786  double B[3][8];          
01787  double BTC[8][3];        
01788  double ke[24][24]; 
01789  sQ4Data  *data = 0L;
01790  sMaterial  *mat  = 0L;       
01791 
01792  /* Inicia matriz k = 0
01793  */
01794  for( i = 0; i < 24; i++ ) {
01795   for( j = 0; j < 24; j++ ) {
01796    k[i][j] = 0.0;
01797   }
01798  }
01799  
01800  /* Pega descrição do elemento
01801  */
01802  data = (sQ4Data *)elm->data;
01803  
01804 /* Pega material
01805  */
01806  mat = MatList[data->matid-1];
01807  
01808  /* Pega as coordenadas nodais
01809  */
01810  _Q4GetCoord(elm, coord);
01811  
01812  /* Pega matriz constitutiva [C]*/
01813  MatConstitutiveMatrix( mat, C );
01814 
01815  for( s = 0; s < 2; s++ ) {
01816   for( r = 0; r < 2; r++ ) {
01817    /* Calcula matriz B*/
01818    _Q4BMatrix( _GPoint[r], _GPoint[s], coord, B );
01819    /* Calcula o determinante do jacobiano */
01820    _Q4Jacobian( _GPoint[r], _GPoint[s],  coord, &detjac, jac );
01821  
01822    /* Calcula [B] transposto * [C] */
01823    for( i = 0; i < 8; i++ ) {
01824     for( j = 0; j < 3; j++)  {
01825      BTC[i][j] =0.0;
01826      for(l=0; l<3; l++){
01827       BTC[i][j] += B[l][i]*C[l][j];
01828      }
01829     }
01830    }
01831    /* Calcula [B] transposto * [C] * [B] * |jac|*/
01832    for( i = 0; i < 8; i++ ) {
01833     for( j = 0; j < 8; j++)  {
01834      ke[i][j] =0.0;
01835      for(l=0; l<3; l++){
01836       ke[i][j] += BTC[i][l]*B[l][j]*detjac;
01837      }
01838     }
01839    }
01840    /* Calcula matriz de rigidez do elemento*/
01841    for( i = 0; i < 8; i++ ) {
01842     for( j = 0; j < 8; j++)  {
01843      k[i][j] += ke[i][j];
01844     }
01845    }
01846   }
01847  }
01848 } /* Q4KMatrix */
01849 
01850 static void Q4GetDof( sElement *elm, int u[24], int *index )
01851 {
01852  sQ4Data *data = 0L;
01853  int        i;
01854 
01855 /* Get element descriptor
01856  */
01857  data = (sQ4Data *)elm->data;
01858 
01859 /* Fill element dof
01860  */
01861  for( i = 0; i < data->NumNodes; i++ ) {
01862   u[2*i]   = 2*(data->inc[i]-1);
01863   u[2*i+1] = 2*(data->inc[i]-1)+1;
01864  }
01865  
01866  *index = 8;
01867 
01868 } /* End of _Q4GetDof */
01869 
01870 static void Q4GetInc( sElement *elm, int inc[8], int *index )
01871 {
01872  sQ4Data *data = 0L;
01873  int        i;
01874 
01875 /* Get element descriptor
01876  */
01877  data = (sQ4Data *)elm->data;
01878 
01879 /* Fill element dof
01880  */
01881  for( i = 0; i < data->NumNodes; i++ ) {
01882   inc[i]   = data->inc[i]-1;
01883  }
01884  
01885  *index = 4;
01886 
01887 } /* End of Q4GetInc */
01888 
01889 
01890 /*
01891 ** ------------------------------------------------------------------------
01892 ** Public functions:
01893 */
01894 
01895 /*
01896 %F This function initializes the sub-class "Q4".
01897 */
01898 void Q4Init( void );
01899 void Q4Init( void )
01900 {
01901 /* Initialize Q4 element sub-class
01902  */
01903  ElmClass[Q4].new               = Q4New;
01904  ElmClass[Q4].free              = Q4Free;
01905  ElmClass[Q4].read              = Q4Read;
01906  ElmClass[Q4].readinitstr       = Q4ReadInitStress;
01907  ElmClass[Q4].readprofile       = Q4ReadProfile;
01908  ElmClass[Q4].mass              = Q4MassMatrix;
01909  ElmClass[Q4].rigidcoeff        = Q4RigidCoeff;
01910  ElmClass[Q4].load              = Q4Load;
01911  ElmClass[Q4].connect           = Q4Connect;
01912  ElmClass[Q4].numnodes          = Q4NumNodes;
01913  ElmClass[Q4].gravity           = Q4Gravity;
01914  ElmClass[Q4].assvector         = Q4AssVector;
01915  ElmClass[Q4].strstrain         = Q4StressStrain;
01916  ElmClass[Q4].timestep          = Q4TimeStep;
01917  ElmClass[Q4].intforce          = Q4InterForce;
01918  ElmClass[Q4].writestr          = Q4WriteStress;
01919  ElmClass[Q4].writendlresult    = Q4WriteNodalResult;
01920  ElmClass[Q4].writegauresult    = Q4WriteGaussResult;
01921  ElmClass[Q4].writegauvecresult = Q4WriteGaussVectorResult;
01922  ElmClass[Q4].updatestress      = Q4UpdateStress;
01923  ElmClass[Q4].percforce         = Q4PercForces;
01924  ElmClass[Q4].setpressure       = Q4SetPressure;
01925  ElmClass[Q4].setinitstress     = Q4SetInitStress;
01926  ElmClass[Q4].viscoforce        = Q4ViscoForce;
01927  ElmClass[Q4].jacobian          = 0L;
01928  ElmClass[Q4].volume            = 0L;
01929  ElmClass[Q4].KMatrix           = Q4KMatrix;
01930  ElmClass[Q4].GetDof            = Q4GetDof;
01931  ElmClass[Q4].GetInc            = Q4GetInc;
01932  
01933 } /* End of Q4Init */
01934 
01935 
01936 /* =======================================================  End of File  */
01937 

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