OpenSees Cloud
OpenSees AMI
Don't Forget to Take a Selfie
Original Post - 09 Nov 2020 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
If you’ve programmed your own UniaxialMaterial in OpenSees, you were likely hyper-focused on correct implementation of the constructor and the methods for state determination, getStress() and commitState(). Rightfully so.
But there are a couple UniaxialMaterial methods, and a code addition
elsewhere, that are critically important when using the database
command
to save/restore your model or when using parallel computing
applications, e.g., OpenSeesSP.
The UniaxialMaterial methods, sendSelf and recvSelf (recv is short for
receive), allow an ObjectBroker to move objects between processors or to
send and receive objects to and from a database. These methods are pure
virtual, inherited from the MovableObject interface. If you are living
in single processor land and not using the database
command, you can
provide dummy implementations to get past the pure virtual goalie.
int
Concrete23::sendSelf(int commitTag, Channel &theChannel)
{
return -1;
}
int
Concrete23::recvSelf(int commitTag, Channel &theChannel,
FEM_ObjectBroker &theBroker)
{
return -1;
}
That is, until someone else wants to use your model for parallel applications or with a database. They will receive an error that looks something like this:
FEM_ObjectBrokerAllClasses::getNewUniaxialMaterial - - no UniaxialMaterial type exists for class tag
623
WARNING Truss::recvSelf() - 10000102 failed to get a blank Material of type
623
10000102 failed to send its Material
WARNING Truss::sendSelf() - 10000112 failed to send its Material
There’s a couple things going on here. First, the
FEM_ObjectBrokerAllClasses object wants to create a blank material
object on the remote host, but is not able to do so. This is a very easy
fix–go into the SRC/actor/objectBroker/FEM_ObjectBrokerAllClasses.cpp
file and add your material to the gigantic switch statement in the
getNewUniaxialMaterial() method.
...
...
case MAT_TAG_Concrete22:
return new Concrete22();
case MAT_TAG_Concrete23: // New addition!
return new Concrete23();
case MAT_TAG_Steel01:
return new Steel01();
...
...
The case labels in the switch statement are the class tags defined in
SRC/classTags.h
.
Second, the truss element fails to receive its material because sendSelf and recvSelf both return -1. To fix this problem, you will need to give these methods real implementations. For UniaxialMaterial, all you have to do in sendSelf is pack the material tag, the material properties, and the material’s committed history variables into a Vector–basically, everything you need to reproduce the model state on the remote host. Then send the Vector through a Channel object.
Note that sendSelf and recvSelf are only called after a commit, so there should be no need to send and receive any trial history variables.
int
Concrete23::sendSelf(int commitTag, Channel &theChannel)
{
static Vector data(14); // Length = 1 + num parameters + num history variables
data(0) = this->getTag();
data(1) = fc;
//
// Put remaining parameters in data
data(7) = minStrain;
//
// Put remaining history variables in data
int res = theChannel.sendVector(this->getDbTag(), commitTag, data);
if (res < 0)
opserr << "Concrete23::sendSelf() - failed to send data\n";
return res;
}
For recvSelf, you will receive the Vector from the Channel, then unpack the Vector and write the private data, i.e., populate the blank material object created by the object broker with the material properties and committed history variables.
int
Concrete23::recvSelf(int commitTag, Channel &theChannel,
FEM_ObjectBroker &theBroker)
{
static Vector data(14); // Same length as in sendSelf
int res = theChannel.recvVector(this->getDbTag(), commitTag, data);
if (res < 0) {
opserr << "Concrete23::recvSelf() - failed to receive data\n";
this->setTag(0);
return res;
}
// Material tag (cast as integer)
this->setTag(int(data(0)));
fc = data(1);
//
// Read remaining parameters from data
minStrain = data(7);
//
// Read remaining history variables from data
//
// Do whatever else you need to do to restore the model state
//
return res;
}
Now everyone can use your Concrete23 model with databases and parallel applications! Implementations of sendSelf and recvSelf get a little more complicated for elements, but the ideas are the same.