Add A New Recorder
A Recorder in the interpreted OpenSees applications is used to obtain information from the model during the analysis. To add a new Recorder option into the interpreted applications, the developer must provide a new C++ subclass of the Recorder class.
Recorder Class
The Recorder class itself is an abstract base class. It inherits from both the tagged object class and the MovableObject class. The class has a minimal interface, which is as shown below:
The Recorder Class:
class Recorder: public MovableObject, public TaggedObject
{
public:
Recorder(int classTag);
virtual ~Recorder();
virtual int record(int commitTag, double timeStamp) =0;
virtual int restart(void);
virtual int domainChanged(void);
virtual int setDomain(Domain &theDomain);
virtual int sendSelf(int commitTag, Channel &theChannel);
virtual int recvSelf(int commitTag, Channel &theChannel,
FEM_ObjectBroker &theBroker);
virtual void Print(OPS_Stream &s, int flag);
protected:
protected:
private:
static int lastRecorderTag;
};
The most important methods in the interface are:
- setDomain() - this is the method that is called when the new recorder object is first added to the domain. It is inside this method that all data, typically memory and pointer values, need to be initialized for subsequent record commands.
- record() - this is the method that is called when the recorder is called upon to record/save information. The method is called with a tag that will be unique and the current time in the domain.
Other Important methods are:
- domainChanged() - this is a method called when something major has happened in the Domain, ie. a new element, node, constraint and/or load pattern has been added to the domain or removed from the domain. It is necessasry for the Recorder to check in this call if it's pointers are still valid (i.e. if an element it was recording info for has been removed from the domain, it wuill have been deleted and it's old pointer information will no longer be valid.)
- send/recvSelf() - are two methods called in parallel applications. When invoked the recorders send/recv information about what they are recording.
- restart() - this method is called if restart() is invoked on the Domain. What the recorder does is up to you the developer.
Example
In the following section we will provide all necessary code to add a new recorder. The purpose of this recorder will be to sum the forces obtained from the list of inputted elements. The recorder will use the getResistingForce() method in the elements to obtain the forces. A similar class exists in the framework, which uses the setResponse()/getResponse() methods in the element interface. To demonstrate some of the output file options, the result will go to either the screen, a text file, or a binary file. More output options are of course available and the developer should look at existing recorder options.
Header
The header for thew new class, which we will call ExampleElementForceSum is as follows:
#include <Recorder.h>
#include <ID.h>
class Domain;
class Vector;
class Matrix;
class Element;
class Response;
class FE_Datastore;
class MyElementSumRecorder: public Recorder
{
public:
MyElementSumRecorder();
MyElementSumRecorder(const ID eleID,
char **argv,
int argc,
bool echoTime,
OPS_Stream *theOutputHandler);
~MyElementSumRecorder();
int record(int commitTag, double timeStamp);
int restart(void);
int setDomain(Domain &theDomain);
int sendSelf(int commitTag, Channel &theChannel);
int recvSelf(int commitTag, Channel &theChannel,
FEM_ObjectBroker &theBroker);
protected:
private:
int numEle; // the number of elements
ID *eleID; // ID (integer list) of element tags to record
Element **theEle; // pointer to array of element pointers
Domain *theDomain; // pointer to domain holding elements
OPS_Stream *theOutput;// pointer to output location
bool echoTimeFlag; // flag indicating if pseudo time to be printed
Vector *data; // Vector (double array) to store sum of element forces
};