00001
00002
00003
00004
00005
00006
00007
00008 #include <iostream.h>
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <math.h>
00012
00013 #include <ID.h>
00014 #include <Vector.h>
00015 #include <Matrix.h>
00016 #include <Element.h>
00017 #include <Node.h>
00018 #include <NDMaterial.h>
00019 #include <Domain.h>
00020 #include <ErrorHandler.h>
00021 #include <ConstantPressureVolumeQuad.h>
00022
00023
00024 Matrix ConstantPressureVolumeQuad :: stiff(8,8) ;
00025 Vector ConstantPressureVolumeQuad :: resid(8) ;
00026 Matrix ConstantPressureVolumeQuad :: mass(8,8) ;
00027 Matrix ConstantPressureVolumeQuad :: damping(8,8) ;
00028
00029
00030 double ConstantPressureVolumeQuad :: one3 = 1.0 / 3.0 ;
00031 double ConstantPressureVolumeQuad :: two3 = 2.0 / 3.0 ;
00032 double ConstantPressureVolumeQuad :: four3 = 4.0 / 3.0 ;
00033 double ConstantPressureVolumeQuad :: one9 = 1.0 / 9.0 ;
00034
00035
00036 double ConstantPressureVolumeQuad :: root3 = sqrt(3.0) ;
00037 double ConstantPressureVolumeQuad :: one_over_root3 = 1.0 / root3 ;
00038
00039 double ConstantPressureVolumeQuad :: sg[] = { -one_over_root3,
00040 one_over_root3,
00041 one_over_root3,
00042 -one_over_root3 } ;
00043
00044 double ConstantPressureVolumeQuad :: tg[] = { -one_over_root3,
00045 -one_over_root3,
00046 one_over_root3,
00047 one_over_root3 } ;
00048
00049 double ConstantPressureVolumeQuad :: wg[] = { 1.0, 1.0, 1.0, 1.0 } ;
00050
00051
00052
00053 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( ) :
00054 Element( 0, ELE_TAG_ConstantPressureVolumeQuad ),
00055 connectedExternalNodes(4)
00056 {
00057 return ;
00058 }
00059
00060
00061
00062 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad(
00063 int tag,
00064 int node1,
00065 int node2,
00066 int node3,
00067 int node4,
00068 NDMaterial &theMaterial ) :
00069 Element( tag, ELE_TAG_ConstantPressureVolumeQuad ),
00070 connectedExternalNodes(4)
00071 {
00072 connectedExternalNodes(0) = node1 ;
00073 connectedExternalNodes(1) = node2 ;
00074 connectedExternalNodes(2) = node3 ;
00075 connectedExternalNodes(3) = node4 ;
00076
00077 int i ;
00078 for ( i = 0 ; i < 4; i++ ) {
00079
00080 materialPointers[i] = theMaterial.getCopy("AxiSymmetric2D") ;
00081
00082 if (materialPointers[i] == 0) {
00083
00084 g3ErrorHandler->fatal("ConstantPressureVolumeQuad::constructor %s",
00085 "- failed to get a material of type: AxiSymmetric2D");
00086 }
00087
00088 }
00089
00090 }
00091
00092
00093
00094 ConstantPressureVolumeQuad :: ~ConstantPressureVolumeQuad( )
00095 {
00096 int i ;
00097 for ( i = 0 ; i < 4; i++ ) {
00098
00099 delete materialPointers[i] ;
00100 materialPointers[i] = 0 ;
00101
00102 nodePointers[i] = 0 ;
00103 }
00104
00105 }
00106
00107
00108
00109 void ConstantPressureVolumeQuad :: setDomain( Domain *theDomain )
00110 {
00111 int i ;
00112 for ( i = 0; i < 4; i++ ) {
00113
00114 nodePointers[i] = theDomain->getNode( connectedExternalNodes(i) ) ;
00115
00116 if ( nodePointers[i] != 0 ) {
00117 const Vector &coor = nodePointers[i]->getCrds( ) ;
00118
00119 xl[0][i] = coor(0) ;
00120 xl[1][i] = coor(1) ;
00121 }
00122
00123 }
00124
00125 this->DomainComponent::setDomain(theDomain);
00126 }
00127
00128
00129
00130 int ConstantPressureVolumeQuad :: getNumExternalNodes( ) const
00131 {
00132 return 4 ;
00133 }
00134
00135
00136
00137 const ID& ConstantPressureVolumeQuad :: getExternalNodes( )
00138 {
00139 return connectedExternalNodes ;
00140 }
00141
00142
00143
00144 int ConstantPressureVolumeQuad :: getNumDOF( )
00145 {
00146 return 8 ;
00147 }
00148
00149
00150
00151 int ConstantPressureVolumeQuad :: commitState( )
00152 {
00153 int i ;
00154 int success = 0 ;
00155
00156 for ( i = 0; i < 4; i++ )
00157 success += materialPointers[i]->commitState( ) ;
00158
00159 return success ;
00160 }
00161
00162
00163
00164
00165 int ConstantPressureVolumeQuad :: revertToLastCommit( )
00166 {
00167 int i ;
00168 int success = 0 ;
00169
00170 for ( i = 0; i < 4; i++ )
00171 success += materialPointers[i]->revertToLastCommit( ) ;
00172
00173 return success ;
00174 }
00175
00176
00177
00178 int ConstantPressureVolumeQuad :: revertToStart( )
00179 {
00180 int i ;
00181 int success = 0 ;
00182
00183 for ( i = 0; i < 4; i++ )
00184 success += materialPointers[i]->revertToStart( ) ;
00185
00186 return success ;
00187 }
00188
00189
00190 void ConstantPressureVolumeQuad :: Print( ostream &s, int flag )
00191 {
00192 s << '\n' ;
00193 s << "Four Node Quad -- Mixed Pressure/Volume -- Plane Strain \n" ;
00194 s << "Node 1 : " << connectedExternalNodes(0) << '\n' ;
00195 s << "Node 2 : " << connectedExternalNodes(1) << '\n' ;
00196 s << "Node 3 : " << connectedExternalNodes(2) << '\n' ;
00197 s << "Node 4 : " << connectedExternalNodes(3) << '\n' ;
00198 s << "Material Information : \n " ;
00199
00200 materialPointers[0]->Print( s, flag ) ;
00201
00202 s << endl ;
00203 }
00204
00205
00206 const Matrix& ConstantPressureVolumeQuad :: getTangentStiff( )
00207 {
00208 int tang_flag = 1 ;
00209
00210
00211 formResidAndTangent( tang_flag ) ;
00212
00213 return stiff ;
00214 }
00215
00216
00217
00218 const Matrix& ConstantPressureVolumeQuad :: getSecantStiff( )
00219 {
00220 int tang_flag = 1 ;
00221
00222
00223 formResidAndTangent( tang_flag ) ;
00224
00225 return stiff ;
00226 }
00227
00228
00229
00230 const Matrix& ConstantPressureVolumeQuad :: getDamp( )
00231 {
00232
00233 return damping ;
00234 }
00235
00236
00237
00238 const Matrix& ConstantPressureVolumeQuad :: getMass( )
00239 {
00240
00241 return mass ;
00242 }
00243
00244
00245
00246 void ConstantPressureVolumeQuad :: zeroLoad( )
00247 {
00248 return ;
00249 }
00250
00251
00252 int ConstantPressureVolumeQuad :: addLoad( const Vector &addP )
00253 {
00254 return -1 ;
00255 }
00256
00257
00258
00259 const Vector& ConstantPressureVolumeQuad :: getResistingForce( )
00260 {
00261 int tang_flag = 0 ;
00262
00263 formResidAndTangent( tang_flag ) ;
00264
00265 return resid ;
00266 }
00267
00268
00269
00270 const Vector& ConstantPressureVolumeQuad :: getResistingForceIncInertia( )
00271 {
00272 int tang_flag = 0 ;
00273
00274
00275 formResidAndTangent( tang_flag ) ;
00276
00277 return resid ;
00278 }
00279
00280
00281
00282
00283
00284 void ConstantPressureVolumeQuad :: formResidAndTangent( int tang_flag )
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 int i, j, k, l ;
00297 int ii, jj, kk ;
00298 int node ;
00299 int success ;
00300
00301 double tmp_shp[3][4] ;
00302
00303 double shp[3][4][4] ;
00304
00305 double vol_avg_shp[3][4] ;
00306
00307 double xsj ;
00308
00309 static Matrix sx(2,2) ;
00310
00311 double dvol[4] ;
00312
00313 double volume = 0.0 ;
00314
00315 double theta = 0.0 ;
00316
00317 double pressure = 0.0 ;
00318
00319 static Vector strain(4) ;
00320
00321 static Vector sigBar(4) ;
00322 static Vector sig(4) ;
00323
00324 double trace = 0.0 ;
00325
00326 static Matrix BJ(4,2) ;
00327 static Matrix BJtran(2,4) ;
00328 static Matrix BK(4,2) ;
00329
00330 static Matrix littleBJ(1,2) ;
00331 static Matrix littleBJtran(2,1) ;
00332 static Matrix littleBK(1,2) ;
00333
00334 static Matrix stiffJK(2,2) ;
00335 static Vector residJ(2) ;
00336
00337 static Vector one(4) ;
00338 static Matrix oneMatrix(4,1) ;
00339 static Matrix oneTran(1,4) ;
00340
00341 static Matrix Pdev(4,4) ;
00342
00343 static Matrix dd(4,4) ;
00344
00345 static Matrix Pdev_dd_Pdev(4,4) ;
00346 static Matrix Pdev_dd_one(4,1) ;
00347 static Matrix one_dd_Pdev(1,4) ;
00348 double bulk ;
00349 static Matrix BJtranD(2,4) ;
00350 static Matrix BJtranDone(2,1) ;
00351 static Matrix littleBJoneD(2,4) ;
00352 static Matrix littleBJtranBulk(2,1) ;
00353
00354
00355 stiff.Zero( ) ;
00356 resid.Zero( ) ;
00357
00358
00359 one(0) = 1.0 ;
00360 one(1) = 1.0 ;
00361 one(2) = 1.0 ;
00362 one(3) = 0.0 ;
00363
00364
00365 oneMatrix(0,0) = 1.0 ;
00366 oneMatrix(1,0) = 1.0 ;
00367 oneMatrix(2,0) = 1.0 ;
00368 oneMatrix(3,0) = 0.0 ;
00369 oneTran = this->transpose( 4, 1, oneMatrix ) ;
00370
00371
00372 Pdev.Zero( ) ;
00373
00374 Pdev(0,0) = two3 ;
00375 Pdev(0,1) = -one3 ;
00376 Pdev(0,2) = -one3 ;
00377
00378 Pdev(1,0) = -one3 ;
00379 Pdev(1,1) = two3 ;
00380 Pdev(1,2) = -one3 ;
00381
00382 Pdev(2,0) = -one3 ;
00383 Pdev(2,1) = -one3 ;
00384 Pdev(2,2) = two3 ;
00385
00386 Pdev(3,3) = 1.0 ;
00387
00388
00389
00390 volume = 0.0 ;
00391
00392 for ( k = 0; k < 3; k++ ){
00393 for ( l = 0; l < 4; l++ )
00394 vol_avg_shp[k][l] = 0.0 ;
00395 }
00396
00397
00398
00399
00400 for ( i = 0; i < 4; i++ ){
00401
00402 shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00403
00404 dvol[i] = wg[i] * xsj ;
00405
00406 volume += dvol[i] ;
00407
00408 for ( k = 0; k < 3; k++ ){
00409 for ( l = 0; l < 4; l++ ) {
00410
00411 shp[k][l][i] = tmp_shp[k][l] ;
00412
00413 vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00414
00415 }
00416 }
00417
00418 }
00419
00420
00421
00422 for ( k = 0; k < 3; k++ ){
00423 for ( l = 0; l < 4; l++ )
00424 vol_avg_shp[k][l] /= volume ;
00425 }
00426
00427
00428
00429 theta = 0.0 ;
00430 for ( i = 0; i < 4; i++ ) {
00431
00432 strain.Zero( ) ;
00433
00434
00435 for ( node = 0; node < 4; node++ ) {
00436
00437 const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00438
00439 strain(0) += shp[0][node][i] * ul(0) ;
00440
00441 strain(1) += shp[1][node][i] * ul(1) ;
00442
00443 strain(2) = 0.0 ;
00444
00445
00446 }
00447
00448 trace = strain(0) + strain(1) + strain(2) ;
00449
00450 theta += trace * dvol[i] ;
00451
00452 }
00453 theta /= volume ;
00454
00455
00456
00457 pressure = 0.0 ;
00458 for ( i = 0; i < 4; i++ ) {
00459
00460 strain.Zero( ) ;
00461
00462
00463 for ( node = 0; node < 4; node++ ) {
00464
00465 const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00466
00467 strain(0) += shp[0][node][i] * ul(0) ;
00468
00469 strain(1) += shp[1][node][i] * ul(1) ;
00470
00471 strain(2) = 0.0 ;
00472
00473 strain(3) += shp[1][node][i] * ul(0)
00474 + shp[0][node][i] * ul(1) ;
00475
00476 }
00477
00478 trace = strain(0) + strain(1) + strain(2) ;
00479
00480 strain -= (one3*trace)*one ;
00481 strain += (one3*theta)*one ;
00482
00483 success = materialPointers[i]->setTrialStrain( strain ) ;
00484
00485 const Vector &sigBar = materialPointers[i]->getStress( ) ;
00486
00487 pressure += one3 * ( sigBar(0) + sigBar(1) + sigBar(2) ) * dvol[i] ;
00488
00489 }
00490 pressure /= volume ;
00491
00492
00493
00494
00495 for ( i = 0; i < 4; i++ ) {
00496
00497 const Vector &sigBar = materialPointers[i]->getStress( ) ;
00498
00499
00500
00501 trace = sigBar(0) + sigBar(1) + sigBar(2) ;
00502
00503 sig = sigBar ;
00504 sig -= (one3*trace)*one ;
00505 sig += pressure*one ;
00506
00507
00508
00509
00510 sig *= dvol[i] ;
00511
00512 if ( tang_flag == 1 ) {
00513
00514 const Matrix &ddBar = materialPointers[i]->getTangent( ) ;
00515
00516 dd = ddBar * dvol[i] ;
00517
00518 Pdev_dd_Pdev = Pdev * dd * Pdev ;
00519
00520 Pdev_dd_one = one3 * ( Pdev * dd * oneMatrix ) ;
00521
00522 one_dd_Pdev = one3 * ( oneTran * dd * Pdev ) ;
00523
00524 bulk = one9 * ( dd(0,0) + dd(0,1) + dd(0,2)
00525 + dd(1,0) + dd(1,1) + dd(1,2)
00526 + dd(2,0) + dd(2,1) + dd(2,2) ) ;
00527
00528 }
00529
00530
00531
00532
00533 jj = 0 ;
00534 for ( j = 0; j < 4; j++ ) {
00535
00536 BJ.Zero( );
00537 BJ(0,0) = shp[0][j][i] ;
00538 BJ(1,1) = shp[1][j][i] ;
00539
00540
00541
00542 BJ(3,0) = shp[1][j][i] ;
00543 BJ(3,1) = shp[0][j][i] ;
00544
00545
00546 littleBJ(0,0) = vol_avg_shp[0][j] ;
00547 littleBJ(0,1) = vol_avg_shp[1][j] ;
00548
00549 BJtran = this->transpose( 4, 2, BJ ) ;
00550
00551 littleBJtran = this->transpose( 1, 2, littleBJ ) ;
00552
00553
00554
00555 residJ = BJtran * sig ;
00556
00557 resid( jj ) += residJ(0) ;
00558 resid( jj+1 ) += residJ(1) ;
00559
00560 if ( tang_flag == 1 ) {
00561
00562 BJtranD = BJtran * Pdev_dd_Pdev ;
00563 BJtranDone = BJtran * Pdev_dd_one ;
00564 littleBJoneD = littleBJtran * one_dd_Pdev ;
00565 littleBJtranBulk = bulk * littleBJtran ;
00566
00567 kk = 0 ;
00568 for ( k = 0; k < 4; k++ ) {
00569
00570 BK.Zero( );
00571 BK(0,0) = shp[0][k][i] ;
00572 BK(1,1) = shp[1][k][i] ;
00573
00574
00575
00576 BK(3,0) = shp[1][k][i] ;
00577 BK(3,1) = shp[0][k][i] ;
00578
00579
00580 littleBK(0,0) = vol_avg_shp[0][k] ;
00581 littleBK(0,1) = vol_avg_shp[1][k] ;
00582
00583
00584
00585 stiffJK = ( BJtranD + littleBJoneD ) * BK
00586 + ( BJtranDone + littleBJtranBulk ) * littleBK ;
00587
00588 stiff( jj, kk ) += stiffJK(0,0) ;
00589 stiff( jj+1, kk ) += stiffJK(1,0) ;
00590 stiff( jj, kk+1 ) += stiffJK(0,1) ;
00591 stiff( jj+1, kk+1 ) += stiffJK(1,1) ;
00592
00593 kk += 2 ;
00594 }
00595
00596 }
00597
00598
00599 jj += 2 ;
00600 }
00601
00602 }
00603
00604
00605 return ;
00606 }
00607
00608
00609
00610
00611 Matrix ConstantPressureVolumeQuad :: transpose( int dim1,
00612 int dim2,
00613 const Matrix &M )
00614 {
00615 int i ;
00616 int j ;
00617
00618 Matrix Mtran( dim2, dim1 ) ;
00619
00620 for ( i = 0; i < dim1; i++ ) {
00621
00622 for ( j = 0; j < dim2; j++ )
00623 Mtran(j,i) = M(i,j) ;
00624
00625 }
00626
00627 return Mtran ;
00628 }
00629
00630
00631
00632
00633 void ConstantPressureVolumeQuad :: shape2d( double ss, double tt,
00634 const double x[2][4],
00635 double shp[3][4],
00636 double &xsj,
00637 Matrix &sx )
00638 {
00639
00640 int i, j, k ;
00641
00642 double temp ;
00643
00644 static const double s[] = { -0.5, 0.5, 0.5, -0.5 } ;
00645 static const double t[] = { -0.5, -0.5, 0.5, 0.5 } ;
00646
00647 static Matrix xs(2,2) ;
00648
00649 for ( i = 0; i < 4; i++ ) {
00650 shp[2][i] = ( 0.5 + s[i]*ss )*( 0.5 + t[i]*tt ) ;
00651 shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
00652 shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
00653 }
00654
00655
00656
00657
00658 xs.Zero( ) ;
00659 for ( i = 0; i < 2; i++ ) {
00660 for ( j = 0; j < 2; j++ ) {
00661
00662 for ( k = 0; k < 4; k++ )
00663 xs(i,j) += x[i][k] * shp[j][k] ;
00664
00665 }
00666 }
00667
00668 xsj = xs(0,0)*xs(1,1) - xs(0,1)*xs(1,0) ;
00669
00670 sx(0,0) = xs(1,1) / xsj ;
00671 sx(1,1) = xs(0,0) / xsj ;
00672 sx(0,1) = -xs(0,1) / xsj ;
00673 sx(1,0) = -xs(1,0) / xsj ;
00674
00675
00676
00677
00678 for ( i = 0; i < 4; i++ ) {
00679 temp = shp[0][i]*sx(0,0) + shp[1][i]*sx(1,0) ;
00680 shp[1][i] = shp[0][i]*sx(0,1) + shp[1][i]*sx(1,1) ;
00681 shp[0][i] = temp ;
00682 }
00683
00684 return ;
00685 }
00686
00687
00688
00689 int ConstantPressureVolumeQuad :: sendSelf (int commitTag, Channel &theChannel)
00690 {
00691 return -1;
00692 }
00693
00694 int ConstantPressureVolumeQuad :: recvSelf (int commitTag,
00695 Channel &theChannel,
00696 FEM_ObjectBroker &theBroker)
00697 {
00698 return -1;
00699 }
00700