Rev 1181 |
Rev 1271 |
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.5 $
// $Date: 2002-12-16 21:10:02 $
// $Source: /usr/local/cvs/OpenSees/SRC/element/feap/fElement.cpp,v $
// File: ~/element/fortran/fElement.C
//
// Written: fmk
// Created: 07/98
// Revision: A
//
// Description: This file contains the implementation for the fElement class.
//
// What: "@(#) fElement.C, revA"
#include "fElement.h"
#include <Domain.h>
#include <Node.h>
#include <Channel.h>
#include <FEM_ObjectBroker.h>
#include <UniaxialMaterial.h>
#include <Renderer.h>
#include <math.h>
#include <stdlib.h>
// initialise all class wise pointers to 0 and numfElements to 0
Matrix **fElement::fElementM;
Vector **fElement::fElementV;
double *fElement::r;
double *fElement::s;
double *fElement::ul;
double *fElement::xl;
double *fElement::tl;
int *fElement::ix;
int fElement::numfElements(0);
static double *work = 0;
static int sizeWork = 0;
#define MAX_NST 64
// constructor:
// responsible for allocating the necessary space needed by each object
// and storing the tags of the fElement end nodes.
fElement::fElement(int tag,
int classTag,
int EleType,
int sizeD, int NEN,
int NDM, int NDF,
int numNh1, int numNh3)
:Element(tag,classTag), nh1(numNh1), nh3(numNh3), h(0), eleType(EleType),
theNodes(0), u(0), nen(NEN), ndf(NDF), ndm(NDM), d(0), data(0),
connectedNodes(0),nrCount(0), theLoad(0), Ki(0)
{
// allocate space for h array
if (nh1 < 0) nh1 = 0;
if (nh3 < 0) nh3 = 0;
if (nh1 != 0 || nh3 != 0) {
int sizeH = 2*nh1 + nh3;
h = new double[sizeH];
if (sizeWork < sizeH) {
if (work != 0)
delete [] work;
work = new double[sizeH];
if (work == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory creating h of size " << 2*nh1+nh3 << endl;
exit(-1);
}
sizeWork = sizeH;
}
if (h == 0 || work == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory creating h of size " << 2*nh1+nh3 << endl;
exit(-1);
}
for (int i=0; i<sizeH; i++)
h[i] = 0.0;
}
connectedNodes = new ID(NEN);
d = new double[sizeD];
for (int i=0; i<sizeD; i++) d[i] = 0.0;
data = new Vector(d, sizeD);
// allocate space for static varaibles on creation of first instance
if (numfElements == 0) {
fElementM = new Matrix *[MAX_NST+1];
fElementV = new Vector *[MAX_NST+1];
s = new double[(MAX_NST+1)*(MAX_NST+1)];
r = new double[MAX_NST+1];
ul = new double[(MAX_NST+1)*6];
xl = new double[MAX_NST+1];
tl = new double[MAX_NST+1];
ix = new int[MAX_NST+1];
// check space was available -- otherwise exit
if (fElementM == 0 || fElementV == 0 || ix == 0 ||
r == 0 || s == 0 || ul == 0 || xl == 0 || tl == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory initialising static stuff\n";
exit(-1);
}
for (int i=0; i<MAX_NST+1; i++) {
fElementM[i] = 0;
fElementV[i] = 0;
}
fElementM[0] = new Matrix(1,1); // dummy for error
fElementV[0] = new Vector(1);
}
// increment number of elements
numfElements++;
}
fElement::fElement(int tag,
int classTag,
int EleType,
int sizeD, int NEN,
int NDM, int NDF, int iow)
:Element(tag,classTag), nh1(0), nh3(0), h(0), eleType(EleType),
theNodes(0), u(0), nen(NEN), ndf(NDF), ndm(NDM), d(0), data(0),
connectedNodes(0), nrCount(0), theLoad(0), Ki(0)
{
connectedNodes = new ID(NEN);
d = new double[sizeD];
data = new Vector(d, sizeD);
if (d == 0 || data == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory creating d of size " << sizeD << endl;
exit(-1);
}
for (int i=0; i<sizeD; i++) d[i] = 0.0;
// invoke the elmt() routine with isw == 1 to read in the element data
// and create room for the h array stuff needed by the element
this->invokefInit(1, iow);
// allocate space for h array
if (nh1 < 0) nh1 = 0;
if (nh3 < 0) nh3 = 0;
if (nh1 != 0 || nh3 != 0) {
int sizeH = 2*nh1+nh3;
h = new double[sizeH];
if (sizeWork < sizeH) {
if (work != 0)
delete [] work;
work = new double[sizeH];
if (work == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory creating h of size " << 2*nh1+nh3 << endl;
exit(-1);
}
sizeWork = sizeH;
}
if (h == 0 || work == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << this->getTag();
cerr << " ran out of memory creating h of size " << sizeH << endl;
exit(-1);
}
else
for (int i=0; i<sizeH; i++) h[i] = 0.0;
}
// allocate space for static varaibles on creation of first instance
if (numfElements == 0) {
fElementM = new Matrix *[MAX_NST+1];
fElementV = new Vector *[MAX_NST+1];
s = new double[(MAX_NST+1)*(MAX_NST+1)];
r = new double[MAX_NST+1];
ul = new double[(MAX_NST+1)*6];
xl = new double[MAX_NST+1];
tl = new double[MAX_NST+1];
ix = new int[MAX_NST+1];
// check space was available -- otherwise exit
if (fElementM == 0 || fElementV == 0 || ix == 0 ||
r == 0 || s == 0 || ul == 0 || xl == 0 || tl == 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << tag;
cerr << " ran out of memory initialising static stuff\n";
exit(-1);
}
for (int i=0; i<MAX_NST+1; i++) {
fElementM[i] = 0;
fElementV[i] = 0;
}
fElementM[0] = new Matrix(1,1); // dummy for error
fElementV[0] = new Vector(1);
}
// increment number of elements
numfElements++;
}
// constructor:
// invoked by a FEM_ObjectBroker - blank object that recvSelf needs
// to be invoked upon
fElement::fElement(int classTag)
:Element(0, classTag), nh1(0), nh3(0), h(0),
theNodes(0), u(0), nen(0), ndf(0), ndm(0), d(0), data(0), connectedNodes(0),
theLoad(0), Ki(0)
{
// does nothing
}
// destructor
// delete must be invoked on any objects created by the object
// and on the matertial object.
fElement::~fElement()
{
// clear up any space allocated for individual object
if (h != 0)
delete [] h;
if (u != 0)
delete [] u;
if (theNodes != 0)
delete [] theNodes;
if (data != 0)
delete data;
if (connectedNodes != 0)
delete connectedNodes;
if (d != 0)
delete [] d;
if (theLoad != 0)
delete theLoad;
if (Ki != 0)
delete Ki;
// if last element - clear up space allocated
numfElements --;
if (numfElements == 0) {
for (int i=0; i<MAX_NST+1; i++) {
if (fElementM[i] != 0) delete fElementM[i];
if (fElementV[i] != 0) delete fElementV[i];
}
delete [] fElementM;
delete [] fElementV;
delete [] s;
delete [] r;
delete [] ul;
delete [] xl;
delete [] tl;
delete [] ix;
}
}
int
fElement::getNumExternalNodes(void) const
{
return connectedNodes->Size();
}
const ID &
fElement::getExternalNodes(void)
{
return *connectedNodes;
}
Node **
fElement::getNodePtrs(void)
{
return theNodes;
}
int
fElement::getNumDOF(void)
{
return ndf*nen;
}
void
fElement::setDomain(Domain *theDomain)
{
// check Domain is not null - invoked when object removed from a domain
if (theDomain == 0) {
ndm = 0;
nen = 0;
ndf = 0;
if (theNodes != 0) {
delete [] theNodes;
theNodes = 0;
}
return;
}
// set up the pointers to the nodes
const ID &theNodeTags = this->getExternalNodes();
int numNodes = theNodeTags.Size();
theNodes = new Node *[numNodes];
for (int i=0; i<numNodes; i++) {
Node *theNode = theDomain->getNode(theNodeTags(i));
if (theNode == 0) {
cerr << "WARNING fElement::setDomain(Domain *theDomain) - node: ";
cerr << theNodeTags(i) << " does not exist in domain for ele " << *this;
ndm = 0; nen = 0; ndf = 0;
return;
}
// set up the pointer to the node
theNodes[i] = theNode;
// check the dimension and number of dof at the node
// is the same as all the other nodes of the element
if (i == 0) {
const Vector &crds = theNode->getCrds();
ndm = crds.Size(); // ndm = dimesion of mesh
ndf = theNode->getNumberDOF(); // ndf = number of dof at nodes
} else {
const Vector &crds = theNode->getCrds();
if (ndm != crds.Size()) {
cerr << "WARNING fElement::setDomain(Domain *theDomain) - node: ";
cerr << theNodeTags(i) << " not in correct dimension " << *this;
ndm = 0; nen = 0; ndf = 0;
return;
}
if (ndf != theNode->getNumberDOF()) {
cerr << "WARNING fElement::setDomain(Domain *theDomain) - node: ";
cerr << theNodeTags(i) << " does not have correct #DOF " << *this;
ndm = 0; nen = 0; ndf = 0;
return;
}
}
}
// call the DomainComponent class method THIS IS VERY IMPORTANT
this->DomainComponent::setDomain(theDomain);
// set nen - the number of element nodes
nen = numNodes;
// allocate memory for u
int nst = ndf*nen;
u = new double[nst];
if (u == 0) {
cerr << "WARNING fElement::setDomain(Domain *theDomain) - ";
cerr << " ran out of memory creating u of size: " << nen*ndf << *this;
ndm = 0; nen = 0; ndf = 0;
return;
}
// zero u
for (int ii=0; ii<nst; ii++)
u[ii] = 0.0;
theLoad = new Vector(nst);
if (theLoad == 0) {
g3ErrorHandler->fatal("Truss::setDomain - truss %d %s %d\n",
this->getTag(),
"out of memory creating vector of size",
nst);
return;
}
// allocate the Matrix and Vector objects if none yet for this size nst
if (fElementM[nst] == 0) {
fElementM[nst] = new Matrix(s,nst,nst);
fElementV[nst] = new Vector(r,nst);
if ((fElementM[nst] == 0) || (fElementV[nst] == 0)) {
cerr << "WARNING fElement::setDomain(Domain *theDomain) - ";
cerr << " ran out of memory creating Matrix and Vector for " << *this;
ndm = 0; nen = 0; ndf = 0;
return;
}
}
}
int
fElement::commitState()
{
int retVal = 0;
// call element commitState to do any base class stuff
if ((retVal = this->Element::commitState()) != 0) {
cerr << "fElement::commitState () - failed in base class";
}
if (nh1 != 0)
for (int i=0; i<nh1; i++)
h[i] = h[i+nh1];
nrCount = 0;
return retVal;
}
int
fElement::revertToLastCommit()
{
if (nh1 != 0)
for (int i=0; i<nh1; i++)
h[i+nh1] = h[i];
nrCount = 0;
return 0;
}
int
fElement::revertToStart()
{
// does nothing
return 0;
}
const Matrix &
fElement::getTangentStiff(void)
{
// check for quick return
if (nen == 0)
return (*fElementM[0]);
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 1.0; ctan[1] = 0.0; ctan[2] = 0.0;
int ior = 0; int iow = 0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int nstR = this->readyfRoutine(false);
// zero the matrix
fElementM[nstR]->Zero();
// invoke the fortran subroutine
int isw = 3;
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
// check nst is as determined in readyfRoutine()
if (nstI != nstR) {
cerr << "FATAL fElement::getTangentStiff() problems with incompatable nst";
cerr << " ready: " << nstR << " invoke: " << nstI << endl;
exit(-1);
}
// return the matrix
return *(fElementM[nstR]);
}
const Matrix &
fElement::getDamp(void)
{
// check for quick return
if (nen == 0)
return (*fElementM[0]);
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 0.0; ctan[1] = 1.0; ctan[2] = 0.0;
int ior = 0; int iow = 0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int NH1, NH2, NH3;
int nstR = this->readyfRoutine(true);
// zero the matrix
fElementM[nstR]->Zero();
// invoke the fortran subroutine
int isw = 3; int nst = nen*ndf; int n = this->getTag();
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
// check nst is as determined in readyfRoutine()
if (nstI != nstR) {
cerr << "FATAL fElement::getTangentStiff() problems with incompatable nst";
cerr << " ready: " << nstR << " invoke: " << nstI << endl;
exit(-1);
}
// return the matrix
return *(fElementM[nstR]);
}
const Matrix &
fElement::getMass(void)
{
// check for quick return
if (nen == 0)
return (*fElementM[0]);
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 0.0; ctan[1] = 0.0; ctan[2] = 1.0;
int ior = 0; int iow = 0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int NH1, NH2, NH3;
int nstR = this->readyfRoutine(true);
// zero the matrix and vector (consistant and lumped)
fElementM[nstR]->Zero();
fElementV[nstR]->Zero();
// invoke the fortran subroutine
int isw = 5; int nst = nen*ndf; int n = this->getTag();
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
// check nst is as determined in readyfRoutine()
if (nstI != nstR) {
cerr << "FATAL fElement::getTangentStiff() problems with incompatable nst";
cerr << " ready: " << nstR << " invoke: " << nstI << endl;
exit(-1);
}
// return the matrix
return *(fElementM[nstR]);
}
void
fElement::zeroLoad(void)
{
// does nothing now
if (theLoad != 0)
theLoad->Zero();
}
int
fElement::addLoad(ElementalLoad *theLoad, double loadFactor)
{
g3ErrorHandler->warning("fElement::addLoad - load type unknown for truss with tag: %d",
this->getTag());
return -1;
}
int
fElement::addInertiaLoadToUnbalance(const Vector &accel)
{
const Matrix &mass = this->getMass();
int nstR = nen*ndf;
Vector &resid = *(fElementV[nstR]);
static const int numberNodes = 4 ;
// store computed RV fro nodes in resid vector
int count = 0;
for (int i=0; i<nen; i++) {
const Vector &Raccel = theNodes[i]->getRV(accel);
for (int j=0; j<ndf; j++)
resid(count++) = Raccel(i);
}
// create the load vector if one does not exist
if (theLoad == 0)
theLoad = new Vector(nstR);
// add -M * RV(accel) to the load vector
theLoad->addMatrixVector(1.0, mass, resid, -1.0);
return 0;
}
const Vector &
fElement::getResistingForce()
{
// check for quick return
if (nen == 0)
return (*fElementV[0]);
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 0.0; ctan[1] = 0.0; ctan[2] = 0.0;
int ior = 0; int iow = 0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int NH1, NH2, NH3;
int nstR = this->readyfRoutine(false);
// zero the vector
fElementV[nstR]->Zero();
// invoke the fortran subroutine
int isw = 6; int nst = nen*ndf; int n = this->getTag();
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
// check nst is as determined in readyfRoutine()
if (nstI != nstR) {
cerr << "FATAL fElement::getTangentStiff() problems with incompatable nst";
cerr << " ready: " << nstR << " invoke: " << nstI << endl;
exit(-1);
}
// negate the sign of the loads -- feap elements return -ku
(*fElementV[nstR]) *= -1.0;
// add the applied loads from other sources
(*fElementV[nstR]) -= *theLoad;
// return the matrix
return *(fElementV[nstR]);
}
const Vector &
fElement::getResistingForceIncInertia()
{
// check for quick return
if (nen == 0)
return (*fElementV[0]);
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 0.0; ctan[1] = 0.0; ctan[2] = 0.0;
int ior = 0; int iow = 0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int NH1, NH2, NH3;
int nstR = this->readyfRoutine(true);
// zero the vector
fElementV[nstR]->Zero();
// invoke the fortran subroutine
int isw = 6; int nst = nen*ndf; int n = this->getTag();
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
// check nst is as determined in readyfRoutine()
if (nstI != nstR) {
cerr << "FATAL fElement::getTangentStiff() problems with incompatable nst";
cerr << " ready: " << nstR << " invoke: " << nstI << endl;
exit(-1);
}
// negate the sign of the loads -- feap elements return -ku
(*fElementV[nstR]) *= -1.0;
// return the matrix
return *(fElementV[nstR]);
}
int
fElement::sendSelf(int commitTag, Channel &theChannel)
{
cerr << "fElement::sendSelf() - not yet implemented\n";
return -1;
}
int
fElement::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
{
cerr << "fElement::recvSelf() - not yet implemented\n";
return -1;
}
int
fElement::displaySelf(Renderer &theViewer, int displayMode, float fact)
{
return 0;
}
void
fElement::Print(ostream &s, int flag)
{
int ior = 0; int iow = 1;
if (s == cerr || s == cout)
ior = -1;
else {
s << "fElement::Print() - can only print to cerr or cout at present\n";
ior = -1;
}
// get the current load factor
Domain *theDomain=this->getDomain();
double dm = theDomain->getCurrentTime();
// set ctan, ior and iow
double ctan[3];
ctan[0] = 0.0; ctan[1] = 0.0; ctan[2] = 0.0;
// call the ready routine to set ul, xl, tl and ix, NH1, NH2 and NH3
int NH1, NH2, NH3;
int nstR = this->readyfRoutine(false);
// invoke the fortran subroutine
int isw = 4; int nst = nen*ndf; int n = this->getTag();
int nstI = this->invokefRoutine(ior, iow, ctan, isw);
}
#ifdef _WIN32
extern "C" int _stdcall GETCOMMON(int *mynh1, int *mynh3, int *sizeH,
double *myh);
extern "C" int _stdcall FILLCOMMON(int *mynen, double *mydm, int *myn,
int *myior, int *myiow, int *mynh1,
int *mynh2, int *mynh3, int *sumnh,
double *myh, double *myctan,
int *nrCount);
extern "C" int _stdcall ELMT01(double *d, double *ul, double *xl, int *ix,
double *tl, double *s, double *r, int *ndf,
int *ndm, int *nst, int *isw);
extern "C" int _stdcall ELMT02(double *d, double *ul, double *xl, int *ix,
double *tl, double *s, double *r, int *ndf,
int *ndm, int *nst, int *isw);
extern "C" int _stdcall ELMT03(double *d, double *ul, double *xl, int *ix,
double *tl, double *s, double *r, int *ndf,
int *ndm, int *nst, int *isw);
extern "C" int _stdcall ELMT04(double *d, double *ul, double *xl, int *ix,
double *tl, double *s, double *r, int *ndf,
int *ndm, int *nst, int *isw);
extern "C" int _stdcall ELMT05(double *d, double *ul, double *xl, int *ix,
double *tl, double *s, double *r, int *ndf,
int *ndm, int *nst, int *isw);
#define getcommon_ GETCOMMON
#define fillcommon_ FILLCOMMON
#define elmt01_ ELMT01
#define elmt02_ ELMT02
#define elmt03_ ELMT03
#define elmt04_ ELMT03
#define elmt05_ ELMT05
#else
extern "C" int getcommon_(int *mynh1, int *mynh3, int *sizeH, double *myh);
extern "C" int fillcommon_(int *mynen, double *mydm, int *myn, int *myior,
int *myiow, int *mynh1, int *mynh2, int *mynh3,
int *sumnh, double *myh, double *myctan,
int *nrCount);
extern "C" int elmt01_(double *d, double *ul, double *xl, int *ix, double *tl,
double *s, double *r, int *ndf, int *ndm, int *nst,
int *isw);
extern "C" int elmt02_(double *d, double *ul, double *xl, int *ix, double *tl,
double *s, double *r, int *ndf, int *ndm, int *nst,
int *isw);
extern "C" int elmt03_(double *d, double *ul, double *xl, int *ix, double *tl,
double *s, double *r, int *ndf, int *ndm, int *nst,
int *isw);
extern "C" int elmt04_(double *d, double *ul, double *xl, int *ix, double *tl,
double *s, double *r, int *ndf, int *ndm, int *nst,
int *isw);
extern "C" int elmt05_(double *d, double *ul, double *xl, int *ix, double *tl,
double *s, double *r, int *ndf, int *ndm, int *nst,
int *isw);
#endif
int
fElement::invokefRoutine(int ior, int iow, double *ctan, int isw)
{
// fill the common blocks
// determine position in h of nh1, nh2 and nh3 - remember Fortarn indexing
int NH1, NH2, NH3;
if (nh1 != 0) {
NH1 = 1;
NH2 = nh1 + NH1;
NH3 = nh1 + NH2;
} else {
NH1 = 1;
NH2 = 1;
NH3 = 1;
}
int NDM = ndm;
int NDF = ndf;
int n = this->getTag();
int sum = 2*nh1 + nh3;
int count = nrCount;
double dm = 0.0; // load factor
fillcommon_(&nen, &dm, &n, &ior, &iow, &NH1, &NH2, &NH3, &sum,
h, ctan, &count);
// invoke the fortran subroutine
int nst = nen*ndf;
if (nst != 0) {
if (eleType == 1)
elmt01_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 2)
elmt02_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 3)
elmt03_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 4)
elmt04_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 5)
elmt05_(d,ul,xl,ix,tl,s,r,&ndf,&NDM,&nst,&isw);
else {
cerr << "fElement::invokefRoutine() unknown element type ";
cerr << eleType << endl;
}
// now copy the stuff from common block to h array
getcommon_(&NH1,&NH3,&sum,h);
}
return nst;
}
int
fElement::invokefInit(int isw, int iow)
{
// fill the common blocks
// determine position in h of nh1, nh2 and nh3 - remember Fortarn indexing
int NH1 =0;
int NH2 =0;
int NH3 =0;
int NDM = ndm;
int NDF = ndf;
double ctan[3];
int n = this->getTag();
int sum = 0;
int ior = 0;
int count = nrCount;
double dm = 0.0;
fillcommon_(&nen, &dm, &n, &ior, &iow, &NH1, &NH2, &NH3, &sum,
h, ctan, &count);
// invoke the fortran subroutine
int nst = nen*ndf;
if (nst != 0) {
if (eleType == 1)
elmt01_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 2)
elmt02_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 3)
elmt03_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 4)
elmt04_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else if (eleType == 5)
elmt05_(d,ul,xl,ix,tl,s,r,&NDF,&NDM,&nst,&isw);
else {
cerr << "fElement::invokefRoutine() unknown element type ";
cerr << eleType << endl;
}
if (nst < 0) {
cerr << "FATAL: fElement::fElement() - eleTag: " << this->getTag();
cerr << " ran out of memory creating h of size " << nst << endl;
exit(-1);
}
}
// now get the size of the state info needed by the element
sum = 0;
getcommon_(&NH1,&NH3,&sum,h);
nh1 = NH1; nh3=NH3;
return 0;
}
int
fElement::readyfRoutine(bool incInertia)
{
// determine nst
int nst = ndf*nen;
// loop over nodes - fill in xl, ul, ix as we go
int posUl = 0;
int posXl = 0;
for (int j=0; j<nen; j++) {
Node *theNode = theNodes[j];
// add the node tag to ix
ix[j] = theNode->getTag();
// add displacement, velocity, accel and increments to ul
// Note: we get nodal vel and accel only if inertia is true, this
// will save memory in static analysis -- look at Node implementation
const Vector &trialDisp = theNode->getTrialDisp();
const Vector &commitDisp = theNode->getDisp();
const Vector &crd = theNode->getCrds();
// add the coordinates to xl
int crdSize = crd.Size();
for (int i=0; i<crdSize; i++) {
xl[posXl] = crd(i);
posXl++;
}
if (incInertia == true) {
const Vector &trialVel = theNode->getTrialVel();
const Vector &trialAccel = theNode->getTrialAccel();
const Vector &commitVel = theNode->getVel();
for (int i=0; i<trialDisp.Size(); i++) {
double trialDispI = trialDisp(i);
ul[posUl] = trialDispI;
ul[posUl+nst] = trialDispI - commitDisp(i);
ul[posUl+2*nst] = trialDispI - u[posUl];
ul[posUl+3*nst] = trialVel(i);
ul[posUl+4*nst] = trialAccel(i);
ul[posUl+5*nst] = commitVel(i);
u[posUl] = trialDispI; // u(k-1) on next call
posUl++;
}
} else {
for (int i=0; i<trialDisp.Size(); i++) {
double trialDispI = trialDisp(i);
ul[posUl] = trialDispI;
ul[posUl+nst] = trialDispI - commitDisp(i);
ul[posUl+2*nst] = trialDispI - u[posUl];
ul[posUl+3*nst] = 0.0;
ul[posUl+4*nst] = 0.0;
ul[posUl+5*nst] = 0.0;
u[posUl] = trialDispI;
posUl++;
}
}
}
// check we have a matrix and vector created for an object of this size
if (fElementM[nst] == 0) {
fElementM[nst] = new Matrix(s,nst,nst);
fElementV[nst] = new Vector(r,nst);
if (fElementM[nst] == 0 || fElementV[nst] == 0) {
cerr << "FATAL fElement::getTangentStiff() nst: " << nst;
cerr << "ran out of memory\n";
exit(-1);
}
}
return nst;
}
int
fElement::update()
{
// determine nst
int nst = ndf*nen;
// increment the newton-raphson count -- needed for Prof. Fillipou's element
nrCount++;
return 0;
}
const Matrix &
fElement::getInitialStiff(void)
{
if (Ki == 0)
Ki = new Matrix(this->getTangentStiff());
if (Ki == 0) {
cerr << "FATAL fElement::getInitialStiff() -";
cerr << "ran out of memory\n";
exit(-1);
}
return *Ki;
}