OPS procedure

For developers writing C++, Fortran, Java, code who have questions or comments to make.

Moderators: silvia, selimgunay, Moderators

Post Reply
filgen
Posts: 3
Joined: Tue Dec 10, 2013 3:05 am
Location: univerisity of coimbra

OPS procedure

Post by filgen »

Hello,

I would like to consider a new structural element with 4 nodes, 4 rotational springs and 12 degrees of freedom.
I believe that there are some mistakes in the OPS procedure that I wrote at the beginning of the .cpp file.

The OPS procedure is


#ifdef _USRDLL
#define OPS_Export extern "C" _declspec(dllexport)
#elif _MACOSX
#define OPS_Export extern "C" __attribute__((visibility("default")))
#else
#define OPS_Export extern "C"
#endif

static int numMySimpleJoint2D = 0;

OPS_Export void *
OPS_SimpleJoint2D(int argc, Domain *TheDomain)
{

Element *theSimpleJoint2D = 0;

int numRemainingArgs = OPS_GetNumRemainingInputArgs();

if (numRemainingArgs == 0) { // parallel processing
theSimpleJoint2D = new SimpleJoint2D();
return theSimpleJoint2D;
}

if (numRemainingArgs != 10) {
opserr << "ERROR - SimpleJoint2D not enough args provided, want: element SimpleJoint2D tag? iNode? jNode? kNode? lNode? iSpring? jSpring? kSpring? lSpring? NLGEOM?\n";
numMySimpleJoint2D++;
}

// get the id and end nodes
int iData[10]; // tag, iNode, jNode, kNode, lNode, iSpring, jSpring, kSpring, lSpring, NLGEOM
int numData;

// void setDomain(Domain *theDomain);

int eleTag = iData[0];
int iNode = iData [1];
int jNode = iData [2];
int kNode = iData [3];
int lNode = iData [4];
int LrgDisp = iData[9];

int matIDi = iData[5];
UniaxialMaterial *spring1 = OPS_GetUniaxialMaterial(matIDi);

if (spring1 == 0) {
opserr << "WARNING material with tag " << matIDi << "not found for element " << eleTag << endln;
return 0;
}

numData = 1;
if (OPS_GetIntInput(&numData, &iData[6]) != 0) {
opserr << "WARNING error reading node j tag for element" << eleTag << endln;
return 0;
}

int matIDj = iData[6];
UniaxialMaterial *spring2 = OPS_GetUniaxialMaterial(matIDj);

if (spring2 == 0) {
opserr << "WARNING material with tag " << matIDj << "not found for element " << eleTag << endln;
return 0;
}

numData = 1;
if (OPS_GetIntInput(&numData, &iData[7]) != 0) {
opserr << "WARNING error reading node k tag for element" << eleTag << endln;
return 0;
}

int matIDk = iData[7];
UniaxialMaterial *spring3 = OPS_GetUniaxialMaterial(matIDk);

if (spring3 == 0) {
opserr << "WARNING material with tag " << matIDk << "not found for element " << eleTag << endln;
return 0;
}

numData = 1;
if (OPS_GetIntInput(&numData, &iData[8]) != 0) {
opserr << "WARNING error reading node l tag for element" << eleTag << endln;
return 0;
}

int matIDl = iData[8];
UniaxialMaterial *spring4 = OPS_GetUniaxialMaterial(matIDl);

if (spring4 == 0) {
opserr << "WARNING material with tag " << matIDl << "not found for element " << eleTag << endln;
return 0;
}

// now create the SimpleJoint2D and add it to the Domain

theSimpleJoint2D = new SimpleJoint2D(eleTag, iNode, jNode, kNode, lNode, *spring1, *spring2, *spring3, *spring4, TheDomain, LrgDisp);


if (theSimpleJoint2D == 0) {
opserr << "WARNING ran out of memory creating element with tag " << eleTag << endln;
return 0;
}




The warning message is "OPS_GetNodeIncrDisp - no node with tag ..."

Thank you in advance for your help.
fmk
Site Admin
Posts: 5884
Joined: Fri Jun 11, 2004 2:33 pm
Location: UC Berkeley
Contact:

Re: OPS procedure

Post by fmk »

why are you calling the function in the first place? it looks like you have a class. this function is for c or fortran element routines (you can call it but the code will be a lot slower than if you had set a pointer to the node as demo'd in the example element).

anyway that is not an answer to the question. as the message says it cannot find a node with the specified tag that you are omitting in the message above . did you construct the nodes in the model with the tag that is output by the message, is the node tag yu think you provided different from the message? if both are trueit is an interesting prblem that may need to get tracked down. as i don't have your code: in the setDomain method of your element see if the node exists in the domain that is getting passed in.
filgen
Posts: 3
Joined: Tue Dec 10, 2013 3:05 am
Location: univerisity of coimbra

Re: OPS procedure

Post by filgen »

Thank you for your help!
I did some change in my file following the indication of "Add a New Element C++" (http://opensees.berkeley.edu/wiki/index ... nt_C%2B%2B) and "Truss2D.cpp" ((root)/trunk/DEVELOPER/element/cpp/Truss2D.cpp).
I found the error message "OPS_GetNodeIncrDisp - no node with tag 3.0030e+007" and I didn't define a node with this tag in my .tcl file.
This is my complete .cpp file.

#include "SimpleJoint2D.h"

#include <elementAPI.h>
#include <G3Globals.h>

#include <Information.h>
#include <Domain.h>
#include <Node.h>
#include <Channel.h>
#include <Message.h>
#include <FEM_ObjectBroker.h>
#include <UniaxialMaterial.h>
#include <Renderer.h>
#include <ElementResponse.h>

#include <math.h>
#include <stdlib.h>
#include <string.h>
// #include <InternalSpring.h>


// initialise the class wide variables
Matrix SimpleJoint2D::SimpleJoint2DK(12,12);
Vector SimpleJoint2D::SimpleJoint2DR(12);


#ifdef _USRDLL
#define OPS_Export extern "C" _declspec(dllexport)
#elif _MACOSX
#define OPS_Export extern "C" __attribute__((visibility("default")))
#else
#define OPS_Export extern "C"
#endif

static int numMySimpleJoint2D = 0;

OPS_Export void *
OPS_SimpleJoint2D()
{
// print out a message about who wrote this element & any copyright info wanted
if (numMySimpleJoint2D == 0) {
opserr << "SimpleJoint2D element - Written by FG\n";
numMySimpleJoint2D++;
}

Element *theSimpleJoint2D = 0;

int numRemainingArgs = OPS_GetNumRemainingInputArgs();
if (numRemainingArgs == 0) { // parallel processing
theSimpleJoint2D = new SimpleJoint2D();
return theSimpleJoint2D;
}
if (numRemainingArgs < 9) {
opserr << "ERROR - SimpleJoint2D not enough args provided, want: element SimpleJoint2D tag? iNode? jNode? kNode? lNode? iSpring? jSpring? kSpring? lSpring?\n";
return 0;
}




// get the id and end nodes
int iData[9]; // tag, iNode, jNode, kNode, lNode, iSpring, jSpring, kSpring, lSpring
//int numData;


int eleTag = iData[0];
int iNode = iData [1];
int jNode = iData [2];
int kNode = iData [3];
int lNode = iData [4];



int matIDi = iData[5];
UniaxialMaterial *spring1 = OPS_GetUniaxialMaterial(matIDi);

int matIDj = iData[6];
UniaxialMaterial *spring2 = OPS_GetUniaxialMaterial(matIDj);

int matIDk = iData[7];
UniaxialMaterial *spring3 = OPS_GetUniaxialMaterial(matIDk);

int matIDl = iData[8];
UniaxialMaterial *spring4 = OPS_GetUniaxialMaterial(matIDl);



// now create the SimpleJoint2D and add it to the Domain

theSimpleJoint2D = new SimpleJoint2D(iData[0], iNode, jNode, kNode, lNode, *spring1, *spring2, *spring3, *spring4);


return theSimpleJoint2D;
}



SimpleJoint2D::SimpleJoint2D(int tag,
int Nd1, int Nd2, int Nd3, int Nd4,
UniaxialMaterial &spring1, UniaxialMaterial &spring2,
UniaxialMaterial &spring3, UniaxialMaterial &spring4)
:Element(tag, 0),
externalNodes(4), h(0.0), d(0.0), A(0.0)

{
// get a copy of the material object for our own use
theSprings [1] = spring1.getCopy();
if (theSprings [1] == 0) {
opserr << "FATAL SimpleJoint2D::SimpleJoint2D() - out of memory, could not get a copy of the Spring1\n";
exit(-1);
}
theSprings [2] = spring2.getCopy();
if (theSprings [2] == 0) {
opserr << "FATAL SimpleJoint2D::SimpleJoint2D() - out of memory, could not get a copy of the Spring2\n";
exit(-1);
}
theSprings [3] = spring3.getCopy();
if (theSprings [3] == 0) {
opserr << "FATAL SimpleJoint2D::SimpleJoint2D() - out of memory, could not get a copy of the Spring3\n";
exit(-1);
}
theSprings [4] = spring4.getCopy();
if (theSprings [4] == 0) {
opserr << "FATAL SimpleJoint2D::SimpleJoint2D() - out of memory, could not get a copy of the Spring4\n";
exit(-1);
}



// fill in the ID containing external node info with node id's
if (externalNodes.Size() != 4) {
opserr << "FATAL SimpleJoint2D::SimpleJoint2D() - out of memory, could not create an ID of size 2\n";
exit(-1);
}

externalNodes(0) = Nd1;
externalNodes(1) = Nd2;
externalNodes(2) = Nd3;
externalNodes(3) = Nd4;

theNodes[0] = 0;
theNodes[1] = 0;
theNodes[2] = 0;
theNodes[3] = 0;
}

// constructor which should be invoked by an FE_ObjectBroker only
SimpleJoint2D::SimpleJoint2D()
:Element(0, 0),
externalNodes(4),
h(0.0), d(0.0), A(0.0)
{
theSprings[0] = 0;
theSprings[1] = 0;
theSprings[2] = 0;
theSprings[3] = 0;

theNodes[0] = 0;
theNodes[1] = 0;
theNodes[2] = 0;
theNodes[3] = 0;
}

// destructor - provided to clean up any memory
SimpleJoint2D::~SimpleJoint2D()
{
// clean up the memory associated with the element, this is
// memory the Truss2D objects allocates and memory allocated
// by other objects that the SimpleJoint2D object is responsible for
// cleaning up, i.e. the MaterialObject.

if ( theSprings[0] != 0 ) delete theSprings[0];
if ( theSprings[1] != 0 ) delete theSprings[1];
if ( theSprings[2] != 0 ) delete theSprings[2];
if ( theSprings[3] != 0 ) delete theSprings[3];
}

int
SimpleJoint2D::getNumExternalNodes(void) const
{
return 4;
}

const ID &
SimpleJoint2D::getExternalNodes(void)
{
return externalNodes;
}

Node **
SimpleJoint2D::getNodePtrs(void)
{
return theNodes;


}

int
SimpleJoint2D::getNumDOF(void) {
return 12;
}

// method: setDomain()
// to set a link to the enclosing Domain, ensure nodes exist in Domain
// and set pointers to these nodes, also determines the length and
// transformation Matrix.
void
SimpleJoint2D::setDomain(Domain *theDomain)
{
// check Domain is not null - invoked when object removed from a domain
if (theDomain == 0) {
return;
}

// first ensure nodes exist in Domain and set the node pointers
Node *end1Ptr, *end2Ptr, *end3Ptr, *end4Ptr;
int Nd1 = externalNodes(0);
int Nd2 = externalNodes(1);
int Nd3 = externalNodes(2);
int Nd4 = externalNodes(3);
end1Ptr = theDomain->getNode(Nd1);
end2Ptr = theDomain->getNode(Nd2);
end3Ptr = theDomain->getNode(Nd3);
end4Ptr = theDomain->getNode(Nd4);

if (end1Ptr == 0) {
opserr << "WARNING SimpleJoint2D::setDomain() - at truss " << this->getTag() << " node " <<
Nd1 << " does not exist in domain\n";

return; // don't go any further - otherwise segmentation fault
}
if (end2Ptr == 0) {
opserr << "WARNING SimpleJoint2D::setDomain() - at truss " << this->getTag() << " node " <<
Nd2 << " does not exist in domain\n";

return; // don't go any further - otherwise segmentation fault
}
if (end3Ptr == 0) {
opserr << "WARNING SimpleJoint2D::setDomain() - at truss " << this->getTag() << " node " <<
Nd3 << " does not exist in domain\n";

return; // don't go any further - otherwise segmentation fault
}
if (end4Ptr == 0) {
opserr << "WARNING SimpleJoint2D::setDomain() - at truss " << this->getTag() << " node " <<
Nd4 << " does not exist in domain\n";

return; // don't go any further - otherwise segmentation fault
}
theNodes[0] = end1Ptr;
theNodes[1] = end2Ptr;
theNodes[2] = end3Ptr;
theNodes[3] = end4Ptr;

// call the DomainComponent class method THIS IS VERY IMPORTANT
this->DomainComponent::setDomain(theDomain);

// ensure connected nodes have correct number of dof's
int dofNd1 = end1Ptr->getNumberDOF();
int dofNd2 = end2Ptr->getNumberDOF();
int dofNd3 = end3Ptr->getNumberDOF();
int dofNd4 = end4Ptr->getNumberDOF();

if (dofNd1 != 3 || dofNd2 != 3 || dofNd3 != 3 || dofNd4 != 3) {
opserr << "SimpleJoint2D::setDomain(): 3 dof required at nodes\n";
return;
}
}
//////////////////////////////////////////////////////////////////////
// Public methods called, taken care of for 2D element subclasses
//////////////////////////////////////////////////////////////////////


int SimpleJoint2D::commitState()
{
int CS1 = theSprings[0]->commitState();
int CS2 = theSprings[1]->commitState();
int CS3 = theSprings[2]->commitState();
int CS4 = theSprings[3]->commitState();

if ( CS1!=CS2 || CS2!=CS3 || CS3!=CS4 ) return -1;
return CS1;
}

int SimpleJoint2D::revertToLastCommit()
{
int RLS1 = theSprings[0]->revertToLastCommit();
int RLS2 = theSprings[1]->revertToLastCommit();
int RLS3 = theSprings[2]->revertToLastCommit();
int RLS4 = theSprings[3]->revertToLastCommit();

if ( RLS1!=RLS2 || RLS2!=RLS3 || RLS3!=RLS4 ) return -1;
return RLS1;
}

int SimpleJoint2D::revertToStart(void)
{
int RS1 = theSprings[0]->revertToStart();
int RS2 = theSprings[1]->revertToStart();
int RS3 = theSprings[2]->revertToStart();
int RS4 = theSprings[3]->revertToStart();

if ( RS1!=RS2 || RS2!=RS3 || RS3!=RS4 ) return -1;
return RS1;
}

int SimpleJoint2D::update()
{

return 0;
}

const Matrix &SimpleJoint2D::getTangentStiff(void)
{
const Vector &disp1 = theNodes[0]->getTrialDisp();
const Vector &disp2 = theNodes[1]->getTrialDisp();
const Vector &disp3 = theNodes[2]->getTrialDisp();
const Vector &disp4 = theNodes[3]->getTrialDisp();

double Delta1 = disp1(2);
double Delta2 = disp2(2);
double Delta3 = disp3(2);
double Delta4 = disp4(2);

int dummy;

dummy = theSprings[0]->setTrialStrain(Delta1);
dummy = theSprings[1]->setTrialStrain(Delta2);
dummy = theSprings[2]->setTrialStrain(Delta3);
dummy = theSprings[3]->setTrialStrain(Delta4);

double K1 = theSprings[0]->getTangent();
double K2 = theSprings[1]->getTangent();
double K3 = theSprings[2]->getTangent();
double K4 = theSprings[3]->getTangent();

SimpleJoint2DK.Zero();

SimpleJoint2DK(3,3) = K1;
SimpleJoint2DK(6,6) = K2;
SimpleJoint2DK(9,9) = K3;
SimpleJoint2DK(12,12) = K4;

return SimpleJoint2DK;
}

const Matrix & SimpleJoint2D::getInitialStiff(void)
{
const Vector &disp1 = theNodes[0]->getTrialDisp();
const Vector &disp2 = theNodes[1]->getTrialDisp();
const Vector &disp3 = theNodes[2]->getTrialDisp();
const Vector &disp4 = theNodes[3]->getTrialDisp();

double Delta1 = disp1(2);
double Delta2 = disp2(2);
double Delta3 = disp3(2);
double Delta4 = disp4(2);

int dummy;

dummy = theSprings[0]->setTrialStrain(Delta1);
dummy = theSprings[1]->setTrialStrain(Delta2);
dummy = theSprings[2]->setTrialStrain(Delta3);
dummy = theSprings[3]->setTrialStrain(Delta4);

double K1 = theSprings[0]->getInitialTangent();
double K2 = theSprings[1]->getInitialTangent();
double K3 = theSprings[2]->getInitialTangent();
double K4 = theSprings[3]->getInitialTangent();

SimpleJoint2DK.Zero();

SimpleJoint2DK(3,3) = K1;
SimpleJoint2DK(6,6) = K2;
SimpleJoint2DK(9,9) = K3;
SimpleJoint2DK(12,12) = K4;

return SimpleJoint2DK;
}



const Vector &
SimpleJoint2D::getResistingForce()
{
// want: R = Ku - Pext

// force = F * transformation
double force = theSprings[4]->getStress();
for (int i=0; i<4; i++)
SimpleJoint2DR(i) = force;

return SimpleJoint2DR;
}

int SimpleJoint2D::sendSelf(int commitTag, Channel &theChannel)
{
return -1;
}


int
SimpleJoint2D::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
{
return -1;
}

void
SimpleJoint2D::Print(OPS_Stream &s, int flag)
{
s << "Element: " << this->getTag();
s << " type: SimpleJoint2D iNode: " << externalNodes(0);
s << " jNode: " << externalNodes(1);
s << " lNode: " << externalNodes(2);
s << " kNode: " << externalNodes(3);
s << " \t Material: " << *theSprings[4];
}



Response *
SimpleJoint2D::setResponse(const char **argv, int argc, OPS_Stream &output)
{
Response *theResponse = 0;

output.tag("ElementOutput");
output.attr("eleType",this->getClassType());
output.attr("eleTag",this->getTag());
int numNodes = this->getNumExternalNodes();
const ID &nodes = this->getExternalNodes();
static char nodeData[32];

for (int i=0; i<numNodes; i++) {
sprintf(nodeData,"node%d",i+1);
output.attr(nodeData,nodes(i));
}

if (strcmp(argv[0],"force") == 0 || strcmp(argv[0],"forces") == 0 ||
strcmp(argv[0],"globalForce") == 0 || strcmp(argv[0],"globalForces") == 0) {
const Vector &force = this->getResistingForce();
int size = force.Size();
for (int i=0; i<size; i++) {
sprintf(nodeData,"P%d",i+1);
output.tag("ResponseType",nodeData);
}
theResponse = new ElementResponse(this, 1, this->getResistingForce());
}

else if (strcmp(argv[0],"dampingForce") == 0 || strcmp(argv[0],"dampingForces") == 0) {
const Vector &force = this->getResistingForce();
int size = force.Size();
for (int i=0; i<size; i++) {
sprintf(nodeData,"P%d",i+1);
output.tag("ResponseType",nodeData);
}
theResponse = new ElementResponse(this, 2, this->getResistingForce());
} else if (strcmp(argv[0],"axialForce") ==0)
return new ElementResponse(this, 3, 0.0);

output.endTag();
return theResponse;
}


int
SimpleJoint2D::getResponse(int responseID, Information &eleInfo)
{
double strain;

switch (responseID) {
case -1:
return -1;
case 1: // global forces
return eleInfo.setVector(this->getResistingForce());
case 2:
return eleInfo.setVector(this->getRayleighDampingForces());
case 3:
theSprings[0]->setTrialStrain(strain);
theSprings[1]->setTrialStrain(strain);
theSprings[2]->setTrialStrain(strain);
theSprings[3]->setTrialStrain(strain);
return eleInfo.setDouble( theSprings[0]->getStress());
return eleInfo.setDouble( theSprings[1]->getStress());
return eleInfo.setDouble( theSprings[2]->getStress());
return eleInfo.setDouble( theSprings[3]->getStress());
default:
return 0;
}
}

double
SimpleJoint2D::computeCurrentStrain(void) const
{

// determine the strain
const Vector &disp1 = theNodes[0]->getTrialDisp();
const Vector &disp2 = theNodes[1]->getTrialDisp();
const Vector &disp3 = theNodes[2]->getTrialDisp();
const Vector &disp4 = theNodes[3]->getTrialDisp();

double dLength = 0.0;
for (int i=0; i<4; i++){
dLength -= (disp2(i)-disp1(i)) ;
}

double strain = dLength;

return strain;
}
fmk
Site Admin
Posts: 5884
Joined: Fri Jun 11, 2004 2:33 pm
Location: UC Berkeley
Contact:

Re: OPS procedure

Post by fmk »

you never get the idData before you start using it, i.e. before eleTag = idData[0] you need to go read the data from the command line into idData.
Post Reply