Don’t Forget to Take a Selfie

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 UniaxialMaterials, 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.


Here’s a video discussion of sendSelf and recvSelf.

One thought on “Don’t Forget to Take a Selfie

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.