Guidelines for developing user defined subroutines.

Frequently asked questions

Guidelines for developing user defined subroutines.

Postby ES3 » Fri Oct 23, 2015 8:41 pm

1. Introduction

User defined features are implemented through C++ classes. Usually there are two types of user defined features: list and object. A list can refer to a list of finite elements, e.g. 4-node Tetrahedral element list with constant strain; an object can refer to a material model, e.g. elasticity model.

In this article, we will show how to implement the 4-node Tetrahedral element list and elastic material.

The user subroutines are usually put into a so-called driver file - user.cpp, which looks like:
Code: Select all
#include "mars.h" // includes the declarations of all MARS core functionalities
#include "myMaterial.cpp"
#include "myElement.cpp"

// --------------------------------------------------------------------
// createUserDefinedList(...) and readRstUserDefineList(...) must always be defined

obLst *Model::createUserDefinedList (string nam, Reader *rdr) {
    string lbl = rdr->getShortLabel();
    if (lbl == "myElement")
        return new ttL_myElement(nam);
    return NULL;
}
obLst *Model::readRstUserDefinedList (RstReader *rst, string nam) {
    return NULL;
}

// --------------------------------------------------------------------
// createUserDefinedObject(...) and readRstUserDefinedObject(...) must always be defined

Obj *Model::createUserDefinedObject (string nam, Reader *rdr) {
    string lbl = rdr->getShortLabel();
    if (lbl == "myMaterial")
        return new myMaterial(nam);
    return NULL;
}
Obj *Model::readRstUserDefinedObject (RstReader *rst, string nam) {
    return NULL;
}


2. Input file

The corresponding inputs are
Code: Select all
UserDefinedObject CONC myMaterial {
   Density 2500 kg/m3
   YoungModulus 3e4 MPa
   PoissonsRatio 0.2
}
//----------------------------
UserDefinedList PRTC myElement {
  Material CONC
  InsertNodeList {
    lengthUnits cm
    InputFormat IBXYZB
    ReadNodes 4
      1  OOO   0 0 1  OOO
      2  OOO   0 0 0  OOO
      3  OOO   0 1 0  OOO
      4  OOO   1 0 0  OOO
    Select cz < 0.1 cm
    Make NodeList base
    Set Translations XXX
    Select all
    Select cz > 0.9 cm
    Make NodeList tip
    Set Translations XOX
    Select all
  }
  ReadObjects 1
  1 1 2 3 4
  Plotting enabled
}

For the user defined material tagged myMaterial, three parameters are defined; for the user defined list tagged myElement, one element is created.

3. User defined object class
Code: Select all
class myMaterial : public Material {
private:
    real lmb, twg, ps1, ps2, blk;
    real ymdDt, lmbDt, twgDt, ps1Dt, ps2Dt;
public:
    myMaterial(string nm) : Material(nm) { init0(); }
    void int0();
    ~myMaterial() { }
    void init();
    virtual processCommand(Reader *, string);
    void execAtEveryStep();
    void calcStrsHx(real *, real *) const;
    void writeRstName(RstWriter *);
    void writeRst(RstWriter *);
    void readRst(RstReader *);
};

Important notice
  • use init0() in the class constructor to set default values to member variables
  • MARS AUTOMATICALLY calls Object::readObjInput(), which REPEATLY calls processCommand() to process input file
  • MARS AUTOMATICALLY calls myMaterial::init() after the input is read
  • use myMaterial::init() to initialize the object with the parameters read from input
  • put the validity checks in myMaterial::init()

4. User defined list class
The user defined list for an element formulation usually includes two classes: class for the list itself, which is the container of the elements; and class of the element.
Code: Select all
class myElement : public DeformableTet {
public:
    myElement() { }
    ~myElement() { }
    void init(ReferenceSystem *rs) { DeformableTet::init(rs); }
    void whatAmI() { cout << "myElement" << endl; };
    void reset();
    real calcForces(Node **, real *);
    void setUpStiffnessMatrix(real **);
};

Code: Select all
class ttL_myElement : public ttLst {
private:
public:
    ttL_myElement() { initList(); }
    ttL_myElement(string nm) : ttLst(nm) { initList(); }
    void initList() { }
    ~ttL_myElement() { }
    Object *createNewObject() { return new myElement(); }
    void setMaterial(Material *m) { mat = m; };
    void setNodeList(ndLst *nL) { ndL = nL; };
    void setStaticVariables();
    bool processCommand(Reader *, string);
    void initialize();
    real calcFrc();
    void writeRst(RstWriter *) { }
    void readRst(RstReader *) { }
};

Important notice for the list class (ttL_myElement)
  • class ttL_myElement is the list container of the elements, which are the objects
  • use initLst() in the constructor to set default values to member variables, if any
  • MARS AUTOMATICALLY calls obLst::readListInput(), which REPEATLY calls processCommand() to process input file
  • MARS AUTOMATICALLY calls ttL_myElement::initialize() after the input is read,
  • in ttL_myElement::initialize(), call myElement::init() to initialize the objects as well
  • put the validity checks in ttL_myElement::initialize()

Appendix A. update read()/readLst() to processCommand()

Since MARS version 2015.1.05, the old way to process input is replaced by the processCommand() to reduce code duplication.

Import Notice

  • MARS NO LONGER AUTOMATICALLY call read() for object type classes or readLst() for list type classes, instead processCommand() is called
  • If procesCommand() is not needed, change read() to readObjInput() and readLst() to readListInput(), respectively. This will override Object::read() and obLst::readListInput().

Code similar to
Code: Select all
void myMaterial::read (Reader *rdr) {
    while (true) {
        rdr->readLine();
        string lbl = rdr->getShortLabel();
        string lb3 = lbl.substr(0,3);
        if (lbl.at(0) == '/' || lbl.at(0) == '}')
            break;
        else if (lb3 == "Den" || lb3 == "dns")
            dns = rdr->readDensity();
        else if (lb3 == "You")
            ymd = rdr->readStress();
        else if (lb3 == "Poi")
            psn = rdr->getFloat();
        else
            rdr->error("Invalid entry in myMaterial");
    }
    Material::check(rdr); // move to ::init()
    init(); // remove, called automatically by MARS once reading is done
}

should be replaced by
Code: Select all
bool myMaterial::processCommand (Reader *rdr, string lbl) {
    if (lbl == "Density")
        dns = rdr->readDensity();
    else if (lbl == "YoungModulus")
        ymd = rdr->readStress();
    else if (lbl == "PoissonsRatio")
        psn = rdr->getFloat();
    else if (Material::processCommand(rdr, lbl) { // code reuse, use parent class to process common inputs
    } else
        return false
    return true;
}


Appendix B. source code and input file
Attachments
files.zip
(4.66 KiB) Downloaded 816 times
ES3
 
Posts: 42
Joined: Thu Jul 09, 2015 9:36 pm

Return to FAQs

Who is online

Users browsing this forum: No registered users and 2 guests

cron