PySimple1.cpp

Go to the documentation of this file.
00001 /* *********************************************************************
00002 **    Module:   PySimple1.cpp 
00003 **
00004 **    Purpose:  Provide a simple p-y spring for OpenSees.
00005 **
00006 **    Developed by Ross W. Boulanger
00007 **    (C) Copyright 2001, All Rights Reserved.
00008 **
00009 ** ****************************************************************** */
00010 
00011 // $Revision: 1.0
00012 // $Date: 2001/12/15
00013 // $Source: /OpenSees/SRC/material/uniaxial/PySimple1.cpp
00014 
00015 // Written: RWB
00016 // Created: Dec 2001
00017 // Revision: A
00018 // tested and checked: Boris Jeremic (jeremic@ucdavis.edu) Spring 2002
00019 //
00020 // Description: This file contains the class implementation for PySimple1
00021 
00022 #include <stdlib.h>
00023 #include <math.h>
00024 
00025 #include "PySimple1.h"
00026 #include <Vector.h>
00027 #include <Channel.h>
00028 
00029 // Controls on internal iteration between spring components
00030 const int PYmaxIterations = 20;
00031 const double PYtolerance = 1.0e-12;
00032 
00034 //      Constructor with data
00035 
00036 PySimple1::PySimple1(int tag, int classtag, int soil, double p_ult, double y_50,
00037                                  double dragratio, double dash_pot)
00038 :UniaxialMaterial(tag,classtag),
00039  soilType(soil), pult(p_ult), y50(y_50), drag(dragratio), dashpot(dash_pot)
00040 {
00041   // Initialize PySimple variables and history variables
00042   //
00043   this->revertToStart();
00044   initialTangent = Ttangent;
00045 }
00046 
00048 //      Default constructor
00049 
00050 PySimple1::PySimple1()
00051 :UniaxialMaterial(0,0),
00052  soilType(0), pult(0.0), y50(0.0), drag(0.0), dashpot(0.0)
00053 {
00054 }
00055 
00057 //      Default destructor
00058 PySimple1::~PySimple1()
00059 {
00060     // Does nothing
00061 }
00062 
00064 void PySimple1::getGap(double ylast, double dy, double dy_old)
00065 {
00066         // For stability in Closure spring, may limit "dy" step size to avoid
00067         // overshooting on the closing of this gap.
00068         //
00069         TGap_y = ylast + dy;
00070         if(TGap_y > TClose_yright) {dy = 0.75*(TClose_yright - ylast);}
00071         if(TGap_y < TClose_yleft)  {dy = 0.75*(TClose_yleft  - ylast);}
00072 
00073         // Limit "dy" step size if it is oscillating in sign and not shrinking
00074         //
00075         if(dy*dy_old < 0.0 && fabs(dy/dy_old) > 0.5) dy = -dy_old/2.0;
00076         
00077         // Combine the Drag and Closure elements in parallel, starting by
00078         // resetting TGap_y in case the step size was limited.
00079         //
00080         TGap_y   = ylast + dy;
00081         getClosure(ylast,dy);
00082         getDrag(ylast,dy);
00083         TGap_p = TDrag_p + TClose_p;
00084         TGap_tang = TDrag_tang + TClose_tang;
00085 
00086         // Ensure that |p|<pmax.
00087         //
00088         if(fabs(TGap_p)>=pult) TGap_p =(TGap_p/fabs(TGap_p))*(1.0-PYtolerance)*pult;
00089 
00090         return;
00091 }
00092 
00094 void PySimple1::getFarField(double y)
00095 {
00096         TFar_y   = y;
00097         TFar_tang= TFar_tang;
00098         TFar_p   = TFar_tang * TFar_y;
00099 
00100         return;
00101 }
00102 
00104 void PySimple1::getClosure(double ylast, double dy)
00105 {
00106         // Reset the history terms to the last Committed values, and let them
00107         // reset if the reversal of loading persists in this step.
00108         //
00109         if(TClose_yleft != CClose_yleft)  TClose_yleft = CClose_yleft;
00110         if(TClose_yright!= CClose_yright) TClose_yright= CClose_yright;
00111 
00112         // Check if plastic deformation in Near Field should cause gap expansion
00113         //
00114         TClose_y = ylast + dy;
00115         double yrebound=1.5*y50;
00116         if(TNF_y+TClose_y > -TClose_yleft + yrebound)
00117                 TClose_yleft=-(TNF_y+TClose_y) + yrebound;
00118         if(TNF_y+TClose_y < -TClose_yright - yrebound)
00119                 TClose_yright=-(TNF_y+TClose_y) - yrebound;
00120 
00121         // Spring force and tangent stiffness
00122         //
00123         TClose_p=1.8*pult*(y50/50.0)*(pow(y50/50.0 + TClose_yright - TClose_y,-1.0)
00124                 -pow(y50/50.0 + TClose_y - TClose_yleft,-1.0));
00125         TClose_tang=1.8*pult*(y50/50.0)*(pow(y50/50.0+ TClose_yright - TClose_y,-2.0)
00126                 +pow(y50/50.0 + TClose_y - TClose_yleft,-2.0));
00127 
00128         // Ensure that tangent not zero or negative.
00129         //      
00130         if(TClose_tang <= 1.0e-2*pult/y50) {TClose_tang = 1.0e-2*pult/y50;}
00131 
00132         return;
00133 }
00134 
00136 void PySimple1::getDrag(double ylast, double dy)
00137 {
00138         TDrag_y = ylast + dy;
00139         double pmax=drag*pult;
00140         double dyTotal=TDrag_y - CDrag_y;
00141 
00142         // Treat as elastic if dyTotal is below PYtolerance
00143         //
00144         if(fabs(dyTotal*TDrag_tang/pult) < 10.0*PYtolerance) 
00145         {
00146                 TDrag_p = TDrag_p + dy*TDrag_tang;
00147                 if(fabs(TDrag_p) >=pmax) TDrag_p =(TDrag_p/fabs(TDrag_p))*(1.0-1.0e-8)*pmax;
00148                 return;
00149         }
00150         // Reset the history terms to the last Committed values, and let them
00151         // reset if the reversal of loading persists in this step.
00152         //
00153         if(TDrag_pin != CDrag_pin)
00154         {
00155                 TDrag_pin = CDrag_pin;
00156                 TDrag_yin = CDrag_yin;
00157         }
00158 
00159         // Change from positive to negative direction
00160         //
00161         if(CDrag_y > CDrag_yin && dyTotal < 0.0)
00162         {
00163                 TDrag_pin = CDrag_p;
00164                 TDrag_yin = CDrag_y;
00165         }
00166         // Change from negative to positive direction
00167         //
00168         if(CDrag_y < CDrag_yin && dyTotal > 0.0)
00169         {
00170                 TDrag_pin = CDrag_p;
00171                 TDrag_yin = CDrag_y;
00172         }
00173         
00174         // Positive loading
00175         //
00176         if(dyTotal >= 0.0)
00177         {
00178                 TDrag_p=pmax-(pmax-TDrag_pin)*pow(y50/2.0,nd)
00179                                         *pow(y50/2.0 + TDrag_y - TDrag_yin,-nd);
00180                 TDrag_tang=nd*(pmax-TDrag_pin)*pow(y50/2.0,nd)
00181                                         *pow(y50/2.0 + TDrag_y - TDrag_yin,-nd-1.0);
00182         }
00183         // Negative loading
00184         //
00185         if(dyTotal < 0.0)
00186         {
00187                 TDrag_p=-pmax+(pmax+TDrag_pin)*pow(y50/2.0,nd)
00188                                         *pow(y50/2.0 - TDrag_y + TDrag_yin,-nd);
00189                 TDrag_tang=nd*(pmax+TDrag_pin)*pow(y50/2.0,nd)
00190                                         *pow(y50/2.0 - TDrag_y + TDrag_yin,-nd-1.0);
00191         }
00192         // Ensure that |p|<pmax and tangent not zero or negative.
00193         //
00194         if(fabs(TDrag_p) >=pmax) {
00195                 TDrag_p =(TDrag_p/fabs(TDrag_p))*(1.0-PYtolerance)*pmax;}
00196         if(TDrag_tang <=1.0e-2*pult/y50) TDrag_tang = 1.0e-2*pult/y50;
00197 
00198         return;
00199 }
00200 
00202 void PySimple1::getNearField(double ylast, double dy, double dy_old)
00203 {
00204         // Limit "dy" step size if it is oscillating in sign and not shrinking
00205         //
00206         if(dy*dy_old < 0.0 && fabs(dy/dy_old) > 0.5) dy = -dy_old/2.0;
00207 
00208         // Set "dy" so "y" is at middle of elastic zone if oscillation is large.
00209         // Note that this criteria is based on the min step size in setTrialStrain.
00210         //
00211         if(dy*dy_old < -y50*y50) dy = (TNFyinr + TNFyinl)/2.0 - ylast;
00212         
00213         // Establish trial "y" and direction of loading (with NFdy) for entire step
00214         //
00215         TNF_y = ylast + dy;
00216         double NFdy = TNF_y - CNF_y;
00217 
00218         // Treat as elastic if NFdy is below PYtolerance
00219         //
00220         if(fabs(NFdy*TNF_tang/pult) < 10.0*PYtolerance) 
00221         {
00222                 TNF_p = TNF_p + dy*TNF_tang;
00223                 if(fabs(TNF_p) >=pult) TNF_p=(TNF_p/fabs(TNF_p))*(1.0-PYtolerance)*pult;
00224                 return;
00225         }
00226 
00227         // Reset the history terms to the last Committed values, and let them
00228         // reset if the reversal of loading persists in this step.
00229         //
00230         if(TNFpinr != CNFpinr || TNFpinl != CNFpinl)
00231         {
00232                 TNFpinr = CNFpinr;
00233                 TNFpinl = CNFpinl;
00234                 TNFyinr = CNFyinr;
00235                 TNFyinl = CNFyinl;
00236         }
00237 
00238         // For stability, may have to limit "dy" step size if direction changed.
00239         //
00240         bool changeDirection = false;
00241         
00242         // Direction change from a yield point triggers new Elastic range
00243         //
00244         double minE = 0.25;             // The min Elastic range on +/- side of p=0
00245         if(CNF_p > CNFpinr && NFdy <0.0){                               // from pos to neg
00246                 changeDirection = true;
00247                 TNFpinr = CNF_p;
00248                 if(fabs(TNFpinr)>=(1.0-PYtolerance)*pult){TNFpinr=(1.0-2.0*PYtolerance)*pult;}
00249                 TNFpinl = TNFpinr - 2.0*pult*Elast;
00250                 if (TNFpinl > -minE*pult) {TNFpinl = -minE*pult;}
00251                 TNFyinr = CNF_y;
00252                 TNFyinl = TNFyinr - (TNFpinr-TNFpinl)/NFkrig; 
00253         }
00254         if(CNF_p < CNFpinl && NFdy > 0.0){                              // from neg to pos
00255                 changeDirection = true;
00256                 TNFpinl = CNF_p;
00257                 if(fabs(TNFpinl)>=(1.0-PYtolerance)*pult){TNFpinl=(-1.0+2.0*PYtolerance)*pult;}
00258                 TNFpinr = TNFpinl + 2.0*pult*Elast;
00259                 if (TNFpinr < minE*pult) {TNFpinr = minE*pult;}
00260                 TNFyinl = CNF_y;
00261                 TNFyinr = TNFyinl + (TNFpinr-TNFpinl)/NFkrig; 
00262         }
00263         // Now if there was a change in direction, limit the step size "dy"
00264         //
00265         if(changeDirection == true) {
00266                 double maxdy = 0.25*pult/NFkrig;
00267                 if(fabs(dy) > maxdy) dy = (dy/fabs(dy))*maxdy;
00268         }
00269 
00270         // Now, establish the trial value of "y" for use in this function call.
00271         //
00272         TNF_y = ylast + dy;
00273 
00274         // Postive loading
00275         //
00276         if(NFdy >= 0.0){
00277                 // Check if elastic using y < yinr
00278                 if(TNF_y <= TNFyinr){                                                   // stays elastic
00279                         TNF_tang = NFkrig;
00280                         TNF_p = TNFpinl + (TNF_y - TNFyinl)*NFkrig;
00281                 }
00282                 else {
00283                         TNF_tang = np * (pult-TNFpinr) * pow(yref,np) 
00284                                 * pow(yref - TNFyinr + TNF_y, -np-1.0);
00285                         TNF_p = pult - (pult-TNFpinr)* pow(yref/(yref-TNFyinr+TNF_y),np);
00286                 }
00287         }
00288 
00289         // Negative loading
00290         //
00291         if(NFdy < 0.0){
00292                 // Check if elastic using y < yinl
00293                 if(TNF_y >= TNFyinl){                                                   // stays elastic
00294                         TNF_tang = NFkrig;
00295                         TNF_p = TNFpinr + (TNF_y - TNFyinr)*NFkrig;
00296                 }
00297                 else {
00298                         TNF_tang = np * (pult+TNFpinl) * pow(yref,np) 
00299                                 * pow(yref + TNFyinl - TNF_y, -np-1.0);
00300                         TNF_p = -pult + (pult+TNFpinl)* pow(yref/(yref+TNFyinl-TNF_y),np);
00301                 }
00302         }
00303 
00304         // Ensure that |p|<pult and tangent not zero or negative.
00305         //
00306         if(fabs(TNF_p) >=pult) TNF_p=(TNF_p/fabs(TNF_p))*(1.0-PYtolerance)*pult;
00307         if(TNF_tang <= 1.0e-2*pult/y50) TNF_tang = 1.0e-2*pult/y50;
00308 
00309     return;
00310 }
00311 
00313 int 
00314 PySimple1::setTrialStrain (double newy, double yRate)
00315 {
00316         // Set trial values for displacement and load in the material
00317         // based on the last Tangent modulus.
00318         //
00319         double dy = newy - Ty;
00320         double dp = Ttangent * dy;
00321         TyRate    = yRate;
00322 
00323         // Limit the size of step (dy or dp) that can be imposed. Prevents
00324         // numerical difficulties upon load reversal at high loads
00325         // where a soft loading modulus becomes a stiff unloading modulus.
00326         //
00327         int numSteps = 1;
00328         double stepSize = 1.0;
00329         if(fabs(dp/pult) > 0.5) numSteps = 1 + int(fabs(dp/(0.5*pult)));
00330         if(fabs(dy/y50)  > 1.0 ) numSteps = 1 + int(fabs(dy/(1.0*y50)));
00331         stepSize = 1.0/float(numSteps);
00332         if(numSteps > 100) numSteps = 100;
00333 
00334         dy = stepSize * dy;
00335 
00336         // Main loop over the required number of substeps
00337         //
00338         for(int istep=1; istep <= numSteps; istep++)
00339         {
00340                 Ty = Ty + dy;
00341                 dp = Ttangent * dy;
00342                 
00343         // May substep within Gap or NearField element if oscillating, which can happen
00344         // when they jump from soft to stiff.
00345         //
00346                 double dy_gap_old = ((Tp + dp) - TGap_p)/TGap_tang;
00347                 double dy_nf_old  = ((Tp + dp) - TNF_p) /TNF_tang;
00348 
00349         // Iterate to distribute displacement among the series components.
00350         // Use the incremental iterative strain & iterate at this strain.
00351         //
00352         for (int j=1; j < PYmaxIterations; j++)
00353         {
00354                 Tp = Tp + dp;
00355 
00356                 // Stress & strain update in Near Field element
00357                 double dy_nf = (Tp - TNF_p)/TNF_tang;
00358                 getNearField(TNF_y,dy_nf,dy_nf_old);
00359                 
00360                 // Residuals in Near Field element
00361                 double p_unbalance = Tp - TNF_p;
00362                 double yres_nf = (Tp - TNF_p)/TNF_tang;
00363                 dy_nf_old = dy_nf;
00364 
00365                 // Stress & strain update in Gap element
00366                 double dy_gap = (Tp - TGap_p)/TGap_tang;
00367                 getGap(TGap_y,dy_gap,dy_gap_old);
00368 
00369                 // Residuals in Gap element
00370                 double p_unbalance2 = Tp - TGap_p;
00371                 double yres_gap = (Tp - TGap_p)/TGap_tang;
00372                 dy_gap_old = dy_gap;
00373 
00374                 // Stress & strain update in Far Field element
00375                 double dy_far = (Tp - TFar_p)/TFar_tang;
00376                 TFar_y = TFar_y + dy_far;
00377                 getFarField(TFar_y);
00378 
00379                 // Residuals in Far Field element
00380                 double p_unbalance3 = Tp - TFar_p;
00381                 double yres_far = (Tp - TFar_p)/TFar_tang;
00382 
00383                 // Update the combined tangent modulus
00384                 Ttangent = pow(1.0/TGap_tang + 1.0/TNF_tang + 1.0/TFar_tang, -1.0);
00385 
00386                 // Residual deformation across combined element
00387                 double dv = Ty - (TGap_y + yres_gap)
00388                         - (TNF_y + yres_nf) - (TFar_y + yres_far);
00389 
00390                 // Residual "p" increment 
00391                 dp = Ttangent * dv;
00392 
00393                 // Test for convergence
00394                 double psum = fabs(p_unbalance) + fabs(p_unbalance2) + fabs(p_unbalance3);
00395                 if(psum/pult < PYtolerance) break;
00396         }
00397         }
00398 
00399         return 0;
00400 }
00402 double 
00403 PySimple1::getStress(void)
00404 {
00405         // Dashpot force is only due to velocity in the far field.
00406         // If converged, proportion by Tangents.
00407         // If not converged, proportion by ratio of displacements in components.
00408         //
00409         double ratio_disp =(1.0/TFar_tang)/(1.0/TFar_tang + 1.0/TNF_tang + 1.0/TGap_tang);
00410         if(Ty != Cy) {
00411                 ratio_disp = (TFar_y - CFar_y)/(Ty - Cy);
00412                 if(ratio_disp > 1.0) ratio_disp = 1.0;
00413                 if(ratio_disp < 0.0) ratio_disp = 0.0;
00414         }
00415         double dashForce = dashpot * TyRate * ratio_disp;
00416 
00417         // Limit the combined force to pult.
00418         //
00419         if(fabs(Tp + dashForce) >= (1.0-PYtolerance)*pult)
00420                 return (1.0-PYtolerance)*pult*(Tp+dashForce)/fabs(Tp+dashForce);
00421         else return Tp + dashForce;
00422 }
00424 double 
00425 PySimple1::getTangent(void)
00426 {
00427     return this->Ttangent;
00428 }
00430 double 
00431 PySimple1::getInitialTangent(void)
00432 {
00433     return this->initialTangent;
00434 }
00436 double 
00437 PySimple1::getDampTangent(void)
00438 {
00439         // Damping tangent is produced only by the far field component.
00440         // If converged, proportion by Tangents.
00441         // If not converged, proportion by ratio of displacements in components.
00442         //
00443         double ratio_disp =(1.0/TFar_tang)/(1.0/TFar_tang + 1.0/TNF_tang + 1.0/TGap_tang);
00444         if(Ty != Cy) {
00445                 ratio_disp = (TFar_y - CFar_y)/(Ty - Cy);
00446                 if(ratio_disp > 1.0) ratio_disp = 1.0;
00447                 if(ratio_disp < 0.0) ratio_disp = 0.0;
00448         }
00449 
00450         double DampTangent = dashpot * ratio_disp;
00451 
00452         // Minimum damping tangent referenced against Farfield spring
00453         //
00454         if(DampTangent < TFar_tang * 1.0e-12) DampTangent = TFar_tang * 1.0e-12;
00455 
00456         // Check if damping force is being limited
00457         //
00458         double totalForce = Tp + dashpot * TyRate * ratio_disp;
00459         if(fabs(totalForce) >= (1.0-PYtolerance)*pult) DampTangent = 0.0;
00460 
00461         return DampTangent;
00462 }
00464 double 
00465 PySimple1::getStrain(void)
00466 {
00467     return this->Ty;
00468 }
00470 double 
00471 PySimple1::getStrainRate(void)
00472 {
00473     return this->TyRate;
00474 }
00476 int 
00477 PySimple1::commitState(void)
00478 {
00479         // Commit trial history variable -- Combined element
00480     Cy       = Ty;
00481     Cp       = Tp;
00482     Ctangent = Ttangent;
00483     
00484         // Commit trial history variables for Near Field component
00485         CNFpinr   = TNFpinr;
00486         CNFpinl   = TNFpinl; 
00487         CNFyinr   = TNFyinr;
00488         CNFyinl   = TNFyinl;    
00489         CNF_p     = TNF_p;
00490         CNF_y     = TNF_y;
00491         CNF_tang  = TNF_tang;
00492 
00493         // Commit trial history variables for Drag component
00494         CDrag_pin = TDrag_pin;
00495         CDrag_yin = TDrag_yin;
00496         CDrag_p   = TDrag_p;
00497         CDrag_y   = TDrag_y;
00498         CDrag_tang= TDrag_tang;
00499 
00500         // Commit trial history variables for Closure component
00501         CClose_yleft  = TClose_yleft;
00502         CClose_yright = TClose_yright;
00503         CClose_p      = TClose_p;
00504         CClose_y      = TClose_y;
00505         CClose_tang   = TClose_tang;
00506 
00507         // Commit trial history variables for the Gap
00508         CGap_y    = TGap_y;
00509         CGap_p    = TGap_p;
00510         CGap_tang = TGap_tang;
00511     
00512         // Commit trial history variables for the Far Field
00513         CFar_y    = TFar_y;
00514         CFar_p    = TFar_p;
00515         CFar_tang = TFar_tang;
00516     
00517     return 0;
00518 }
00519 
00521 int 
00522 PySimple1::revertToLastCommit(void)
00523 {
00524   // Reset to committed values
00525   
00526   Ty       = Cy;
00527   Tp       = Cp;
00528   Ttangent = Ctangent;
00529   
00530   
00531   TNFpinr   = CNFpinr;
00532   TNFpinl   = CNFpinl; 
00533   TNFyinr   = CNFyinr;
00534   TNFyinl   = CNFyinl;  
00535   TNF_p     = CNF_p;
00536   TNF_y     = CNF_y;
00537   TNF_tang  = CNF_tang;
00538   
00539   TDrag_pin = CDrag_pin;
00540   TDrag_yin = CDrag_yin;
00541   TDrag_p   = CDrag_p;
00542   TDrag_y   = CDrag_y;
00543   TDrag_tang= CDrag_tang;
00544   
00545   TClose_yleft  = CClose_yleft;
00546   TClose_yright = CClose_yright;
00547   TClose_p      = CClose_p;
00548   TClose_y      = CClose_y;
00549   TClose_tang   = CClose_tang;
00550   
00551   TGap_y    = CGap_y;
00552   TGap_p    = CGap_p;
00553   TGap_tang = CGap_tang;
00554   
00555   TFar_y    = CFar_y;
00556   TFar_p    = CFar_p;
00557   TFar_tang = CFar_tang;
00558   
00559   return 0;
00560 }
00561 
00563 int 
00564 PySimple1::revertToStart(void)
00565 {
00566 
00567         // If soilType = 0, then it is entering with the default constructor.
00568         // To avoid division by zero, set small nonzero values for terms.
00569         //
00570         if(soilType == 0){
00571                 pult = 1.0e-12;
00572                 y50  = 1.0e12;
00573         }
00574 
00575         // Reset gap "drag" if zero (or negative).
00576         //
00577         if(drag <= PYtolerance) drag = PYtolerance;
00578 
00579         // Only allow zero or positive dashpot values
00580         //
00581         if(dashpot < 0.0) dashpot = 0.0;
00582 
00583         // Do not allow zero or negative values for y50 or pult.
00584         //
00585         if(pult <= 0.0 || y50 <= 0.0) {
00586                 opserr << "WARNING -- only accepts positive nonzero pult and y50" << endln;
00587                 opserr << "PyLiq1: " << endln;
00588                 opserr << "pult: " << pult << "   y50: " << y50 << endln;
00589                 exit(-1);
00590         }
00591 
00592         // Initialize variables for Near Field rigid-plastic spring
00593         //
00594         if(soilType ==0) {      // This will happen with default constructor
00595                 yref  = 10.0*y50;
00596                 np    = 5.0;
00597                 Elast = 0.35;
00598                 nd    = 1.0;
00599                 TFar_tang   = pult/(8.0*pow(Elast,2.0)*y50);
00600         }
00601         else if(soilType ==1) {
00602                 yref  = 10.0*y50;
00603                 np    = 5.0;
00604                 Elast = 0.35;
00605                 nd    = 1.0;
00606                 TFar_tang   = pult/(8.0*pow(Elast,2.0)*y50);
00607         }
00608         else if (soilType == 2){
00609                 yref  = 0.5*y50;
00610                 np    = 2.0;
00611                 Elast = 0.2;
00612                 nd    = 1.0;
00613                 // This TFar_tang assumes Elast=0.2, but changes very little for other
00614                 // reasonable Elast values. i.e., API curves are quite linear initially.
00615                 TFar_tang   = 0.542*pult/y50;
00616         }
00617         else{
00618                 opserr << "WARNING -- only accepts soilType of 1 or 2" << endln;
00619                 opserr << "PyLiq1: " << endln;
00620                 opserr << "soilType: " << soilType << endln;
00621                 exit(-1);
00622         }
00623 
00624         // Far Field components: TFar_tang was set under "soil type" statements.
00625         //
00626         TFar_p  = 0.0;
00627         TFar_y  = 0.0;
00628 
00629         // Near Field components
00630         //
00631         NFkrig  = 100.0 * (0.5 * pult) / y50;
00632         TNFpinr = Elast*pult;
00633         TNFpinl = -TNFpinr;
00634         TNFyinr = TNFpinr / NFkrig;
00635         TNFyinl = -TNFyinr;
00636         TNF_p   = 0.0;
00637         TNF_y   = 0.0;
00638         TNF_tang= NFkrig;
00639 
00640         // Drag components
00641         //
00642         TDrag_pin = 0.0;
00643         TDrag_yin = 0.0;
00644         TDrag_p   = 0.0;
00645         TDrag_y   = 0.0;
00646         TDrag_tang= nd*(pult*drag-TDrag_p)*pow(y50/2.0,nd)
00647                                         *pow(y50/2.0 - TDrag_y + TDrag_yin,-nd-1.0);
00648 
00649         // Closure components
00650         //
00651         TClose_yleft = -y50/100.0;
00652         TClose_yright=  y50/100.0;
00653         TClose_p     = 0.0; 
00654         TClose_y     = 0.0;
00655         TClose_tang  = 1.8*pult*(y50/50.0)*(pow(y50/50.0+ TClose_yright - TClose_y,-2.0)
00656                 +pow(y50/50.0 + TClose_y - TClose_yleft,-2.0));
00657 
00658         // Gap (Drag + Closure in parallel)
00659         //
00660         TGap_y   = 0.0;
00661         TGap_p   = 0.0;
00662         TGap_tang= TClose_tang + TDrag_tang;
00663 
00664         // Entire element (Far field + Near field + Gap in series)
00665         //
00666         Ty       = 0.0;
00667         Tp       = 0.0;
00668         Ttangent = pow(1.0/TGap_tang + 1.0/TNF_tang + 1.0/TFar_tang, -1.0);
00669         TyRate   = 0.0;
00670 
00671         // Now get all the committed variables initiated
00672         //
00673         this->commitState();
00674 
00675     return 0;
00676 }
00677 
00679 UniaxialMaterial *
00680 PySimple1::getCopy(void)
00681 {
00682     PySimple1 *theCopy;                 // pointer to a PySimple1 class
00683         theCopy = new PySimple1();      // new instance of this class
00684         *theCopy= *this;                        // theCopy (dereferenced) = this (dereferenced pointer)
00685         return theCopy;
00686 }
00687 
00689 int 
00690 PySimple1::sendSelf(int cTag, Channel &theChannel)
00691 {
00692   int res = 0;
00693   
00694   static Vector data(39);
00695   
00696   data(0) = this->getTag();
00697   data(1) = soilType;
00698   data(2) = pult;
00699   data(3) = y50;
00700   data(4) = drag;
00701   data(5) = dashpot;
00702   data(6) = yref;
00703   data(7) = np;
00704   data(8) = Elast;
00705   data(9) = nd;
00706   data(10)= NFkrig;
00707 
00708   data(11) = CNFpinr;
00709   data(12) = CNFpinl;
00710   data(13) = CNFyinr;
00711   data(14) = CNFyinl;
00712   data(15) = CNF_p;
00713   data(16) = CNF_y;
00714   data(17) = CNF_tang;
00715 
00716   data(18) = CDrag_pin;
00717   data(19) = CDrag_yin;
00718   data(20) = CDrag_p;
00719   data(21) = CDrag_y;
00720   data(22) = CDrag_tang;
00721 
00722   data(23) = CClose_yleft;
00723   data(24) = CClose_yright;
00724   data(25) = CClose_p;
00725   data(26) = CClose_y;
00726   data(27) = CClose_tang;
00727 
00728   data(28) = CGap_y;
00729   data(29) = CGap_p;
00730   data(30) = CGap_tang;
00731 
00732   data(31) = CFar_y;
00733   data(32) = CFar_p;
00734   data(33) = CFar_tang;
00735 
00736   data(34) = Cy;
00737   data(35) = Cp;
00738   data(36) = Ctangent;
00739   data(37) = TyRate;
00740 
00741   data(38) = initialTangent;
00742 
00743   res = theChannel.sendVector(this->getDbTag(), cTag, data);
00744   if (res < 0) 
00745     opserr << "PySimple1::sendSelf() - failed to send data\n";
00746 
00747   return res;
00748 }
00749 
00751 int 
00752 PySimple1::recvSelf(int cTag, Channel &theChannel, 
00753                                FEM_ObjectBroker &theBroker)
00754 {
00755   int res = 0;
00756   
00757   static Vector data(39);
00758   res = theChannel.recvVector(this->getDbTag(), cTag, data);
00759   
00760   if (res < 0) {
00761       opserr << "PySimple1::recvSelf() - failed to receive data\n";
00762       CNF_tang = 0; 
00763       this->setTag(0);      
00764   }
00765   else {
00766     this->setTag((int)data(0));
00767         soilType = (int)data(1);
00768         pult     = data(2);
00769         y50      = data(3);
00770         drag     = data(4);
00771         dashpot  = data(5);
00772         yref     = data(6);
00773         np       = data(7);
00774         Elast    = data(8);
00775         nd       = data(9);
00776         NFkrig   = data(10);
00777 
00778         CNFpinr  = data(11);
00779         CNFpinl  = data(12);
00780         CNFyinr  = data(13);
00781         CNFyinl  = data(14);
00782         CNF_p    = data(15);
00783         CNF_y    = data(16);
00784         CNF_tang = data(17);
00785 
00786         CDrag_pin = data(18);
00787         CDrag_yin = data(19);
00788         CDrag_p   = data(20);
00789         CDrag_y   = data(21);
00790         CDrag_tang= data(22);
00791 
00792         CClose_yleft = data(23);
00793         CClose_yright= data(24);
00794         CClose_p     = data(25);
00795         CClose_y     = data(26);
00796         CClose_tang  = data(27);
00797 
00798         CGap_y    = data(28);
00799         CGap_p    = data(29);
00800         CGap_tang = data(30);
00801 
00802         CFar_y    = data(31);
00803         CFar_p    = data(32);
00804         CFar_tang = data(33);
00805 
00806         Cy        = data(34);
00807         Cp        = data(35);
00808         Ctangent  = data(36);
00809         TyRate    = data(37);
00810         
00811         initialTangent = data(38);
00812 
00813         // set the trial quantities
00814         this->revertToLastCommit();
00815   }
00816 
00817   return res;
00818 }
00819 
00821 void 
00822 PySimple1::Print(OPS_Stream &s, int flag)
00823 {
00824     s << "PySimple1, tag: " << this->getTag() << endln;
00825     s << "  soilType: " << soilType << endln;
00826     s << "  pult: " << pult << endln;
00827     s << "  y50: " << y50 << endln;
00828     s << "  drag: " << drag << endln;
00829         s << "  dashpot: " << dashpot << endln;
00830 }
00831 
00833 

Generated on Mon Oct 23 15:05:21 2006 for OpenSees by doxygen 1.5.0