Rev 579 |
Rev 757 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/* ****************************************************************** **
** OpenSees - Open System for Earthquake Engineering Simulation **
** Pacific Earthquake Engineering Research Center **
** **
** **
** (C) Copyright 1999, The Regents of the University of California **
** All Rights Reserved. **
** **
** Commercial use of this program without express permission of the **
** University of California, Berkeley, is strictly prohibited. See **
** file 'COPYRIGHT' in main directory for information on usage and **
** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. **
** **
** Developed by: **
** Frank McKenna (fmckenna@ce.berkeley.edu) **
** Gregory L. Fenves (fenves@ce.berkeley.edu) **
** Filip C. Filippou (filippou@ce.berkeley.edu) **
** **
** ****************************************************************** */
// $Revision: 1.2 $
// $Date: 2001-11-26 22:53:52 $
// $Source: /usr/local/cvs/OpenSees/SRC/element/elasticBeamColumn/ElasticBeam2d.cpp,v $
// File: ~/model/ElasticBeam2d.C
//
// Written: fmk 11/95
// Revised:
//
// Purpose: This file contains the class definition for ElasticBeam2d.
// ElasticBeam2d is a 3d beam element. As such it can only
// connect to a node with 6-dof.
#include <ElasticBeam2d.h>
#include <ElementalLoad.h>
#include <Domain.h>
#include <Channel.h>
#include <FEM_ObjectBroker.h>
#include <CrdTransf2d.h>
#include <Information.h>
#include <ElementResponse.h>
#include <Renderer.h>
#include <math.h>
#include <stdlib.h>
Matrix ElasticBeam2d::K(6,6);
Vector ElasticBeam2d::P(6);
Matrix ElasticBeam2d::kb(3,3);
ElasticBeam2d::ElasticBeam2d()
:Element(0,ELE_TAG_ElasticBeam2d),
A(0), E(0), I(0), L(0.0), rho(0.0),
Q(6), q(3), q0(6), node1Ptr(0), node2Ptr(0),
connectedExternalNodes(2), theCoordTransf(0)
{
// does nothing
}
ElasticBeam2d::ElasticBeam2d(int tag, double a, double e, double i,
int Nd1, int Nd2,
CrdTransf2d &coordTransf, double r)
:Element(tag,ELE_TAG_ElasticBeam2d),
A(a), E(e), I(i), L(0.0), rho(r),
Q(6), q(3), q0(6), node1Ptr(0), node2Ptr(0),
connectedExternalNodes(2), theCoordTransf(0)
{
connectedExternalNodes(0) = Nd1;
connectedExternalNodes(1) = Nd2;
theCoordTransf = coordTransf.getCopy();
if (!theCoordTransf)
g3ErrorHandler->fatal("ElasticBeam2d::ElasticBeam2d -- failed to get copy of coordinate transformation");
}
ElasticBeam2d::~ElasticBeam2d()
{
if (theCoordTransf)
delete theCoordTransf;
}
int
ElasticBeam2d::getNumExternalNodes(void) const
{
return 2;
}
const ID &
ElasticBeam2d::getExternalNodes(void)
{
return connectedExternalNodes;
}
int
ElasticBeam2d::getNumDOF(void)
{
return 6;
}
void
ElasticBeam2d::setDomain(Domain *theDomain)
{
if (theDomain == 0)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Domain is null");
node1Ptr = theDomain->getNode(connectedExternalNodes(0));
node2Ptr = theDomain->getNode(connectedExternalNodes(1));
if (node1Ptr == 0)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Node 1: %i does not exist",
connectedExternalNodes(0));
if (node2Ptr == 0)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Node 2: %i does not exist",
connectedExternalNodes(1));
int dofNd1 = node1Ptr->getNumberDOF();
int dofNd2 = node2Ptr->getNumberDOF();
if (dofNd1 != 3)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Node 1: %i has incorrect number of DOF",
connectedExternalNodes(0));
if (dofNd2 != 3)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Node 2: %i has incorrect number of DOF",
connectedExternalNodes(1));
this->DomainComponent::setDomain(theDomain);
if (theCoordTransf->initialize(node1Ptr, node2Ptr) != 0)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Error initializing coordinate transformation");
L = theCoordTransf->getInitialLength();
if (L == 0.0)
g3ErrorHandler->fatal("ElasticBeam2d::setDomain -- Element has zero length");
}
int
ElasticBeam2d::commitState()
{
return theCoordTransf->commitState();
}
int
ElasticBeam2d::revertToLastCommit()
{
return theCoordTransf->revertToLastCommit();
}
int
ElasticBeam2d::revertToStart()
{
return theCoordTransf->revertToStart();
}
const Matrix &
ElasticBeam2d::getTangentStiff(void)
{
theCoordTransf->update();
const Vector &v = theCoordTransf->getBasicTrialDisp();
double EoverL = E/L;
double EAoverL = A*EoverL; // EA/L
double EIoverL2 = 2.0*I*EoverL; // 2EI/L
double EIoverL4 = 2.0*EIoverL2; // 4EI/L
q(0) = EAoverL*v(0);
q(1) = EIoverL4*v(1) + EIoverL2*v(2);
q(2) = EIoverL2*v(1) + EIoverL4*v(2);
kb(0,0) = EAoverL;
kb(1,1) = kb(2,2) = EIoverL4;
kb(2,1) = kb(1,2) = EIoverL2;
return theCoordTransf->getGlobalStiffMatrix(kb,q);
}
const Matrix &
ElasticBeam2d::getSecantStiff(void)
{
return this->getTangentStiff();
}
const Matrix &
ElasticBeam2d::getDamp(void)
{
K.Zero();
return K;
}
const Matrix &
ElasticBeam2d::getMass(void)
{
K.Zero();
if (rho > 0.0) {
double m = 0.5*rho*L;
K(0,0) = m;
K(1,1) = m;
K(3,3) = m;
K(4,4) = m;
}
return K;
}
void
ElasticBeam2d::zeroLoad(void)
{
Q.Zero();
q0.Zero();
return;
}
int
ElasticBeam2d::addLoad(ElementalLoad *theLoad, double loadFactor)
{
int type;
const Vector &data = theLoad->getData(type, loadFactor);
if (type == LOAD_TAG_Beam2dUniformLoad) {
double w = data(0) * loadFactor;
// fixed end forces
double V = 0.5*w*L;
double M = V*L/6.0; // w*l*l/12
q0(1) += V;
q0(2) += -M;
q0(4) += V;
q0(5) += M;
} else if (type == LOAD_TAG_Beam2dPointLoad) {
double P = data(0) * loadFactor;
double a = data(1) * L;
double b = L-a;
double L2 = 1/(L*L);
double L3 = L2/L;
double a2 = a*a;
double b2 = b*b;
// fixed end forces
double M1 = -a * b2 * P * L2;
double M2 = a2 * b * P * L2;
double V1 = (3.0*a + b) * b2 * P * L3;
double V2 = (3.0*b + a) * a2 * P * L3;
double M1M2divL = (M1 + M2)/L;
q0(1) += V1 - M1M2divL; // -.. for affect of unbalanced M on computation of V in local
q0(2) += M1;
q0(4) += V2 + M1M2divL; // +.. for affect of unbalanced M on computation of V in local
q0(5) += M2;
} else {
g3ErrorHandler->warning("ElasticBeam2d::addLoad() - beam %d,load type %d unknown\n",
this->getTag(), type);
return -1;
}
return 0;
}
int
ElasticBeam2d::addInertiaLoadToUnbalance(const Vector &accel)
{
if (rho == 0.0)
return 0;
// Get R * accel from the nodes
const Vector &Raccel1 = node1Ptr->getRV(accel);
const Vector &Raccel2 = node2Ptr->getRV(accel);
if (3 != Raccel1.Size() || 3 != Raccel2.Size()) {
g3ErrorHandler->warning("ElasticBeam2d::addInertiaLoadToUnbalance %s\n",
"matrix and vector sizes are incompatable");
return -1;
}
// Want to add ( - fact * M R * accel ) to unbalance
// Take advantage of lumped mass matrix
double m = 0.5*rho*L;
Q(0) -= m * Raccel1(0);
Q(1) -= m * Raccel1(1);
Q(3) -= m * Raccel2(0);
Q(4) -= m * Raccel2(1);
return 0;
}
const Vector &
ElasticBeam2d::getResistingForceIncInertia()
{
P = this->getResistingForce();
const Vector &accel1 = node1Ptr->getTrialAccel();
const Vector &accel2 = node2Ptr->getTrialAccel();
double m = 0.5*rho*L;
P(0) += m * accel1(0);
P(1) += m * accel1(1);
P(3) += m * accel2(0);
P(4) += m * accel2(1);
return P;
}
const Vector &
ElasticBeam2d::getResistingForce()
{
theCoordTransf->update();
const Vector &v = theCoordTransf->getBasicTrialDisp();
double EoverL = E/L;
double EAoverL = A*EoverL; // EA/L
double EIoverL2 = 2.0*I*EoverL; // 2EI/L
double EIoverL4 = 2.0*EIoverL2; // 4EI/L
// determine q = kv + q0
q(0) = EAoverL*v(0);
q(1) = EIoverL4*v(1) + EIoverL2*v(2);
q(2) = EIoverL2*v(1) + EIoverL4*v(2);
// add the q0 forces (stored in q0(3, 2 & 5))
q(0) += q0(3);
q(1) += q0(2);
q(2) += q0(5);
// set the element reactions in basic system (stored in q0(0, 1 and 4))
static Vector p0(3);
p0(0) = q0(0);
p0(1) = q0(1);
p0(2) = q0(4);
P = theCoordTransf->getGlobalResistingForce(q, p0);
// P = P - Q;
P.addVector(1.0, Q, -1.0);
return P;
}
int
ElasticBeam2d::sendSelf(int cTag, Channel &theChannel)
{
int res = 0;
static Vector data(9);
data(0) = A;
data(1) = E;
data(2) = I;
data(3) = rho;
data(4) = this->getTag();
data(5) = connectedExternalNodes(0);
data(6) = connectedExternalNodes(1);
data(7) = theCoordTransf->getClassTag();
int dbTag = theCoordTransf->getDbTag();
if (dbTag == 0) {
dbTag = theChannel.getDbTag();
if (dbTag != 0)
theCoordTransf->setDbTag(dbTag);
}
data(8) = dbTag;
// Send the data vector
res += theChannel.sendVector(this->getDbTag(), cTag, data);
if (res < 0) {
g3ErrorHandler->warning("%s -- could not send data Vector",
"ElasticBeam2d::sendSelf");
return res;
}
// Ask the CoordTransf to send itself
res += theCoordTransf->sendSelf(cTag, theChannel);
if (res < 0) {
g3ErrorHandler->warning("%s -- could not send CoordTransf",
"ElasticBeam2d::sendSelf");
return res;
}
return res;
}
int
ElasticBeam2d::recvSelf(int cTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
{
int res = 0;
static Vector data(9);
res += theChannel.recvVector(this->getDbTag(), cTag, data);
if (res < 0) {
g3ErrorHandler->warning("%s -- could not receive data Vector",
"ElasticBeam2d::recvSelf");
return res;
}
A = data(0);
E = data(1);
I = data(2);
rho = data(3);
this->setTag((int)data(4));
connectedExternalNodes(0) = (int)data(5);
connectedExternalNodes(1) = (int)data(6);
// Check if the CoordTransf is null; if so, get a new one
int crdTag = (int)data(7);
if (theCoordTransf == 0) {
theCoordTransf = theBroker.getNewCrdTransf2d(crdTag);
if (theCoordTransf == 0) {
g3ErrorHandler->warning("%s -- could not get a CrdTransf2d",
"ElasticBeam2d::recvSelf");
return -1;
}
}
// Check that the CoordTransf is of the right type; if not, delete
// the current one and get a new one of the right type
if (theCoordTransf->getClassTag() != crdTag) {
delete theCoordTransf;
theCoordTransf = theBroker.getNewCrdTransf2d(crdTag);
if (theCoordTransf == 0) {
g3ErrorHandler->warning("%s -- could not get a CrdTransf2d",
"ElasticBeam2d::recvSelf");
return -1;
}
}
// Now, receive the CoordTransf
theCoordTransf->setDbTag((int)data(8));
res += theCoordTransf->recvSelf(cTag, theChannel, theBroker);
if (res < 0) {
g3ErrorHandler->warning("%s -- could not receive CoordTransf",
"ElasticBeam2d::recvSelf");
return res;
}
// Revert the crdtrasf to its last committed state
theCoordTransf->revertToLastCommit();
return res;
}
void
ElasticBeam2d::Print(ostream &s, int flag)
{
s << "\nElasticBeam2d: " << this->getTag() << endl;
s << "\tConnected Nodes: " << connectedExternalNodes ;
s << "\tCoordTransf: " << theCoordTransf->getTag() << endl;
double V = (q(1)+q(2))/L;
s << "\tEnd 1 Forces (P V M): " << -q(0)+q0(0) << ' ' << V + q0(1) << ' ' << q(1) << endl;
s << "\tEnd 2 Forces (P V M): " << q(0) << ' ' << -V+q0(4) << ' ' << q(2) << endl;
}
int
ElasticBeam2d::displaySelf(Renderer &theViewer, int displayMode, float fact)
{
// first determine the end points of the beam based on
// the display factor (a measure of the distorted image)
const Vector &end1Crd = node1Ptr->getCrds();
const Vector &end2Crd = node2Ptr->getCrds();
const Vector &end1Disp = node1Ptr->getDisp();
const Vector &end2Disp = node2Ptr->getDisp();
static Vector v1(3);
static Vector v2(3);
for (int i = 0; i < 2; i++) {
v1(i) = end1Crd(i) + end1Disp(i)*fact;
v2(i) = end2Crd(i) + end2Disp(i)*fact;
}
return theViewer.drawLine (v1, v2, 1.0, 1.0);
}
Response*
ElasticBeam2d::setResponse(char **argv, int argc, Information &info)
{
// stiffness
if (strcmp(argv[0],"stiffness") == 0)
return new ElementResponse(this, 1, K);
// global forces
else if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 ||
strcmp(argv[0],"globalForce") == 0 || strcmp(argv[0],"globalForces") == 0)
return new ElementResponse(this, 2, P);
// local forces
else if (strcmp(argv[0],"localForce") == 0 || strcmp(argv[0],"localForces") == 0)
return new ElementResponse(this, 3, P);
else
return 0;
}
int
ElasticBeam2d::getResponse (int responseID, Information &eleInfo)
{
double V;
switch (responseID) {
case 1: // stiffness
return eleInfo.setMatrix(this->getTangentStiff());
case 2: // global forces
return eleInfo.setVector(this->getResistingForce());
case 3: // local forces
// Axial
P(3) = q(0);
P(0) = -q(0) + q0(0);
// Moment
P(2) = q(1);
P(5) = q(2);
// Shear
V = (q(1)+q(2))/L;
P(1) = V + q0(1);
P(4) = -V + q0(4);
return eleInfo.setVector(P);
default:
return -1;
}
}
int
ElasticBeam2d::setParameter (char **argv, int argc, Information &info)
{
// E of the beam interior
if (strcmp(argv[0],"E") == 0) {
info.theType = DoubleType;
return 1;
}
// A of the beam interior
else if (strcmp(argv[0],"A") == 0) {
info.theType = DoubleType;
return 2;
}
// I of the beam interior
else if (strcmp(argv[0],"I") == 0) {
info.theType = DoubleType;
return 3;
}
else
return -1;
}
int
ElasticBeam2d::updateParameter (int parameterID, Information &info)
{
switch (parameterID) {
case -1:
return -1;
case 1:
this->E = info.theDouble;
return 0;
case 2:
this->A = info.theDouble;
return 0;
case 3:
this->I = info.theDouble;
return 0;
default:
return -1;
}
}