Forked from
gmsh / gmsh
14487 commits behind the upstream repository.
-
Samuel Melchior authoredSamuel Melchior authored
dgDofContainer.cpp 21.75 KiB
#include "GmshConfig.h"
#include "dgDofContainer.h"
#include "function.h"
#include "dgGroupOfElements.h"
#include "dgConservationLaw.h"
#include "dgAlgorithm.h"
#include "GModel.h"
#ifdef HAVE_MPI
#include "mpi.h"
#else
#include "string.h"
#endif
#include <sstream>
#include "MElement.h"
dgDofContainer::dgDofContainer (dgGroupCollection *groups, int nbFields):
_groups(*groups), _mshStep(0)
{
int _dataSize = 0;
_dataSizeGhost=0;
_totalNbElements = 0;
_parallelStructureExists = false;
_nbFields = nbFields;
for (int i=0; i< _groups.getNbElementGroups();i++){
int nbNodes = _groups.getElementGroup(i)->getNbNodes();
int nbElements = _groups.getElementGroup(i)->getNbElements();
_totalNbElements +=nbElements;
_dataSize += nbNodes*_nbFields*nbElements;
}
// allocate the big vectors
_data = new fullVector<double>(_dataSize);
// create proxys for each group
int offset = 0;
_dataProxys.resize(_groups.getNbElementGroups()+_groups.getNbGhostGroups());
for (int i=0;i<_groups.getNbElementGroups();i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
_groupId[group] = i;
int nbNodes = group->getNbNodes();
int nbElements = group->getNbElements();
_dataProxys[i] = new fullMatrix<double> (&(*_data)(offset),nbNodes, _nbFields*nbElements);
offset += nbNodes*_nbFields*nbElements;
}
//ghosts
int totalNbElementsGhost =0;
for (int i=0; i<_groups.getNbGhostGroups(); i++){
int nbNodes = _groups.getGhostGroup(i)->getNbNodes();
int nbElements = _groups.getGhostGroup(i)->getNbElements();
totalNbElementsGhost +=nbElements;
_dataSizeGhost += nbNodes*_nbFields*nbElements;
}
_dataProxys.resize(_groups.getNbElementGroups()+_groups.getNbGhostGroups());
_ghostData = new fullVector<double>(_dataSizeGhost);
offset=0;
for (int i=0;i<_groups.getNbGhostGroups();i++){
dgGroupOfElements *group = _groups.getGhostGroup(i);
int nbNodes = group->getNbNodes();
int nbElements = group->getNbElements();
_groupId[group] = i+_groups.getNbElementGroups();
_dataProxys[i+_groups.getNbElementGroups()] = new fullMatrix<double> (&(*_ghostData)(offset),nbNodes, _nbFields*nbElements);
offset += nbNodes*_nbFields*nbElements;
}
}
dgDofContainer::~dgDofContainer (){
if(_parallelStructureExists) {
delete []countSend;
delete []countRecv;
delete []shiftSend;
delete []shiftRecv;
delete []groupShiftRecv;
delete []sendBuf;
delete []recvBuf;
}
for (int i=0;i<_dataProxys.size();++i) delete _dataProxys[i];
delete _data;
delete _ghostData;
}
void dgDofContainer::buildParallelStructure(){
if (_parallelStructureExists)
return;
// MPI all2all buffers
countSend = new int[Msg::GetCommSize()];
shiftSend = new int[Msg::GetCommSize()];
countRecv = new int[Msg::GetCommSize()];
shiftRecv = new int[Msg::GetCommSize()];
groupShiftRecv = new int[_groups.getNbGhostGroups()];
for(int i=0;i<Msg::GetCommSize();i++){
countSend[i]=0;
countRecv[i]=0;
for(size_t j=0;j<_groups.getNbImageElementsOnPartition(i);j++){
countSend[i] += _groups.getElementGroup(_groups.getImageElementGroup(i,j))->getNbNodes()*_nbFields;
}
}
for(size_t i=0; i<_groups.getNbGhostGroups(); i++){
dgGroupOfElements *group = _groups.getGhostGroup(i);
groupShiftRecv[i] = countRecv[group->getGhostPartition()];
countRecv[group->getGhostPartition()]+=group->getNbElements()*group->getNbNodes()*_nbFields;
}
shiftSend[0] = shiftRecv[0]=0;
int totalSend = countSend[0];
int totalRecv = countRecv[0];
for(size_t i=1; i<Msg::GetCommSize(); i++){
shiftSend[i] = shiftSend[i-1]+countSend[i-1];
shiftRecv[i] = shiftRecv[i-1]+countRecv[i-1];
totalSend += countSend[i];
totalRecv += countRecv[i];
}
for(size_t i=0; i<_groups.getNbGhostGroups(); i++){
dgGroupOfElements *group = _groups.getGhostGroup(i);
groupShiftRecv[i] += shiftRecv[group->getGhostPartition()];
}
sendBuf = new double[totalSend];
recvBuf = new double[totalRecv];
_parallelStructureExists = true;
}
void dgDofContainer::scatter() {
if(!_parallelStructureExists)
buildParallelStructure();
//1) fill
int index=0;
for(int i=0;i<Msg::GetCommSize();i++){
for(size_t j=0;j<_groups.getNbImageElementsOnPartition(i);j++){
fullMatrix<double> &sol = getGroupProxy(_groups.getImageElementGroup(i,j));
int eid = _groups.getImageElementPositionInGroup(i,j);
for(int l=0;l<_nbFields;l++) {
for(int k=0;k<sol.size1();k++) {
sendBuf[index++] = sol(k, eid *_nbFields+l);
}
}
}
}
//2) send
#ifdef HAVE_MPI
MPI_Alltoallv(sendBuf,countSend,shiftSend,MPI_DOUBLE,recvBuf,countRecv,shiftRecv,MPI_DOUBLE,MPI_COMM_WORLD);
#else
memcpy(recvBuf,sendBuf,countSend[0]*sizeof(double));
#endif
//3) distribute
for(int i=0; i< _groups.getNbGhostGroups();i++) {
fullMatrix<double> &sol = getGroupProxy(i+_groups.getNbElementGroups());
fullMatrix<double> recvProxy (recvBuf + groupShiftRecv[i], sol.size1(), sol.size2());
sol.setAll(recvProxy);
}
}
void dgDofContainer::setAll(double v) {
for(int i=0;i<_data->size();i++)
(*_data)(i)=v;
for(int i=0;i<_ghostData->size();i++)
(*_ghostData)(i)=v;
}
void dgDofContainer::scale(double f)
{
_data->scale(f);
_ghostData->scale(f);
}
void dgDofContainer::scale(std::vector<dgGroupOfElements*>groupsVector, double f){
for(int i=0;i<groupsVector.size();i++){
dgGroupOfElements *g=groupsVector[i];
fullMatrix<double> &proxy=getGroupProxy(g);
proxy.scale(f);
}
}
void dgDofContainer::axpy(dgDofContainer &x, double a)
{
_data->axpy(*x._data,a);
_ghostData->axpy(*x._ghostData,a);
}
void dgDofContainer::axpy(std::vector<dgGroupOfElements*>groupsVector,dgDofContainer &x, double a){
for(int i=0;i<groupsVector.size();i++){
dgGroupOfElements *g=groupsVector[i];
fullMatrix<double> &proxy=getGroupProxy(g);
fullMatrix<double> &xProxy=x.getGroupProxy(g);
proxy.add(xProxy,a);
}
}
double dgDofContainer::norm() {
double localNorm = _data->norm();
#ifdef HAVE_MPI
double globalNorm;
MPI_Allreduce(&localNorm, &globalNorm, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
return globalNorm;
#else
return localNorm;
#endif
}
double dgDofContainer::norm(std::vector<dgGroupOfElements *>gV){
double norm=0;
for(int i=0;i<gV.size();i++){
dgGroupOfElements* g=gV[i];
fullMatrix<double>&groupData=getGroupProxy(g);
for(int r=0;r<groupData.size1();r++){
for(int c=0;c<groupData.size1();c++){
norm+=groupData(r,c)*groupData(r,c);
}
}
}
return norm;
}
void dgDofContainer::save(const std::string name) {
FILE *f = fopen (name.c_str(),"wb");
_data->binarySave(f);
fclose(f);
}
void dgDofContainer::load(const std::string name) {
FILE *f = fopen (name.c_str(),"rb");
_data->binaryLoad(f);
fclose(f);
}
void dgDofContainer::L2Projection(std::string functionName){
scale(0.);
dgDofContainer rhs(&_groups, _nbFields);
for (int iGroup=0;iGroup<_groups.getNbElementGroups();iGroup++) {
const dgGroupOfElements &group = *_groups.getElementGroup(iGroup);
fullMatrix<double> Source = fullMatrix<double> (group.getNbIntegrationPoints(),group.getNbElements() * _nbFields);
dataCacheMap cacheMap;
cacheMap.setNbEvaluationPoints(group.getNbIntegrationPoints());
dataCacheElement &cacheElement = cacheMap.getElement();
cacheMap.provideData("UVW",1,3).set(group.getIntegrationPointsMatrix());
dataCacheDouble &sourceTerm = cacheMap.get(functionName);
fullMatrix<double> source;
for (int iElement=0 ; iElement<group.getNbElements() ;++iElement) {
cacheElement.set(group.getElement(iElement));
source.setAsProxy(Source, iElement*_nbFields, _nbFields);
for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
const double detJ = group.getDetJ (iElement, iPt);
for (int k=0;k<_nbFields;k++)
source(iPt,k) = sourceTerm(iPt,k)*detJ;
}
}
rhs.getGroupProxy(iGroup).gemm(group.getSourceRedistributionMatrix(), Source);
dgAlgorithm::multAddInverseMassMatrix(group, rhs.getGroupProxy(iGroup), getGroupProxy(iGroup));
}
}
void dgDofContainer::Mesh2Mesh_BuildL2Projection(linearSystemCSRGmm<double> &projector,dgDofContainer &donor){
// for basis function i
// for integration pts
// search for element in 2d mesh
// for basis function j
// evauate quad
// add to matrix correct indices
dgGroupCollection* dGroups = donor.getGroups();
dgGroupCollection* rGroups = this->getGroups();
std::vector<int> rGroupsStartIGlobal(rGroups->getNbElementGroups() + 1);
int jGlobal = 0; // indices in global container
rGroupsStartIGlobal[0] = 0;
for (int i = 1; i<rGroupsStartIGlobal.size(); i++)
rGroupsStartIGlobal[i] = rGroupsStartIGlobal[i-1] + rGroups->getElementGroup(i-1)->getNbElements()*rGroups->getElementGroup(i-1)->getNbNodes();
projector.allocate(rGroupsStartIGlobal[rGroupsStartIGlobal.size()-1]);
for (int iGroup=0;iGroup<dGroups->getNbElementGroups();iGroup++) {// for 3d.groups
const dgGroupOfElements &dGroup = *dGroups->getElementGroup(iGroup);
fullMatrix<double> iPtsMatrix = dGroup.getIntegrationPointsMatrix();
for (int iElement=0 ; iElement<dGroup.getNbElements() ;++iElement) {// for elements
double rShapeFun[256];
double dShapeFun[256];
GModel *rModel = rGroups->getModel();
GModel *dModel = dGroups->getModel();
// dataCacheDouble xyz = cacheMap.get("XYZ");
MElement* dElem = dGroup.getElement(iElement);
for (int iPt =0; iPt< dGroup.getNbIntegrationPoints(); iPt++) {
double x=0,y=0,z=0;
dElem->getFunctionSpace()->f(iPtsMatrix(iPt,0),iPtsMatrix(iPt,1),iPtsMatrix(iPt,2),dShapeFun);
for (int iVer=0; iVer < dElem->getNumVertices(); iVer++) {
x += dElem->getVertex(iVer)->x()*dShapeFun[iVer];
y += dElem->getVertex(iVer)->y()*dShapeFun[iVer];
z += dElem->getVertex(iVer)->z()*dShapeFun[iVer];
}
z = 0;
SPoint3 p(x,y,z); // find p in 2D mesh
MElement *rElem = rGroups->getModel()->getMeshElementByCoord(p);
int iGroupR,iElementR;
rGroups->find(rElem,iGroupR,iElementR);
if (iElementR == -1)
Msg::Error("Integration point not found in receiver mesh.");
const dgGroupOfElements &rGroup = *rGroups->getElementGroup(iGroupR);
double U[3],X[3]={x,y,z};
rElem->xyz2uvw(X,U);
dGroup.getFunctionSpace().f(iPtsMatrix(iPt,0),iPtsMatrix(iPt,1),iPtsMatrix(iPt,2),dShapeFun);
rGroup.getFunctionSpace().f(U[0],U[1],U[2],rShapeFun);
const double detJ = dGroup.getDetJ (iElement, iPt);
int iGlobal = rGroupsStartIGlobal[iGroupR]+rGroup.getNbNodes()*iElementR;
for (int jPsi=0;jPsi<dGroup.getNbNodes();jPsi++){
for (int iPsi=0;iPsi<rGroup.getNbNodes();iPsi++){
// get global index of shape functions
// sum of nElems in previous groups
// iElem + i|j
double val = rShapeFun[iPsi]*dShapeFun[jPsi];//*iPtsMatrix(iPt,3);//*detJ;
projector.addToMatrix(iGlobal+iPsi,jGlobal+jPsi,val);
}
}
}
jGlobal += dGroup.getNbNodes();
}
}
}
void dgDofContainer::Mesh2Mesh_ApplyL2Projection(linearSystemCSRGmm<double> &projector,dgDofContainer &donor){
scale(0.);
dgGroupCollection* dGroups = donor.getGroups();
dgGroupCollection* rGroups = this->getGroups();
std::vector<int> dGroupsStartIGlobal(dGroups->getNbElementGroups() + 1);
int iGlobal = 0; // indices in global container
dGroupsStartIGlobal[0] = 0;
for (int i = 1; i<dGroupsStartIGlobal.size(); i++)
dGroupsStartIGlobal[i] = dGroupsStartIGlobal[i-1] + dGroups->getElementGroup(i-1)->getNbElements()*dGroups->getElementGroup(i-1)->getNbNodes();
int *startIndex;
int *columns;
double *values;
projector.getMatrix(startIndex,columns,values);
int nbFields = 0; // TO DEFINE !!!
for (int iGroup=0;iGroup<rGroups->getNbElementGroups();iGroup++) {// for 2d.groups
const dgGroupOfElements &rGroup = *rGroups->getElementGroup(iGroup);
this->getGroupProxy(iGroup).scale(0);
for (int iElement=0 ; iElement<rGroup.getNbElements() ;++iElement) {// for elements
for (int iNode = 0 ; iNode<rGroup.getNbNodes() ;++iNode) {
int jGroup = 0;
for (int i = startIndex[iGlobal++]; i < startIndex[iGlobal] - 1; i++){
int jGlobal = columns[i];
for (;jGlobal < dGroupsStartIGlobal[jGroup+1];jGroup++) {
}
int jElement = (jGlobal-dGroupsStartIGlobal[jGroup])/dGroups->getElementGroup(jGroup)->getNbNodes();
int jNode = jGlobal-dGroupsStartIGlobal[jGroup]-jElement*dGroups->getElementGroup(jGroup)->getNbNodes();
for (int m = 0; m < nbFields; m++){
(this->getGroupProxy(iGroup))(iNode,iElement*nbFields+m) += values[i]*(donor.getGroupProxy(jGroup))(jNode,jElement*nbFields+m);
}
}
}
}//*/
}
}
void dgDofContainer::exportGroupIdMsh(){
// the elementnodedata::export does not work !!
std::ostringstream name_oss;
name_oss<<"groupsId.msh";
if(Msg::GetCommSize()>1)
name_oss<<"_"<<Msg::GetCommRank();
FILE *f = fopen (name_oss.str().c_str(),"w");
int COUNT = 0;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
COUNT += _groups.getElementGroup(i)->getNbElements();
}
fprintf(f,"$MeshFormat\n2.1 0 8\n$EndMeshFormat\n");
fprintf(f,"$ElementNodeData\n");
fprintf(f,"1\n");
fprintf(f,"\"%s\"\n","GroupsIds");
fprintf(f,"1\n");
fprintf(f,"0.0\n");
fprintf(f,"%d\n", Msg::GetCommSize() > 1 ? 4 : 3);
fprintf(f,"0\n 1\n %d\n",COUNT);
if(Msg::GetCommSize() > 1) fprintf(f,"%d\n", Msg::GetCommRank());
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
fprintf(f,"%d %d",num,sol.size1());
for (int k=0;k<sol.size1();++k) {
fprintf(f," %.16E ",i*1.0);
}
fprintf(f,"\n");
}
}
fprintf(f,"$EndElementNodeData\n");
fclose(f);
return;
// we should discuss that : we do a copy of the solution, this should
// be avoided !
/*std::map<int, std::vector<double> > data;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
std::vector<double> val;
// val.resize(sol.size2()*sol.size1());
val.resize(sol.size1());
int counter = 0;
// for (int iC=0;iC<sol.size2();iC++)
printf("%g %g %g\n",sol(0,0),sol(1,0),sol(2,0));
for (int iR=0;iR<sol.size1();iR++)val[counter++] = sol(iR,0);
data[num] = val;
}
}
PView *pv = new PView (name, "ElementNodeData", _gm, data, 0.0, 1);
pv->getData()->writeMSH(name+".msh", false);
delete pv;
*/
}
void dgDofContainer::exportMultirateGroupMsh(){
// the elementnodedata::export does not work !!
std::ostringstream name_oss;
name_oss<<"groupsMultirateType.msh";
if(Msg::GetCommSize()>1)
name_oss<<"_"<<Msg::GetCommRank();
FILE *f = fopen (name_oss.str().c_str(),"w");
int COUNT = 0;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
COUNT += _groups.getElementGroup(i)->getNbElements();
}
fprintf(f,"$MeshFormat\n2.1 0 8\n$EndMeshFormat\n");
fprintf(f,"$ElementNodeData\n");
fprintf(f,"1\n");
fprintf(f,"\"%s\"\n","GroupsIds");
fprintf(f,"1\n");
fprintf(f,"0.0\n");
fprintf(f,"%d\n", Msg::GetCommSize() > 1 ? 4 : 3);
fprintf(f,"0\n 1\n %d\n",COUNT);
if(Msg::GetCommSize() > 1) fprintf(f,"%d\n", Msg::GetCommRank());
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
int groupType=0;//-3*group->getMultirateExponent();
if(group->getIsInnerMultirateBuffer())
groupType+=1;
if(group->getIsOuterMultirateBuffer())
groupType+=2;
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
fprintf(f,"%d %d",num,sol.size1());
for (int k=0;k<sol.size1();++k) {
fprintf(f," %.16E ",groupType*1.0);
}
fprintf(f,"\n");
}
}
fprintf(f,"$EndElementNodeData\n");
fclose(f);
return;
// we should discuss that : we do a copy of the solution, this should
// be avoided !
/*std::map<int, std::vector<double> > data;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
std::vector<double> val;
// val.resize(sol.size2()*sol.size1());
val.resize(sol.size1());
int counter = 0;
// for (int iC=0;iC<sol.size2();iC++)
printf("%g %g %g\n",sol(0,0),sol(1,0),sol(2,0));
for (int iR=0;iR<sol.size1();iR++)val[counter++] = sol(iR,0);
data[num] = val;
}
}
PView *pv = new PView (name, "ElementNodeData", _gm, data, 0.0, 1);
pv->getData()->writeMSH(name+".msh", false);
delete pv;
*/
}
void dgDofContainer::exportMsh(const std::string name)
{
// the elementnodedata::export does not work !!
for (int ICOMP = 0; ICOMP<_nbFields;++ICOMP){
std::ostringstream name_oss, name_view;
name_view<<"comp_"<<ICOMP;
name_oss<<name<<"_COMP_"<<ICOMP<<".msh";
if(Msg::GetCommSize()>1)
name_oss<<"_"<<Msg::GetCommRank();
FILE *f = fopen (name_oss.str().c_str(),"w");
if(!f){
Msg::Error("Unable to open export file '%s'", name.c_str());
}
int COUNT = 0;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
COUNT += _groups.getElementGroup(i)->getNbElements();
}
fprintf(f,"$MeshFormat\n2.1 0 8\n$EndMeshFormat\n");
fprintf(f,"$ElementNodeData\n");
fprintf(f,"1\n");
fprintf(f,"\"%s\"\n",name_view.str().c_str());
fprintf(f,"1\n");
fprintf(f,"%d\n", _mshStep); // should print actual time here
fprintf(f,"%d\n", Msg::GetCommSize() > 1 ? 4 : 3);
fprintf(f,"%d\n 1\n %d\n", _mshStep, COUNT);
if(Msg::GetCommSize() > 1) fprintf(f,"%d\n", Msg::GetCommRank());
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
fprintf(f,"%d %d",num,sol.size1());
for (int k=0;k<sol.size1();++k) {
fprintf(f," %.16E ",sol(k,ICOMP));
}
fprintf(f,"\n");
}
}
fprintf(f,"$EndElementNodeData\n");
fclose(f);
}
_mshStep++;
// we should discuss that : we do a copy of the solution, this should
// be avoided !
/*std::map<int, std::vector<double> > data;
for (int i=0;i < _groups.getNbElementGroups() ;i++){
dgGroupOfElements *group = _groups.getElementGroup(i);
for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) {
MElement *e = group->getElement(iElement);
int num = e->getNum();
fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields);
std::vector<double> val;
// val.resize(sol.size2()*sol.size1());
val.resize(sol.size1());
int counter = 0;
// for (int iC=0;iC<sol.size2();iC++)
printf("%g %g %g\n",sol(0,0),sol(1,0),sol(2,0));
for (int iR=0;iR<sol.size1();iR++)val[counter++] = sol(iR,0);
data[num] = val;
}
}
PView *pv = new PView (name, "ElementNodeData", _gm, data, 0.0, 1);
pv->getData()->writeMSH(name+".msh", false);
delete pv;
*/
}
#include "LuaBindings.h"
void dgDofContainer::registerBindings(binding *b){
classBinding *cb = b->addClass<dgDofContainer>("dgDofContainer");
cb->setDescription("The DofContainer class provides a vector containing the degree of freedoms");
methodBinding *cm;
cm = cb->setConstructor<dgDofContainer,dgGroupCollection*,int>();
cm->setDescription("Build a vector");
cm->setArgNames("GroupCollection","nbFields",NULL);
cm = cb->addMethod("L2Projection",&dgDofContainer::L2Projection);
cm->setDescription("Project a function onto this vector");
cm->setArgNames("functionName",NULL);
cm = cb->addMethod("exportMsh",&dgDofContainer::exportMsh);
cm->setDescription("Export the dof for gmsh visualization");
cm->setArgNames("filename", NULL);
cm = cb->addMethod("exportGroupIdMsh",&dgDofContainer::exportGroupIdMsh);
cm->setDescription("Export the group ids for gmsh visualization");
cm = cb->addMethod("exportMultirateGroupMsh",&dgDofContainer::exportMultirateGroupMsh);
cm->setDescription("Export the group Multirate properties for gmsh visualization");
cm = cb->addMethod("norm",(double (dgDofContainer::*)())&dgDofContainer::norm);
cm->setDescription("Returns the norm of the vector");
cm = cb->addMethod("scale",(void (dgDofContainer::*)(double))&dgDofContainer::scale);
cm->setArgNames("factor",NULL);
cm->setDescription("this=this*scale");
cm = cb->addMethod("axpy",(void (dgDofContainer::*)(dgDofContainer &,double)) &dgDofContainer::axpy);
cm->setArgNames("dofContainer","a",NULL);
cm->setDescription("this = this+a*dofContainer");
cm = cb->addMethod("Mesh2Mesh_BuildL2Projection",&dgDofContainer::Mesh2Mesh_BuildL2Projection);
cm->setDescription("Build L2 projection matrix between donor and this dofContainer.");
cm->setArgNames("projector","donor",NULL);
}