00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <math.h>
00034
00035 #include <ID.h>
00036 #include <Vector.h>
00037 #include <Matrix.h>
00038 #include <Element.h>
00039 #include <Node.h>
00040 #include <NDMaterial.h>
00041 #include <Domain.h>
00042 #include <ErrorHandler.h>
00043 #include <ConstantPressureVolumeQuad.h>
00044 #include <Renderer.h>
00045 #include <ElementResponse.h>
00046 #include <Channel.h>
00047 #include <FEM_ObjectBroker.h>
00048
00049
00050 double ConstantPressureVolumeQuad::matrixData[64];
00051 Matrix ConstantPressureVolumeQuad :: stiff(matrixData,8,8) ;
00052 Vector ConstantPressureVolumeQuad :: resid(8) ;
00053 Matrix ConstantPressureVolumeQuad :: mass(8,8) ;
00054 Matrix ConstantPressureVolumeQuad :: damping(8,8) ;
00055
00056
00057 double ConstantPressureVolumeQuad :: one3 = 1.0 / 3.0 ;
00058 double ConstantPressureVolumeQuad :: two3 = 2.0 / 3.0 ;
00059 double ConstantPressureVolumeQuad :: four3 = 4.0 / 3.0 ;
00060 double ConstantPressureVolumeQuad :: one9 = 1.0 / 9.0 ;
00061
00062
00063 double ConstantPressureVolumeQuad :: root3 = sqrt(3.0) ;
00064 double ConstantPressureVolumeQuad :: one_over_root3 = 1.0 / root3 ;
00065
00066 double ConstantPressureVolumeQuad :: sg[] = { -one_over_root3,
00067 one_over_root3,
00068 one_over_root3,
00069 -one_over_root3 } ;
00070
00071 double ConstantPressureVolumeQuad :: tg[] = { -one_over_root3,
00072 -one_over_root3,
00073 one_over_root3,
00074 one_over_root3 } ;
00075
00076 double ConstantPressureVolumeQuad :: wg[] = { 1.0, 1.0, 1.0, 1.0 } ;
00077
00078
00079
00080 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad( ) :
00081 Element( 0, ELE_TAG_ConstantPressureVolumeQuad ),
00082 connectedExternalNodes(4), load(0)
00083 {
00084 for (int i=0; i<9; i++)
00085 materialPointers[i] = 0;
00086 }
00087
00088
00089
00090 ConstantPressureVolumeQuad :: ConstantPressureVolumeQuad(
00091 int tag,
00092 int node1,
00093 int node2,
00094 int node3,
00095 int node4,
00096 NDMaterial &theMaterial ) :
00097 Element( tag, ELE_TAG_ConstantPressureVolumeQuad ),
00098 connectedExternalNodes(4), load(0)
00099 {
00100 connectedExternalNodes(0) = node1 ;
00101 connectedExternalNodes(1) = node2 ;
00102 connectedExternalNodes(2) = node3 ;
00103 connectedExternalNodes(3) = node4 ;
00104
00105 int i ;
00106 for ( i = 0 ; i < 4; i++ ) {
00107
00108 materialPointers[i] = theMaterial.getCopy("AxiSymmetric2D") ;
00109
00110 if (materialPointers[i] == 0) {
00111 opserr << "ConstantPressureVolumeQuad::constructor - failed to get a material of type: AxiSymmetric2D\n";
00112 exit(-1);
00113 }
00114
00115 }
00116
00117 }
00118
00119
00120
00121 ConstantPressureVolumeQuad :: ~ConstantPressureVolumeQuad( )
00122 {
00123 int i ;
00124 for ( i = 0 ; i < 4; i++ ) {
00125
00126 delete materialPointers[i] ;
00127 materialPointers[i] = 0 ;
00128
00129 nodePointers[i] = 0 ;
00130 }
00131
00132 if (load != 0)
00133 delete load;
00134 }
00135
00136
00137
00138 void ConstantPressureVolumeQuad :: setDomain( Domain *theDomain )
00139 {
00140 int i ;
00141 for ( i = 0; i < 4; i++ ) {
00142
00143 nodePointers[i] = theDomain->getNode( connectedExternalNodes(i) ) ;
00144
00145 if ( nodePointers[i] != 0 ) {
00146 const Vector &coor = nodePointers[i]->getCrds( ) ;
00147
00148 xl[0][i] = coor(0) ;
00149 xl[1][i] = coor(1) ;
00150 }
00151
00152 }
00153
00154 this->DomainComponent::setDomain(theDomain);
00155 }
00156
00157
00158
00159 int ConstantPressureVolumeQuad :: getNumExternalNodes( ) const
00160 {
00161 return 4 ;
00162 }
00163
00164
00165
00166 const ID& ConstantPressureVolumeQuad :: getExternalNodes( )
00167 {
00168 return connectedExternalNodes ;
00169 }
00170
00171
00172 Node **
00173 ConstantPressureVolumeQuad::getNodePtrs(void)
00174 {
00175 return nodePointers;
00176 }
00177
00178
00179
00180 int ConstantPressureVolumeQuad :: getNumDOF( )
00181 {
00182 return 8 ;
00183 }
00184
00185
00186
00187 int ConstantPressureVolumeQuad :: commitState( )
00188 {
00189 int success = 0 ;
00190
00191
00192 if ((success = this->Element::commitState()) != 0) {
00193 opserr << "ConstantPressureVolumeQuad::commitState () - failed in base class";
00194 }
00195
00196 for (int i = 0; i < 4; i++ )
00197 success += materialPointers[i]->commitState( ) ;
00198
00199 return success ;
00200 }
00201
00202
00203
00204
00205 int ConstantPressureVolumeQuad :: revertToLastCommit( )
00206 {
00207 int i ;
00208 int success = 0 ;
00209
00210 for ( i = 0; i < 4; i++ )
00211 success += materialPointers[i]->revertToLastCommit( ) ;
00212
00213 return success ;
00214 }
00215
00216
00217
00218 int ConstantPressureVolumeQuad :: revertToStart( )
00219 {
00220 int i ;
00221 int success = 0 ;
00222
00223 for ( i = 0; i < 4; i++ )
00224 success += materialPointers[i]->revertToStart( ) ;
00225
00226 return success ;
00227 }
00228
00229 int
00230 ConstantPressureVolumeQuad :: update( )
00231 {
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 int i, k, l;
00243 int node ;
00244 int success = 0;
00245
00246 static double tmp_shp[3][4] ;
00247
00248 static double shp[3][4][4] ;
00249
00250 static double vol_avg_shp[3][4] ;
00251
00252 double xsj ;
00253
00254 static Matrix sx(2,2) ;
00255
00256 double dvol[4] ;
00257
00258 double volume = 0.0 ;
00259
00260 double theta = 0.0 ;
00261
00262 static Vector strain(4) ;
00263
00264 double trace = 0.0 ;
00265
00266 static Vector one(4) ;
00267
00268
00269 one(0) = 1.0 ;
00270 one(1) = 1.0 ;
00271 one(2) = 1.0 ;
00272 one(3) = 0.0 ;
00273
00274
00275
00276 volume = 0.0 ;
00277
00278 for ( k = 0; k < 3; k++ ){
00279 for ( l = 0; l < 4; l++ )
00280 vol_avg_shp[k][l] = 0.0 ;
00281 }
00282
00283
00284
00285
00286 for ( i = 0; i < 4; i++ ){
00287
00288 shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00289
00290 dvol[i] = wg[i] * xsj ;
00291
00292 volume += dvol[i] ;
00293
00294 for ( k = 0; k < 3; k++ ){
00295 for ( l = 0; l < 4; l++ ) {
00296
00297 shp[k][l][i] = tmp_shp[k][l] ;
00298
00299 vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00300
00301 }
00302 }
00303
00304 }
00305
00306
00307
00308 for ( k = 0; k < 3; k++ ){
00309 for ( l = 0; l < 4; l++ )
00310 vol_avg_shp[k][l] /= volume ;
00311 }
00312
00313
00314
00315 theta = 0.0 ;
00316 for ( i = 0; i < 4; i++ ) {
00317
00318 strain.Zero( ) ;
00319
00320
00321 for ( node = 0; node < 4; node++ ) {
00322
00323 const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00324
00325 strain(0) += shp[0][node][i] * ul(0) ;
00326
00327 strain(1) += shp[1][node][i] * ul(1) ;
00328
00329 strain(2) = 0.0 ;
00330
00331 }
00332
00333 trace = strain(0) + strain(1) + strain(2) ;
00334
00335 theta += trace * dvol[i] ;
00336
00337 }
00338 theta /= volume ;
00339
00340
00341
00342 for ( i = 0; i < 4; i++ ) {
00343
00344 strain.Zero( ) ;
00345
00346
00347 for ( node = 0; node < 4; node++ ) {
00348
00349 const Vector &ul = nodePointers[node]->getTrialDisp( ) ;
00350
00351 strain(0) += shp[0][node][i] * ul(0) ;
00352
00353 strain(1) += shp[1][node][i] * ul(1) ;
00354
00355 strain(2) = 0.0 ;
00356
00357 strain(3) += shp[1][node][i] * ul(0)
00358 + shp[0][node][i] * ul(1) ;
00359
00360 }
00361
00362 trace = strain(0) + strain(1) + strain(2) ;
00363
00364
00365 strain.addVector(1.0, one, -one3*trace ) ;
00366
00367
00368 strain.addVector(1.0, one, one3*theta ) ;
00369
00370 success += materialPointers[i]->setTrialStrain( strain ) ;
00371
00372 }
00373
00374 return success;
00375 }
00376
00377
00378 void ConstantPressureVolumeQuad :: Print( OPS_Stream &s, int flag )
00379 {
00380 s << endln ;
00381 s << "Four Node Quad -- Mixed Pressure/Volume -- Plane Strain \n" ;
00382 s << "Element Number " << this->getTag() << endln ;
00383 s << "Node 1 : " << connectedExternalNodes(0) << endln ;
00384 s << "Node 2 : " << connectedExternalNodes(1) << endln ;
00385 s << "Node 3 : " << connectedExternalNodes(2) << endln ;
00386 s << "Node 4 : " << connectedExternalNodes(3) << endln ;
00387 s << "Material Information : \n " ;
00388
00389 materialPointers[0]->Print( s, flag ) ;
00390
00391 s << endln ;
00392 }
00393
00394
00395 const Matrix& ConstantPressureVolumeQuad :: getTangentStiff( )
00396 {
00397 int tang_flag = 1 ;
00398
00399
00400 formResidAndTangent( tang_flag ) ;
00401
00402 return stiff ;
00403 }
00404
00405 const Matrix& ConstantPressureVolumeQuad :: getInitialStiff( )
00406 {
00407 int i, j, k, l, p, q ;
00408 int jj, kk ;
00409
00410 static double tmp_shp[3][4] ;
00411
00412 static double shp[3][4][4] ;
00413
00414 static double vol_avg_shp[3][4] ;
00415
00416 double xsj ;
00417
00418 static Matrix sx(2,2) ;
00419
00420 double dvol[4] ;
00421
00422 double volume = 0.0 ;
00423
00424 double pressure = 0.0 ;
00425
00426 static Vector strain(4) ;
00427
00428
00429 static Vector sig(4) ;
00430
00431 double trace = 0.0 ;
00432
00433 static Matrix BJtran(2,4) ;
00434 static Matrix BK(4,2) ;
00435
00436 static Matrix littleBJtran(2,1) ;
00437 static Matrix littleBK(1,2) ;
00438
00439 static Matrix stiffJK(2,2) ;
00440 static Vector residJ(2) ;
00441
00442 static Vector one(4) ;
00443
00444 static Matrix Pdev(4,4) ;
00445
00446
00447
00448 static Matrix ddPdev(4,4) ;
00449 static Matrix PdevDD(4,4) ;
00450
00451 static double Pdev_dd_Pdev_data[16];
00452 static double Pdev_dd_one_data[4];
00453 static double one_dd_Pdev_data[4];
00454 static Matrix Pdev_dd_Pdev(Pdev_dd_Pdev_data, 4, 4);
00455 static Matrix Pdev_dd_one(Pdev_dd_one_data, 4, 1);
00456 static Matrix one_dd_Pdev(one_dd_Pdev_data, 1,4) ;
00457
00458 double bulk ;
00459 static Matrix BJtranD(2,4) ;
00460 static Matrix BJtranDone(2,1) ;
00461
00462 static Matrix littleBJoneD(2,4) ;
00463 static Matrix littleBJtranBulk(2,1) ;
00464
00465
00466 stiff.Zero();
00467
00468
00469 one(0) = 1.0 ;
00470 one(1) = 1.0 ;
00471 one(2) = 1.0 ;
00472 one(3) = 0.0 ;
00473
00474
00475 Pdev.Zero( ) ;
00476
00477 Pdev(0,0) = two3 ;
00478 Pdev(0,1) = -one3 ;
00479 Pdev(0,2) = -one3 ;
00480
00481 Pdev(1,0) = -one3 ;
00482 Pdev(1,1) = two3 ;
00483 Pdev(1,2) = -one3 ;
00484
00485 Pdev(2,0) = -one3 ;
00486 Pdev(2,1) = -one3 ;
00487 Pdev(2,2) = two3 ;
00488
00489 Pdev(3,3) = 1.0 ;
00490
00491
00492 volume = 0.0 ;
00493
00494 for ( k = 0; k < 3; k++ ){
00495 for ( l = 0; l < 4; l++ )
00496 vol_avg_shp[k][l] = 0.0 ;
00497 }
00498
00499
00500
00501
00502 for ( i = 0; i < 4; i++ ){
00503
00504 shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00505
00506 dvol[i] = wg[i] * xsj ;
00507
00508 volume += dvol[i] ;
00509
00510 for ( k = 0; k < 3; k++ ){
00511 for ( l = 0; l < 4; l++ ) {
00512
00513 shp[k][l][i] = tmp_shp[k][l] ;
00514
00515 vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00516
00517 }
00518 }
00519
00520 }
00521
00522
00523
00524 for ( k = 0; k < 3; k++ ){
00525 for ( l = 0; l < 4; l++ )
00526 vol_avg_shp[k][l] /= volume ;
00527 }
00528
00529
00530 for ( i = 0; i < 4; i++ ) {
00531
00532 static Matrix dd(4,4);
00533
00534 dd = materialPointers[i]->getInitialTangent( ) ;
00535
00536 dd *= dvol[i] ;
00537
00538
00539 Pdev_dd_Pdev.addMatrixTripleProduct(0.0,
00540 Pdev,
00541 dd,
00542 1.0) ;
00543
00544
00545 PdevDD.addMatrixProduct(0.0, Pdev, dd, 1.0) ;
00546 Pdev_dd_one(0,0) = one3 * (PdevDD(0,0) + PdevDD(0,1) + PdevDD(0,2));
00547 Pdev_dd_one(1,0) = one3 * (PdevDD(1,0) + PdevDD(1,1) + PdevDD(1,2));
00548 Pdev_dd_one(2,0) = one3 * (PdevDD(2,0) + PdevDD(2,1) + PdevDD(2,2));
00549 Pdev_dd_one(3,0) = one3 * (PdevDD(3,0) + PdevDD(3,1) + PdevDD(3,2));
00550
00551
00552 ddPdev.addMatrixProduct(0.0, dd, Pdev, 1.0) ;
00553 one_dd_Pdev(0,0) = one3 * (ddPdev(0,0) + ddPdev(1,0) + ddPdev(2,0));
00554 one_dd_Pdev(0,1) = one3 * (ddPdev(0,1) + ddPdev(1,1) + ddPdev(2,1));
00555 one_dd_Pdev(0,2) = one3 * (ddPdev(0,2) + ddPdev(1,2) + ddPdev(2,2));
00556 one_dd_Pdev(0,3) = one3 * (ddPdev(0,3) + ddPdev(1,3) + ddPdev(2,3));
00557
00558 bulk = one9 * ( dd(0,0) + dd(0,1) + dd(0,2)
00559 + dd(1,0) + dd(1,1) + dd(1,2)
00560 + dd(2,0) + dd(2,1) + dd(2,2) ) ;
00561
00562 jj = 0 ;
00563 for ( j = 0; j < 4; j++ ) {
00564
00565 double BJ00 = shp[0][j][i];
00566 double BJ11 = shp[1][j][i];
00567 double BJ30 = shp[1][j][i];
00568 double BJ31 = shp[0][j][i];
00569
00570 BJtran.Zero( );
00571 BJtran(0,0) = shp[0][j][i] ;
00572 BJtran(1,1) = shp[1][j][i] ;
00573
00574
00575
00576 BJtran(0,3) = shp[1][j][i] ;
00577 BJtran(1,3) = shp[0][j][i] ;
00578
00579
00580
00581 double ltBJ00 = vol_avg_shp[0][j] ;
00582 double ltBJ01 = vol_avg_shp[1][j] ;
00583
00584
00585
00586
00587
00588
00589
00590 static double Adata[8];
00591 static Matrix A(Adata, 2, 4);
00592
00593
00594
00595
00596 for (int colA = 0, loc = 0, colPdev = 0; colA<4; colA++, colPdev += 4) {
00597 double data3colA = Pdev_dd_Pdev_data[3+colPdev];
00598 Adata[loc++] = BJ00*Pdev_dd_Pdev_data[colPdev] + BJ30*data3colA + ltBJ00*one_dd_Pdev_data[colA];
00599 Adata[loc++] = BJ11*Pdev_dd_Pdev_data[1+colPdev] + BJ31*data3colA + ltBJ01*one_dd_Pdev_data[colA];
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609 double B1, B2;
00610
00611
00612
00613 B1 = BJ00*Pdev_dd_one_data[0] + BJ30*Pdev_dd_one_data[3] + ltBJ00 *bulk;
00614 B2 = BJ11*Pdev_dd_one_data[1] + BJ31*Pdev_dd_one_data[3] + ltBJ01 *bulk;
00615
00616 int colkk, colkkP1;
00617 for ( k = 0, kk=0, colkk =0, colkkP1 =8;
00618 k < 4;
00619 k++, kk += 2, colkk += 16, colkkP1 += 16 ) {
00620
00621 double BK00 = shp[0][k][i];
00622 double BK11 = shp[1][k][i];
00623 double BK30 = shp[1][k][i];
00624 double BK31 = shp[0][k][i];
00625
00626 double littleBK00 = vol_avg_shp[0][k];
00627 double littleBK01 = vol_avg_shp[1][k];
00628
00629
00630
00631 stiff( jj, kk ) += Adata[0]*BK00 + Adata[6]*BK30 + B1 * littleBK00;
00632 stiff( jj+1, kk ) += Adata[1]*BK00 + Adata[7]*BK30 + B2 * littleBK00;
00633 stiff( jj, kk+1 ) += Adata[2]*BK11 + Adata[6]*BK31 + B1 * littleBK01;
00634 stiff( jj+1, kk+1 ) += Adata[3]*BK11 + Adata[7]*BK31 + B2 * littleBK01;
00635
00636 }
00637
00638 jj += 2 ;
00639 }
00640 }
00641
00642 return stiff ;
00643 }
00644
00645
00646 const Matrix& ConstantPressureVolumeQuad :: getMass( )
00647 {
00648 int tangFlag = 1 ;
00649
00650 formInertiaTerms( tangFlag ) ;
00651 return mass ;
00652 }
00653
00654
00655
00656 void ConstantPressureVolumeQuad :: zeroLoad( )
00657 {
00658 if (load != 0)
00659 load->Zero();
00660
00661 return ;
00662 }
00663
00664 int
00665 ConstantPressureVolumeQuad::addLoad(ElementalLoad *theLoad, double loadFactor)
00666 {
00667 opserr << "ConstantPressureVolumeQuad::addLoad - load type unknown for ele with tag: " << this->getTag() << endln;
00668 return -1;
00669 }
00670
00671 int
00672 ConstantPressureVolumeQuad::addInertiaLoadToUnbalance(const Vector &accel)
00673 {
00674 static const int numberGauss = 9 ;
00675 static const int numberNodes = 9 ;
00676 static const int ndf = 2 ;
00677
00678 int i;
00679
00680
00681 int haveRho = 0;
00682 for (i = 0; i < numberGauss; i++) {
00683 if (materialPointers[i]->getRho() != 0.0)
00684 haveRho = 1;
00685 }
00686
00687 if (haveRho == 0)
00688 return 0;
00689
00690
00691 int tangFlag = 1 ;
00692 formInertiaTerms( tangFlag ) ;
00693
00694
00695 int count = 0;
00696
00697 for (i=0; i<numberNodes; i++) {
00698 const Vector &Raccel = nodePointers[i]->getRV(accel);
00699 for (int j=0; j<ndf; j++)
00700 resid(count++) = Raccel(i);
00701 }
00702
00703
00704 if (load == 0)
00705 load = new Vector(numberNodes*ndf);
00706
00707
00708 load->addMatrixVector(1.0, mass, resid, -1.0);
00709
00710 return 0;
00711 }
00712
00713
00714
00715 const Vector& ConstantPressureVolumeQuad :: getResistingForce( )
00716 {
00717 int tang_flag = 0 ;
00718
00719 formResidAndTangent( tang_flag ) ;
00720
00721
00722 if (load != 0)
00723 resid -= *load;
00724
00725 return resid ;
00726 }
00727
00728
00729
00730 const Vector& ConstantPressureVolumeQuad :: getResistingForceIncInertia( )
00731 {
00732 int tang_flag = 0 ;
00733
00734 static Vector res(8);
00735
00736
00737 formResidAndTangent( tang_flag ) ;
00738
00739
00740 formInertiaTerms( tang_flag ) ;
00741 res = resid;
00742
00743
00744 if (load != 0)
00745 res -= *load;
00746
00747
00748 if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0)
00749 res += this->getRayleighDampingForces();
00750
00751 return res ;
00752 }
00753
00754
00755
00756
00757 void ConstantPressureVolumeQuad::formInertiaTerms( int tangFlag )
00758 {
00759
00760 static const int ndm = 2 ;
00761
00762 static const int ndf = 2 ;
00763
00764 static const int numberNodes = 4 ;
00765
00766 static const int numberGauss = 4 ;
00767
00768 static const int nShape = 3 ;
00769
00770 static const int massIndex = nShape - 1 ;
00771
00772 double xsj ;
00773
00774 double dvol ;
00775
00776 static double shp[nShape][numberNodes] ;
00777
00778 static Vector momentum(ndf) ;
00779
00780 static Matrix sx(ndm,ndm) ;
00781
00782 int i, j, k, p ;
00783 int jj, kk ;
00784
00785 double temp, rho, massJK ;
00786
00787
00788
00789 mass.Zero( ) ;
00790
00791
00792 for ( i = 0; i < numberGauss; i++ ) {
00793
00794
00795 shape2d( sg[i], tg[i], xl, shp, xsj, sx ) ;
00796
00797
00798 dvol = wg[i] * xsj ;
00799
00800
00801 momentum.Zero( ) ;
00802 for ( j = 0; j < numberNodes; j++ )
00803
00804 momentum.addVector( 1.0,
00805 nodePointers[j]->getTrialAccel(),
00806 shp[massIndex][j] ) ;
00807
00808
00809 rho = materialPointers[i]->getRho() ;
00810
00811
00812 momentum *= rho ;
00813
00814
00815
00816 jj = 0 ;
00817 for ( j = 0; j < numberNodes; j++ ) {
00818
00819 temp = shp[massIndex][j] * dvol ;
00820
00821 if ( tangFlag == 1 ) {
00822
00823
00824 temp *= rho ;
00825
00826
00827 kk = 0 ;
00828 for ( k = 0; k < numberNodes; k++ ) {
00829
00830 massJK = temp * shp[massIndex][k] ;
00831
00832 for ( p = 0; p < ndf; p++ )
00833 mass( jj+p, kk+p ) += massJK ;
00834
00835 kk += ndf ;
00836 }
00837
00838 }
00839
00840 else
00841 for ( p = 0; p < ndf; p++ )
00842 resid( jj+p ) += ( temp * momentum(p) ) ;
00843
00844 jj += ndf ;
00845
00846 }
00847
00848
00849 }
00850
00851
00852
00853 }
00854
00855
00856
00857
00858 void ConstantPressureVolumeQuad :: formResidAndTangent( int tang_flag )
00859 {
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870 int i, j, k, l, p, q ;
00871 int jj, kk ;
00872
00873 static double tmp_shp[3][4] ;
00874
00875 static double shp[3][4][4] ;
00876
00877 static double vol_avg_shp[3][4] ;
00878
00879 double xsj ;
00880
00881 static Matrix sx(2,2) ;
00882
00883 double dvol[4] ;
00884
00885 double volume = 0.0 ;
00886
00887 double pressure = 0.0 ;
00888
00889 static Vector strain(4) ;
00890
00891
00892 static Vector sig(4) ;
00893
00894 double trace = 0.0 ;
00895
00896 static Matrix BJtran(2,4) ;
00897 static Matrix BK(4,2) ;
00898
00899 static Matrix littleBJtran(2,1) ;
00900 static Matrix littleBK(1,2) ;
00901
00902 static Matrix stiffJK(2,2) ;
00903 static Vector residJ(2) ;
00904
00905 static Vector one(4) ;
00906
00907 static Matrix Pdev(4,4) ;
00908
00909
00910
00911 static Matrix ddPdev(4,4) ;
00912 static Matrix PdevDD(4,4) ;
00913
00914 static double Pdev_dd_Pdev_data[16];
00915 static double Pdev_dd_one_data[4];
00916 static double one_dd_Pdev_data[4];
00917 static Matrix Pdev_dd_Pdev(Pdev_dd_Pdev_data, 4, 4);
00918 static Matrix Pdev_dd_one(Pdev_dd_one_data, 4, 1);
00919 static Matrix one_dd_Pdev(one_dd_Pdev_data, 1,4) ;
00920
00921 double bulk ;
00922 static Matrix BJtranD(2,4) ;
00923 static Matrix BJtranDone(2,1) ;
00924
00925 static Matrix littleBJoneD(2,4) ;
00926 static Matrix littleBJtranBulk(2,1) ;
00927
00928
00929 if ( tang_flag == 1 )
00930 stiff.Zero();
00931 else
00932 resid.Zero();
00933
00934
00935 one(0) = 1.0 ;
00936 one(1) = 1.0 ;
00937 one(2) = 1.0 ;
00938 one(3) = 0.0 ;
00939
00940
00941 Pdev.Zero( ) ;
00942
00943 Pdev(0,0) = two3 ;
00944 Pdev(0,1) = -one3 ;
00945 Pdev(0,2) = -one3 ;
00946
00947 Pdev(1,0) = -one3 ;
00948 Pdev(1,1) = two3 ;
00949 Pdev(1,2) = -one3 ;
00950
00951 Pdev(2,0) = -one3 ;
00952 Pdev(2,1) = -one3 ;
00953 Pdev(2,2) = two3 ;
00954
00955 Pdev(3,3) = 1.0 ;
00956
00957
00958 volume = 0.0 ;
00959
00960 for ( k = 0; k < 3; k++ ){
00961 for ( l = 0; l < 4; l++ )
00962 vol_avg_shp[k][l] = 0.0 ;
00963 }
00964
00965
00966
00967
00968 for ( i = 0; i < 4; i++ ){
00969
00970 shape2d( sg[i], tg[i], xl, tmp_shp, xsj, sx ) ;
00971
00972 dvol[i] = wg[i] * xsj ;
00973
00974 volume += dvol[i] ;
00975
00976 for ( k = 0; k < 3; k++ ){
00977 for ( l = 0; l < 4; l++ ) {
00978
00979 shp[k][l][i] = tmp_shp[k][l] ;
00980
00981 vol_avg_shp[k][l] += tmp_shp[k][l] * dvol[i] ;
00982
00983 }
00984 }
00985
00986 }
00987
00988
00989
00990 for ( k = 0; k < 3; k++ ){
00991 for ( l = 0; l < 4; l++ )
00992 vol_avg_shp[k][l] /= volume ;
00993 }
00994
00995
00996 if (tang_flag != 1) {
00997 pressure = 0.0 ;
00998 for ( i = 0; i < 4; i++ ) {
00999
01000 const Vector &sigBar = materialPointers[i]->getStress( ) ;
01001
01002 pressure += one3 * ( sigBar(0) + sigBar(1) + sigBar(2) ) * dvol[i] ;
01003
01004 }
01005
01006 pressure /= volume ;
01007 }
01008
01009
01010
01011 for ( i = 0; i < 4; i++ ) {
01012
01013 if ( tang_flag == 1 ) {
01014
01015 static Matrix dd(4,4);
01016 dd = materialPointers[i]->getTangent( ) ;
01017
01018 dd *= dvol[i] ;
01019
01020
01021 Pdev_dd_Pdev.addMatrixTripleProduct(0.0,
01022 Pdev,
01023 dd,
01024 1.0) ;
01025
01026
01027 PdevDD.addMatrixProduct(0.0, Pdev, dd, 1.0) ;
01028 Pdev_dd_one(0,0) = one3 * (PdevDD(0,0) + PdevDD(0,1) + PdevDD(0,2));
01029 Pdev_dd_one(1,0) = one3 * (PdevDD(1,0) + PdevDD(1,1) + PdevDD(1,2));
01030 Pdev_dd_one(2,0) = one3 * (PdevDD(2,0) + PdevDD(2,1) + PdevDD(2,2));
01031 Pdev_dd_one(3,0) = one3 * (PdevDD(3,0) + PdevDD(3,1) + PdevDD(3,2));
01032
01033
01034 ddPdev.addMatrixProduct(0.0, dd, Pdev, 1.0) ;
01035 one_dd_Pdev(0,0) = one3 * (ddPdev(0,0) + ddPdev(1,0) + ddPdev(2,0));
01036 one_dd_Pdev(0,1) = one3 * (ddPdev(0,1) + ddPdev(1,1) + ddPdev(2,1));
01037 one_dd_Pdev(0,2) = one3 * (ddPdev(0,2) + ddPdev(1,2) + ddPdev(2,2));
01038 one_dd_Pdev(0,3) = one3 * (ddPdev(0,3) + ddPdev(1,3) + ddPdev(2,3));
01039
01040 bulk = one9 * ( dd(0,0) + dd(0,1) + dd(0,2)
01041 + dd(1,0) + dd(1,1) + dd(1,2)
01042 + dd(2,0) + dd(2,1) + dd(2,2) ) ;
01043
01044 } else {
01045
01046 const Vector &sigBar = materialPointers[i]->getStress( ) ;
01047 trace = sigBar(0) + sigBar(1) + sigBar(2) ;
01048 sig = sigBar ;
01049
01050
01051 sig.addVector(1.0, one, -one3*trace ) ;
01052 sig.addVector(1.0, one, pressure ) ;
01053
01054
01055 sig *= dvol[i] ;
01056 }
01057
01058
01059 jj = 0 ;
01060 for ( j = 0; j < 4; j++ ) {
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 double BJ00 = shp[0][j][i];
01090 double BJ11 = shp[1][j][i];
01091 double BJ30 = shp[1][j][i];
01092 double BJ31 = shp[0][j][i];
01093
01094 BJtran.Zero( );
01095 BJtran(0,0) = shp[0][j][i] ;
01096 BJtran(1,1) = shp[1][j][i] ;
01097
01098
01099
01100 BJtran(0,3) = shp[1][j][i] ;
01101 BJtran(1,3) = shp[0][j][i] ;
01102
01103
01104
01105 if ( tang_flag == 1 ) {
01106
01107 double ltBJ00 = vol_avg_shp[0][j] ;
01108 double ltBJ01 = vol_avg_shp[1][j] ;
01109
01110
01111
01112
01113
01114
01115
01116 static double Adata[8];
01117 static Matrix A(Adata, 2, 4);
01118
01119
01120
01121
01122 for (int colA = 0, loc = 0, colPdev = 0; colA<4; colA++, colPdev += 4) {
01123 double data3colA = Pdev_dd_Pdev_data[3+colPdev];
01124 Adata[loc++] = BJ00*Pdev_dd_Pdev_data[colPdev] + BJ30*data3colA + ltBJ00*one_dd_Pdev_data[colA];
01125 Adata[loc++] = BJ11*Pdev_dd_Pdev_data[1+colPdev] + BJ31*data3colA + ltBJ01*one_dd_Pdev_data[colA];
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135 double B1, B2;
01136
01137
01138
01139 B1 = BJ00*Pdev_dd_one_data[0] + BJ30*Pdev_dd_one_data[3] + ltBJ00 *bulk;
01140 B2 = BJ11*Pdev_dd_one_data[1] + BJ31*Pdev_dd_one_data[3] + ltBJ01 *bulk;
01141
01142 int colkk, colkkP1;
01143 for ( k = 0, kk=0, colkk =0, colkkP1 =8;
01144 k < 4;
01145 k++, kk += 2, colkk += 16, colkkP1 += 16 ) {
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159 double BK00 = shp[0][k][i];
01160 double BK11 = shp[1][k][i];
01161 double BK30 = shp[1][k][i];
01162 double BK31 = shp[0][k][i];
01163
01164 double littleBK00 = vol_avg_shp[0][k];
01165 double littleBK01 = vol_avg_shp[1][k];
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186 stiff( jj, kk ) += Adata[0]*BK00 + Adata[6]*BK30 + B1 * littleBK00;
01187 stiff( jj+1, kk ) += Adata[1]*BK00 + Adata[7]*BK30 + B2 * littleBK00;
01188 stiff( jj, kk+1 ) += Adata[2]*BK11 + Adata[6]*BK31 + B1 * littleBK01;
01189 stiff( jj+1, kk+1 ) += Adata[3]*BK11 + Adata[7]*BK31 + B2 * littleBK01;
01190
01191 }
01192
01193 } else {
01194
01195
01196 residJ.addMatrixVector(0.0, BJtran, sig, 1.0);
01197 resid( jj ) += residJ(0);
01198 resid( jj+1 ) += residJ(1);
01199 }
01200
01201 jj += 2 ;
01202 }
01203
01204 }
01205
01206
01207 return ;
01208 }
01209
01210
01211
01212 void ConstantPressureVolumeQuad :: shape2d( double ss, double tt,
01213 const double x[2][4],
01214 double shp[3][4],
01215 double &xsj,
01216 Matrix &sx )
01217 {
01218
01219 int i, j, k ;
01220
01221 double temp ;
01222
01223 static const double s[] = { -0.5, 0.5, 0.5, -0.5 } ;
01224 static const double t[] = { -0.5, -0.5, 0.5, 0.5 } ;
01225
01226 static double xs[2][2];
01227
01228
01229
01230 for ( i = 0; i < 4; i++ ) {
01231 shp[2][i] = ( 0.5 + s[i]*ss )*( 0.5 + t[i]*tt ) ;
01232 shp[0][i] = s[i] * ( 0.5 + t[i]*tt ) ;
01233 shp[1][i] = t[i] * ( 0.5 + s[i]*ss ) ;
01234 }
01235
01236
01237
01238
01239 for ( i = 0; i < 2; i++ ) {
01240 for ( j = 0; j < 2; j++ ) {
01241
01242 double value = 0;
01243 for ( k = 0; k < 4; k++ )
01244 value += x[i][k] * shp[j][k] ;
01245
01246 xs[i][j] = value;
01247
01248 }
01249 }
01250
01251 xsj = xs[0][0]*xs[1][1] - xs[0][1]*xs[1][0] ;
01252
01253 sx(0,0) = xs[1][1] / xsj ;
01254 sx(1,1) = xs[0][0] / xsj ;
01255 sx(0,1) = -xs[0][1] / xsj ;
01256 sx(1,0) = -xs[1][0] / xsj ;
01257
01258
01259
01260 for ( i = 0; i < 4; i++ ) {
01261 temp = shp[0][i]*sx(0,0) + shp[1][i]*sx(1,0) ;
01262 shp[1][i] = shp[0][i]*sx(0,1) + shp[1][i]*sx(1,1) ;
01263 shp[0][i] = temp ;
01264 }
01265
01266 return ;
01267 }
01268
01269
01270
01271 int
01272 ConstantPressureVolumeQuad::displaySelf(Renderer &theViewer, int displayMode, float fact)
01273 {
01274
01275
01276
01277 const Vector &end1Crd = nodePointers[0]->getCrds();
01278 const Vector &end2Crd = nodePointers[1]->getCrds();
01279 const Vector &end3Crd = nodePointers[2]->getCrds();
01280 const Vector &end4Crd = nodePointers[3]->getCrds();
01281
01282 static Matrix coords(4,3) ;
01283 static Vector values(4) ;
01284
01285 coords.Zero( ) ;
01286
01287 values(0) = 1 ;
01288 values(1) = 1 ;
01289 values(2) = 1 ;
01290 values(3) = 1 ;
01291
01292
01293 if (displayMode >= 0) {
01294
01295 const Vector &end1Disp = nodePointers[0]->getDisp();
01296 const Vector &end2Disp = nodePointers[1]->getDisp();
01297 const Vector &end3Disp = nodePointers[2]->getDisp();
01298 const Vector &end4Disp = nodePointers[3]->getDisp();
01299
01300 for (int i = 0; i < 2; i++) {
01301 coords(0,i) = end1Crd(i) + end1Disp(i)*fact;
01302 coords(1,i) = end2Crd(i) + end2Disp(i)*fact;
01303 coords(2,i) = end3Crd(i) + end3Disp(i)*fact;
01304 coords(3,i) = end4Crd(i) + end4Disp(i)*fact;
01305 }
01306 } else {
01307 int mode = displayMode * -1;
01308 const Matrix &eigen1 = nodePointers[0]->getEigenvectors();
01309 const Matrix &eigen2 = nodePointers[1]->getEigenvectors();
01310 const Matrix &eigen3 = nodePointers[2]->getEigenvectors();
01311 const Matrix &eigen4 = nodePointers[3]->getEigenvectors();
01312 if (eigen1.noCols() >= mode) {
01313 for (int i = 0; i < 2; i++) {
01314 coords(0,i) = end1Crd(i) + eigen1(i,mode-1)*fact;
01315 coords(1,i) = end2Crd(i) + eigen2(i,mode-1)*fact;
01316 coords(2,i) = end3Crd(i) + eigen3(i,mode-1)*fact;
01317 coords(3,i) = end4Crd(i) + eigen4(i,mode-1)*fact;
01318 }
01319 } else {
01320 for (int i = 0; i < 2; i++) {
01321 coords(0,i) = end1Crd(i);
01322 coords(1,i) = end2Crd(i);
01323 coords(2,i) = end3Crd(i);
01324 coords(3,i) = end4Crd(i);
01325 }
01326 }
01327 }
01328
01329
01330 int error = 0;
01331
01332 error += theViewer.drawPolygon (coords, values);
01333
01334 return error;
01335 }
01336
01337
01338 Response*
01339 ConstantPressureVolumeQuad::setResponse(const char **argv, int argc,
01340 Information &eleInfo, OPS_Stream &output)
01341 {
01342 Response *theResponse =0;
01343
01344 output.tag("ElementOutput");
01345 output.attr("eleType","ConstantPressureVolumeQuad");
01346 output.attr("eleTag",this->getTag());
01347 output.attr("node1",connectedExternalNodes[0]);
01348 output.attr("node2",connectedExternalNodes[1]);
01349 output.attr("node3",connectedExternalNodes[2]);
01350 output.attr("node4",connectedExternalNodes[3]);
01351
01352 char dataOut[10];
01353 if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0) {
01354
01355 for (int i=1; i<=4; i++) {
01356 sprintf(dataOut,"P1_%d",i);
01357 output.tag("ResponseType",dataOut);
01358 sprintf(dataOut,"P2_%d",i);
01359 output.tag("ResponseType",dataOut);
01360 }
01361
01362 theResponse = new ElementResponse(this, 1, resid);
01363 } else if (strcmp(argv[0],"material") == 0 || strcmp(argv[0],"integrPoint") == 0) {
01364 int pointNum = atoi(argv[1]);
01365 if (pointNum > 0 && pointNum <= 4) {
01366
01367 output.tag("GaussPoint");
01368 output.attr("number",pointNum);
01369 output.attr("eta",sg[pointNum-1]);
01370 output.attr("neta",tg[pointNum-1]);
01371
01372 theResponse = materialPointers[pointNum-1]->setResponse(&argv[2], argc-2, eleInfo, output);
01373
01374 output.endTag();
01375
01376 } else if (strcmp(argv[0],"stresses") ==0) {
01377
01378 for (int i=0; i<4; i++) {
01379 output.tag("GaussPoint");
01380 output.attr("number",i+1);
01381 output.attr("eta",sg[i]);
01382 output.attr("neta",tg[i]);
01383
01384 output.tag("NdMaterialOutput");
01385 output.attr("classType", materialPointers[i]->getClassTag());
01386 output.attr("tag", materialPointers[i]->getTag());
01387
01388 output.tag("ResponseType","UnknownStress");
01389 output.tag("ResponseType","UnknownStress");
01390 output.tag("ResponseType","UnknownStress");
01391 output.tag("ResponseType","UnknownStress");
01392
01393 output.endTag();
01394 output.endTag();
01395 }
01396
01397 theResponse = new ElementResponse(this, 3, Vector(16));
01398 }
01399 }
01400
01401 output.endTag();
01402
01403 return theResponse;
01404 }
01405
01406 int
01407 ConstantPressureVolumeQuad::getResponse(int responseID, Information &eleInfo)
01408 {
01409 if (responseID == 1) {
01410
01411 return eleInfo.setVector(this->getResistingForce());
01412
01413 } else if (responseID == 3) {
01414
01415
01416 static Vector stresses(16);
01417 int cnt = 0;
01418 for (int i = 0; i < 4; i++) {
01419
01420
01421 const Vector &sigma = materialPointers[i]->getStress();
01422 stresses(cnt) = sigma(0);
01423 stresses(cnt+1) = sigma(1);
01424 stresses(cnt+2) = sigma(2);
01425 stresses(cnt+3) = sigma(2);
01426 cnt += 4;
01427 }
01428 return eleInfo.setVector(stresses);
01429
01430 } else
01431
01432 return -1;
01433 }
01434
01435
01436
01437 int ConstantPressureVolumeQuad :: sendSelf (int commitTag, Channel &theChannel)
01438 {
01439 int res = 0;
01440
01441
01442
01443
01444 int dataTag = this->getDbTag();
01445
01446
01447
01448 int matDbTag;
01449
01450 static ID idData(13);
01451
01452 int i;
01453 for (i = 0; i < 4; i++) {
01454 idData(i) = materialPointers[i]->getClassTag();
01455 matDbTag = materialPointers[i]->getDbTag();
01456
01457
01458 if (matDbTag == 0) {
01459 matDbTag = theChannel.getDbTag();
01460 if (matDbTag != 0)
01461 materialPointers[i]->setDbTag(matDbTag);
01462 }
01463 idData(i+4) = matDbTag;
01464 }
01465
01466 idData(8) = this->getTag();
01467 idData(9) = connectedExternalNodes(0);
01468 idData(10) = connectedExternalNodes(1);
01469 idData(11) = connectedExternalNodes(2);
01470 idData(12) = connectedExternalNodes(3);
01471
01472 res += theChannel.sendID(dataTag, commitTag, idData);
01473 if (res < 0) {
01474 opserr << "WARNING ConstantPressureVolumeQuad::sendSelf() - " << this->getTag() << " failed to send ID\n";
01475
01476 return res;
01477 }
01478
01479
01480 for (i = 0; i < 4; i++) {
01481 res += materialPointers[i]->sendSelf(commitTag, theChannel);
01482 if (res < 0) {
01483 opserr << "WARNING ConstantPressureVolumeQuad::sendSelf() - " << this->getTag() << "failed to send its Material\n";
01484 return res;
01485 }
01486 }
01487 return res;
01488 }
01489
01490 int
01491 ConstantPressureVolumeQuad :: recvSelf (int commitTag,
01492 Channel &theChannel,
01493 FEM_ObjectBroker &theBroker)
01494 {
01495 int res = 0;
01496
01497 int dataTag = this->getDbTag();
01498
01499 static ID idData(13);
01500
01501 res += theChannel.recvID(dataTag, commitTag, idData);
01502 if (res < 0) {
01503 opserr << "WARNING ConstantPressureVolumeQuad::recvSelf() - " << this->getTag() << " failed to receive ID\n";
01504 return res;
01505 }
01506
01507 this->setTag(idData(8));
01508 connectedExternalNodes(0) = idData(9);
01509 connectedExternalNodes(1) = idData(10);
01510 connectedExternalNodes(2) = idData(11);
01511 connectedExternalNodes(3) = idData(12);
01512
01513 int i;
01514
01515 if (materialPointers[0] == 0) {
01516 for (i = 0; i < 4; i++) {
01517 int matClassTag = idData(i);
01518 int matDbTag = idData(i+4);
01519
01520 materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01521 if (materialPointers[i] == 0) {
01522 opserr << "ConstantPressureVolumeQuad::recvSelf() - " <<
01523 "Broker could not create NDMaterial of class type" << matClassTag << endln;
01524 return -1;
01525 }
01526
01527 materialPointers[i]->setDbTag(matDbTag);
01528 res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01529 if (res < 0) {
01530 opserr << "NLBeamColumn3d::recvSelf() - material " <<
01531 i << "failed to recv itself\n";
01532 return res;
01533 }
01534 }
01535 }
01536
01537 else {
01538 for (i = 0; i < 4; i++) {
01539 int matClassTag = idData(i);
01540 int matDbTag = idData(i+4);
01541
01542
01543 if (materialPointers[i]->getClassTag() != matClassTag) {
01544 delete materialPointers[i];
01545 materialPointers[i] = theBroker.getNewNDMaterial(matClassTag);
01546 if (materialPointers[i] == 0) {
01547 opserr << "ConstantPressureVolumeQuad::recvSelf() - " <<
01548 "Broker could not create NDMaterial of class type" << matClassTag << endln;
01549 exit(-1);
01550 }
01551 }
01552
01553 materialPointers[i]->setDbTag(matDbTag);
01554 res += materialPointers[i]->recvSelf(commitTag, theChannel, theBroker);
01555 if (res < 0) {
01556 opserr << "ConstantPressureVolumeQuad::recvSelf() - material " << i <<
01557 "failed to recv itself\n";
01558 return res;
01559 }
01560 }
01561 }
01562
01563 return res;
01564 }
01565