Forked from
gmsh / gmsh
14635 commits behind the upstream repository.
-
Richard Comblen authoredRichard Comblen authored
dgGroupOfElements.cpp 46.33 KiB
#include "GmshConfig.h"
#include "GmshMessage.h"
#include "dgGroupOfElements.h"
#include "dgConservationLaw.h"
#include "dgDofContainer.h"
#include "dgAlgorithm.h"
#include "MElement.h"
#include "polynomialBasis.h"
#include "Numeric.h"
#include "MTriangle.h"
#include "MQuadrangle.h"
#include "MLine.h"
#include "MPoint.h"
#include "GModel.h"
#ifdef HAVE_MPI
#include "mpi.h"
#else
#include <string.h>
#endif
static fullMatrix<double> * dgGetIntegrationRule (MElement *e, int p){
int npts;
IntPt *pts;
e->getIntegrationPoints(2*p+1, &npts, &pts);
fullMatrix<double> *m = new fullMatrix<double> (npts, 4);
for (int i=0;i<npts;i++){
(*m)(i,0) = pts[i].pt[0];
(*m)(i,1) = pts[i].pt[1];
(*m)(i,2) = pts[i].pt[2];
(*m)(i,3) = pts[i].weight;
}
return m;
}
static fullMatrix<double> dgGetFaceIntegrationRuleOnElement (
const polynomialBasis *fsFace,
const fullMatrix<double> &intgFace,
const polynomialBasis *fsElement,
const std::vector <int> &closure) {
int npts=intgFace.size1();
fullMatrix<double> intgElement(npts, 4);
double f[256];
for (int i=0;i<npts;i++){
fsFace->f(intgFace(i,0),intgFace(i,1),intgFace(i,2),f);
for(size_t j=0; j<closure.size();j++){
int jNod=closure[j];
for(int k=0;k<fsElement->points.size2();k++)
intgElement(i,k) += f[j] * fsElement->points(jNod,k);
intgElement(i,3) = intgFace(i,3);
}
}
return intgElement;
}
dgGroupOfElements::dgGroupOfElements(const std::vector<MElement*> &e,
int polyOrder,
int ghostPartition)
: _elements(e),
_fs(*_elements[0]->getFunctionSpace(polyOrder)),
_integration(dgGetIntegrationRule (_elements[0], polyOrder)),
_ghostPartition(ghostPartition)
{
_order=polyOrder;
_dimUVW = _dimXYZ = e[0]->getDim();
// this is the biggest piece of data ... the mappings
int nbPsi = _fs.coefficients.size1();
_redistributionFluxes[0] = new fullMatrix<double> (nbPsi,_integration->size1());
_redistributionFluxes[1] = new fullMatrix<double> (nbPsi,_integration->size1());
_redistributionFluxes[2] = new fullMatrix<double> (nbPsi,_integration->size1());
_redistributionSource = new fullMatrix<double> (nbPsi,_integration->size1());
_collocation = new fullMatrix<double> (_integration->size1(),nbPsi);
_mapping = new fullMatrix<double> (e.size(), 10 * _integration->size1());
_imass = new fullMatrix<double> (nbPsi,nbPsi*e.size());
_dPsiDx = new fullMatrix<double> ( _integration->size1()*3,nbPsi*e.size());
_elementVolume = new fullMatrix<double> (e.size(),1);
double g[256][3],f[256];
for (int i=0;i<_elements.size();i++){
MElement *e = _elements[i];
element_to_index[e] = i;
fullMatrix<double> imass(*_imass,nbPsi*i,nbPsi);
for (int j=0;j< _integration->size1() ; j++ ){
_fs.f((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), f);
_fs.df((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), g);
double jac[3][3],ijac[3][3],detjac;
(*_mapping)(i,10*j + 9) =
e->getJacobian ((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), jac);
(*_elementVolume)(i,0) += (*_mapping)(i,10*j+9)*(*_integration)(j,3);
const double weight = (*_integration)(j,3);
detjac=inv3x3(jac,ijac);
(*_mapping)(i,10*j + 0) = ijac[0][0];
(*_mapping)(i,10*j + 1) = ijac[0][1];
(*_mapping)(i,10*j + 2) = ijac[0][2];
(*_mapping)(i,10*j + 3) = ijac[1][0];
(*_mapping)(i,10*j + 4) = ijac[1][1];
(*_mapping)(i,10*j + 5) = ijac[1][2];
(*_mapping)(i,10*j + 6) = ijac[2][0];
(*_mapping)(i,10*j + 7) = ijac[2][1];
(*_mapping)(i,10*j + 8) = ijac[2][2];
for (int k=0;k<nbPsi;k++){
for (int l=0;l<nbPsi;l++) {
imass(k,l) += f[k]*f[l]*weight*detjac;
}
// (iQP*3+iXYZ , iFace*NPsi+iPsi)
(*_dPsiDx)(j*3 ,i*nbPsi+k) = g[k][0]*ijac[0][0]+g[k][1]*ijac[0][1]+g[k][2]*ijac[0][2];
(*_dPsiDx)(j*3+1,i*nbPsi+k) = g[k][0]*ijac[1][0]+g[k][1]*ijac[1][1]+g[k][2]*ijac[1][2];
(*_dPsiDx)(j*3+2,i*nbPsi+k) = g[k][0]*ijac[2][0]+g[k][1]*ijac[2][1]+g[k][2]*ijac[2][2];
}
}
imass.invertInPlace();
}
// redistribution matrix
// quadrature weight x parametric gradients in quadrature points
for (int j=0;j<_integration->size1();j++) {
_fs.df((*_integration)(j,0),
(*_integration)(j,1),
(*_integration)(j,2), g);
_fs.f((*_integration)(j,0),
(*_integration)(j,1),
(*_integration)(j,2), f);
const double weight = (*_integration)(j,3);
for (int k=0;k<_fs.coefficients.size1();k++){
(*_redistributionFluxes[0])(k,j) = g[k][0] * weight;
(*_redistributionFluxes[1])(k,j) = g[k][1] * weight;
(*_redistributionFluxes[2])(k,j) = g[k][2] * weight;
(*_redistributionSource)(k,j) = f[k] * weight;
(*_collocation)(j,k) = f[k];
}
}
}
void dgGroupOfElements::copyPrivateDataFrom(const dgGroupOfElements *from){
// Msg::Error("dgGroupOfElements::copyPrivateDataFrom not yet implemented, ask Richard");
}
dgGroupOfElements::~dgGroupOfElements(){
delete _integration;
delete _redistributionFluxes[0];
delete _redistributionFluxes[1];
delete _redistributionFluxes[2];
delete _redistributionSource;
delete _dPsiDx;
delete _mapping;
delete _collocation;
delete _imass;
delete _elementVolume;
}
void dgGroupOfFaces::addFace(const MFace &topoFace, int iElLeft, int iElRight){
// compute all closures
// compute closures for the interpolation
_left.push_back(iElLeft);
MElement &elLeft = *_groupLeft.getElement(iElLeft);
int ithFace, sign, rot;
elLeft.getFaceInfo (topoFace, ithFace, sign, rot);
int closureIdLeft = _fsLeft->getFaceClosureId(ithFace, sign, rot);
_closuresIdLeft.push_back(closureIdLeft);
if(iElRight>=0){
_right.push_back(iElRight);
MElement &elRight = *_groupRight.getElement(iElRight);
elRight.getFaceInfo (topoFace, ithFace, sign, rot);
_closuresIdRight.push_back(_fsRight->getFaceClosureId(ithFace, sign, rot));
}
// compute the face element that correspond to the geometrical closure
// get the vertices of the face
std::vector<MVertex*> vertices;
const std::vector<int> & geomClosure = elLeft.getFunctionSpace()->getFaceClosure(closureIdLeft);
for (int j=0; j<geomClosure.size() ; j++)
vertices.push_back( elLeft.getVertex(geomClosure[j]) );
// triangular face
if (topoFace.getNumVertices() == 3){
switch(vertices.size()){
case 3 : _faces.push_back(new MTriangle (vertices) ); break;
case 6 : _faces.push_back(new MTriangle6 (vertices) ); break;
case 10 : _faces.push_back(new MTriangleN (vertices,3) ); break;
case 15 : _faces.push_back(new MTriangleN (vertices,4) ); break;
case 21 : _faces.push_back(new MTriangleN (vertices,5) ); break;
default : throw;
}
}
else if (topoFace.getNumVertices() == 4){
switch(vertices.size()){
case 4 : _faces.push_back(new MQuadrangle (vertices) ); break;
case 8 : _faces.push_back(new MQuadrangle8 (vertices) ); break;
case 9 : _faces.push_back(new MQuadrangle9 (vertices) ); break;
case 16 : _faces.push_back(new MQuadrangleN (vertices, 4)); break;
case 25 : _faces.push_back(new MQuadrangleN (vertices, 5)); break;
default : throw;
}
}
// quad face 2 do
else {
throw;
}
}
void dgGroupOfFaces::addEdge(const MEdge &topoEdge, int iElLeft, int iElRight) {
_left.push_back(iElLeft);
MElement &elLeft = *_groupLeft.getElement(iElLeft);
int ithEdge, sign;
elLeft.getEdgeInfo (topoEdge, ithEdge, sign);
_closuresIdLeft.push_back(_fsLeft->getEdgeClosureId(ithEdge, sign));
if(iElRight>=0) {
_right.push_back(iElRight);
_groupRight.getElement(iElRight)->getEdgeInfo (topoEdge, ithEdge, sign);
_closuresIdRight.push_back(_fsRight->getEdgeClosureId(ithEdge,sign));
}
std::vector<MVertex*> vertices;
const std::vector<int> &geomClosure = elLeft.getFunctionSpace()->getEdgeClosure(_closuresIdLeft.back());
for (int j=0; j<geomClosure.size() ; j++)
vertices.push_back( elLeft.getVertex(geomClosure[j]) );
switch(vertices.size())
{
case 2 : _faces.push_back(new MLine (vertices) ); break;
case 3 : _faces.push_back(new MLine3 (vertices) ); break;
default : _faces.push_back(new MLineN (vertices) ); break;
}
}
void dgGroupOfFaces::addVertex(MVertex *topoVertex, int iElLeft, int iElRight){
_left.push_back(iElLeft);
MElement &elLeft = *_groupLeft.getElement(iElLeft);
int ithVertex;
elLeft.getVertexInfo (topoVertex, ithVertex);
_closuresIdLeft.push_back(ithVertex);
if(iElRight>=0){
_right.push_back(iElRight);
MElement &elRight = *_groupRight.getElement(iElRight);
elRight.getVertexInfo (topoVertex, ithVertex);
_closuresIdRight.push_back(ithVertex);
}
_faces.push_back(new MPoint(topoVertex) );
}
void dgGroupOfFaces::init(int pOrder) {
if (!_faces.size())return;
_fsFace = _faces[0]->getFunctionSpace (pOrder);
_integration = dgGetIntegrationRule (_faces[0],pOrder);
_redistribution = new fullMatrix<double> (_fsFace->coefficients.size1(),_integration->size1());
_collocation = new fullMatrix<double> (_integration->size1(), _fsFace->coefficients.size1());
_detJac = new fullMatrix<double> (_integration->size1(), _faces.size());
_interfaceSurface = new fullMatrix<double>(_faces.size(),1);
for (size_t i=0; i<_closuresLeft.size(); i++)
_integrationPointsLeft.push_back(dgGetFaceIntegrationRuleOnElement(_fsFace,*_integration,_fsLeft,_closuresLeft[i]));
for (size_t i=0; i<_closuresRight.size(); i++)
_integrationPointsRight.push_back(dgGetFaceIntegrationRuleOnElement(_fsFace,*_integration,_fsRight,_closuresRight[i]));
double f[256];
for (int j=0;j<_integration->size1();j++) {
_fsFace->f((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), f);
const double weight = (*_integration)(j,3);
for (int k=0;k<_fsFace->coefficients.size1();k++){
(*_redistribution)(k,j) = f[k] * weight;
(*_collocation)(j,k) = f[k];
}
}
for (int i=0;i<_faces.size();i++){
MElement *f = _faces[i];
for (int j=0;j< _integration->size1() ; j++ ){
double jac[3][3];
(*_detJac)(j,i) = f->getJacobian ((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), jac);
(*_interfaceSurface)(i,0) += (*_integration)(j,3)*(*_detJac)(j,i);
}
}
// compute data on quadrature points : normals and dPsidX
double g[256][3];
_normals = new fullMatrix<double> (3,_integration->size1()*_faces.size());
_dPsiLeftDxOnQP = new fullMatrix<double> ( _integration->size1()*3,_fsLeft->points.size1()*_faces.size());
if(_fsRight){
_dPsiRightDxOnQP = new fullMatrix<double> ( _integration->size1()*3,_fsRight->points.size1()*_faces.size());
}
int index = 0;
for (size_t i=0; i<_faces.size();i++){
const std::vector<int> &closureLeft=getClosureLeft(i);
fullMatrix<double> &intLeft=_integrationPointsLeft[_closuresIdLeft[i]];
double jac[3][3],ijac[3][3];
for (int j=0; j<intLeft.size1(); j++){
_fsLeft->df((intLeft)(j,0),(intLeft)(j,1),(intLeft)(j,2),g);
getElementLeft(i)->getJacobian ((intLeft)(j,0), (intLeft)(j,1), (intLeft)(j,2), jac);
inv3x3(jac,ijac);
//compute dPsiLeftDxOnQP
// (iQP*3+iXYZ , iFace*NPsi+iPsi)
int nPsi = _fsLeft->coefficients.size1();
for (int iPsi=0; iPsi< nPsi; iPsi++) {
(*_dPsiLeftDxOnQP)(j*3 ,i*nPsi+iPsi) = g[iPsi][0]*ijac[0][0]+g[iPsi][1]*ijac[0][1]+g[iPsi][2]*ijac[0][2];
(*_dPsiLeftDxOnQP)(j*3+1,i*nPsi+iPsi) = g[iPsi][0]*ijac[1][0]+g[iPsi][1]*ijac[1][1]+g[iPsi][2]*ijac[1][2];
(*_dPsiLeftDxOnQP)(j*3+2,i*nPsi+iPsi) = g[iPsi][0]*ijac[2][0]+g[iPsi][1]*ijac[2][1]+g[iPsi][2]*ijac[2][2];
}
//compute face normals
double &nx=(*_normals)(0,index);
double &ny=(*_normals)(1,index);
double &nz=(*_normals)(2,index);
double nu=0,nv=0,nw=0;
for (size_t k=0; k<closureLeft.size(); k++){
int inode=closureLeft[k];
nu += g[inode][0];
nv += g[inode][1];
nw += g[inode][2];
}
nx = nu*ijac[0][0]+nv*ijac[0][1]+nw*ijac[0][2];
ny = nu*ijac[1][0]+nv*ijac[1][1]+nw*ijac[1][2];
nz = nu*ijac[2][0]+nv*ijac[2][1]+nw*ijac[2][2];
double norm = sqrt(nx*nx+ny*ny+nz*nz);
nx/=norm;
ny/=norm;
nz/=norm;
index++;
}
// there is nothing on the right for boundary groups
if(_fsRight){
fullMatrix<double> &intRight=_integrationPointsRight[_closuresIdRight[i]];
for (int j=0; j<intRight.size1(); j++){
_fsRight->df((intRight)(j,0),(intRight)(j,1),(intRight)(j,2),g);
getElementRight(i)->getJacobian ((intRight)(j,0), (intRight)(j,1), (intRight)(j,2), jac);
inv3x3(jac,ijac);
//compute dPsiRightDxOnQP
// (iQP*3+iXYZ , iFace*NPsi+iPsi)
int nPsi = _fsRight->coefficients.size1();
for (int iPsi=0; iPsi< nPsi; iPsi++) {
(*_dPsiRightDxOnQP)(j*3 ,i*nPsi+iPsi) = g[iPsi][0]*ijac[0][0]+g[iPsi][1]*ijac[0][1]+g[iPsi][2]*ijac[0][2];
(*_dPsiRightDxOnQP)(j*3+1,i*nPsi+iPsi) = g[iPsi][0]*ijac[1][0]+g[iPsi][1]*ijac[1][1]+g[iPsi][2]*ijac[1][2];
(*_dPsiRightDxOnQP)(j*3+2,i*nPsi+iPsi) = g[iPsi][0]*ijac[2][0]+g[iPsi][1]*ijac[2][1]+g[iPsi][2]*ijac[2][2];
}
}
}
}
}
dgGroupOfFaces::~dgGroupOfFaces()
{
if (!_faces.size())return;
delete _redistribution;
delete _collocation;
delete _detJac;
delete _normals;
delete _dPsiLeftDxOnQP;
delete _dPsiRightDxOnQP;
delete _interfaceSurface;
}
dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MVertex*> &boundaryVertices):
_groupLeft(elGroup),_groupRight(elGroup)
{
_boundaryTag=boundaryTag;
if(boundaryTag==""){
Msg::Warning ("empty boundary tag, group of boundary faces not created");
return;
}
_fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
_closuresLeft = _fsLeft->vertexClosure;
_fsRight=NULL;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumVertices(); j++){
MVertex* vertex = el.getVertex(j);
if(boundaryVertices.find(vertex)!=boundaryVertices.end())
addVertex(vertex,i,-1);
}
}
init(pOrder);
}
dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MEdge,Less_Edge> &boundaryEdges):
_groupLeft(elGroup),_groupRight(elGroup)
{
_boundaryTag=boundaryTag;
if(boundaryTag==""){
Msg::Warning ("empty boundary tag, group of boundary faces not created");
return;
}
_fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
_closuresLeft = _fsLeft->edgeClosure;
_fsRight=NULL;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumEdges(); j++){
MEdge edge = el.getEdge(j);
if(boundaryEdges.find(edge)!=boundaryEdges.end())
addEdge(edge,i,-1);
}
}
init(pOrder);
}
dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MFace,Less_Face> &boundaryFaces):
_groupLeft(elGroup),_groupRight(elGroup)
{
_boundaryTag=boundaryTag;
if(boundaryTag=="")
throw;
_fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
_closuresLeft = _fsLeft->faceClosure;
_fsRight=NULL;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumFaces(); j++){
MFace face = el.getFace(j);
if(boundaryFaces.find(face)!=boundaryFaces.end())
addFace(face,i,-1);
}
}
init(pOrder);
}
dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, int pOrder):
_groupLeft(elGroup),_groupRight(elGroup)
{
_fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
_fsRight=_groupRight.getElement(0)->getFunctionSpace(pOrder);
switch (_groupLeft.getElement(0)->getDim()) {
case 1 : {
std::map<MVertex*,int> vertexMap;
_closuresLeft = _fsLeft->vertexClosure;
_closuresRight = _fsRight->vertexClosure;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumVertices(); j++){
MVertex* vertex = el.getVertex(j);
if(vertexMap.find(vertex) == vertexMap.end()){
vertexMap[vertex] = i;
}else{
addVertex(vertex,vertexMap[vertex],i);
}
}
}
break;
}
case 2 : {
std::map<MEdge,int,Less_Edge> edgeMap;
_closuresLeft = _fsLeft->edgeClosure;
_closuresRight = _fsRight->edgeClosure;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumEdges(); j++){
MEdge edge = el.getEdge(j);
if(edgeMap.find(edge) == edgeMap.end()){
edgeMap[edge] = i;
}else{
addEdge(edge,edgeMap[edge],i);
}
}
}
break;
}
case 3 : {
std::map<MFace,int,Less_Face> faceMap;
_closuresLeft = _fsLeft->faceClosure;
_closuresRight = _fsRight->faceClosure;
for(int i=0; i<elGroup.getNbElements(); i++){
MElement &el = *elGroup.getElement(i);
for (int j=0; j<el.getNumFaces(); j++){
MFace face = el.getFace(j);
if(faceMap.find(face) == faceMap.end()){
faceMap[face] = i;
}else{
addFace(face,faceMap[face],i);
}
}
}
break;
}
default : throw;
}
init(pOrder);
}
dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup1, const dgGroupOfElements &elGroup2, int pOrder):
_groupLeft(elGroup1),_groupRight(elGroup2)
{
_fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
_fsRight=_groupRight.getElement(0)->getFunctionSpace(pOrder);
switch (_groupLeft.getElement(0)->getDim()) {
case 1 : {
std::map<MVertex*,int> vertexMap1;
_closuresLeft = _fsLeft->vertexClosure;
_closuresRight = _fsRight->vertexClosure;
for(int i=0; i<elGroup1.getNbElements(); i++){
MElement &el = *elGroup1.getElement(i);
for (int j=0; j<el.getNumVertices(); j++){
MVertex* vertex = el.getVertex(j);
if(vertexMap1.find(vertex) == vertexMap1.end()){
vertexMap1[vertex] = i;
}else{
vertexMap1.erase(vertex);
}
}
}
for(int i=0; i<elGroup2.getNbElements(); i++){
MElement &el = *elGroup2.getElement(i);
for (int j=0; j<el.getNumVertices(); j++){
MVertex* vertex = el.getVertex(j);
std::map<MVertex*,int>::iterator it = vertexMap1.find(vertex);
if(it != vertexMap1.end()){
addVertex(vertex,it->second,i);
}
}
}
}
break;
case 2 : {
std::map<MEdge,int,Less_Edge> edgeMap;
_closuresLeft = _fsLeft->edgeClosure;
_closuresRight = _fsRight->edgeClosure;
for(int i=0; i<elGroup1.getNbElements(); i++){
MElement &el = *elGroup1.getElement(i);
for (int j=0; j<el.getNumEdges(); j++){
MEdge edge = el.getEdge(j);
if(edgeMap.find(edge) == edgeMap.end()){
edgeMap[edge] = i;
}else{
edgeMap.erase(edge);
}
}
}
for(int i=0; i<elGroup2.getNbElements(); i++){
MElement &el = *elGroup2.getElement(i);
for (int j=0; j<el.getNumEdges(); j++){
MEdge edge = el.getEdge(j);
std::map<MEdge,int,Less_Edge>::iterator it = edgeMap.find(edge);
if(it != edgeMap.end()){
// MElement &el2 = *elGroup1.getElement(it->second);
// printf("%d %d \n",edge.getVertex(0)->getNum(),edge.getVertex(1)->getNum());
// for (int k=0;k<el.getNumVertices();k++)printf("%d ",el.getVertex(k)->getNum());
// printf("\n");
// for (int k=0;k<el2.getNumVertices();k++)printf("%d ",el2.getVertex(k)->getNum());
// printf("\n");
addEdge(edge,it->second,i);
}
}
}
break;
}
case 3 : {
std::map<MFace,int,Less_Face> faceMap;
_closuresLeft = _fsLeft->faceClosure;
_closuresRight = _fsRight->faceClosure;
for(int i=0; i<elGroup1.getNbElements(); i++){
MElement &el = *elGroup1.getElement(i);
for (int j=0; j<el.getNumFaces(); j++){
MFace face = el.getFace(j);
if(faceMap.find(face) == faceMap.end()){
faceMap[face] = i;
}else{
faceMap.erase(face);
}
}
}
for(int i=0; i<elGroup2.getNbElements(); i++){
MElement &el = *elGroup2.getElement(i);
for (int j=0; j<el.getNumFaces(); j++){
MFace face = el.getFace(j);
std::map<MFace,int,Less_Face>::iterator it = faceMap.find(face);
if(it != faceMap.end()){
addFace(face,it->second,i);
}
}
}
break;
}
default : throw;
}
init(pOrder);
}
void dgGroupOfFaces::mapToInterface ( int nFields,
const fullMatrix<double> &vLeft,
const fullMatrix<double> &vRight,
fullMatrix<double> &v)
{
if(isBoundary()){
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureLeft.size(); j++){
v(j, i*nFields + iField) = vLeft(closureLeft[j], _left[i]*nFields + iField);
}
}
}
}else{
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureRight = getClosureRight(i);
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureLeft.size(); j++){
v(j, i*2*nFields + iField) = vLeft(closureLeft[j], _left[i]*nFields + iField);
}
for(size_t j =0; j < closureRight.size(); j++)
v(j, (i*2+1)*nFields + iField) = vRight(closureRight[j], _right[i]*nFields + iField);
}
}
}
}
void dgGroupOfFaces::mapFromInterface ( int nFields,
const fullMatrix<double> &v,
fullMatrix<double> &vLeft,
fullMatrix<double> &vRight
)
{
if(isBoundary()){
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureLeft.size(); j++)
vLeft(closureLeft[j], _left[i]*nFields + iField) += v(j, i*nFields + iField);
}
}
}else{
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureRight = getClosureRight(i);
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureLeft.size(); j++)
vLeft(closureLeft[j], _left[i]*nFields + iField) += v(j, i*2*nFields + iField);
for(size_t j =0; j < closureRight.size(); j++)
vRight(closureRight[j], _right[i]*nFields + iField) += v(j, (i*2+1)*nFields + iField);
}
}
}
}
void dgGroupOfFaces::mapLeftFromInterface ( int nFields,
const fullMatrix<double> &v,
fullMatrix<double> &vLeft
)
{
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureRight = getClosureRight(i);
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureLeft.size(); j++)
vLeft(closureLeft[j], _left[i]*nFields + iField) += v(j, i*2*nFields + iField);
}
}
}
void dgGroupOfFaces::mapRightFromInterface ( int nFields,
const fullMatrix<double> &v,
fullMatrix<double> &vRight
)
{
for(int i=0; i<getNbElements(); i++) {
const std::vector<int> &closureRight = getClosureRight(i);
const std::vector<int> &closureLeft = getClosureLeft(i);
for (int iField=0; iField<nFields; iField++){
for(size_t j =0; j < closureRight.size(); j++)
vRight(closureRight[j], _right[i]*nFields + iField) += v(j, (i*2+1)*nFields + iField);
}
}
}
/*
void dgAlgorithm::buildGroupsOfFaces(GModel *model, int dim, int order,
std::vector<dgGroupOfElements*> &eGroups,
std::vector<dgGroupOfFaces*> &fGroups,
std::vector<dgGroupOfFaces*> &bGroups){
}
void dgAlgorithm::buildMandatoryGroups(dgGroupOfElements &eGroup,
std::vector<dgGroupOfElements*> &partitionedGroups){
}
void dgAlgorithm::partitionGroup(dgGroupOfElements &eGroup,
std::vector<dgGroupOfElements*> &partitionedGroups){
}
*/
//static void partitionGroup (std::vector<MElement *>,){
//}
// this function creates groups of elements
// First, groups of faces are created on every physical group
// of dimension equal to the dimension of the problem minus one
// Then, groups of elements are created
// -) Elements of different types are separated
// -) Then those groups are split into partitions
// -) Finally, those groups are re-numbered
void dgGroupCollection::buildGroupsOfElements(GModel *model, int dim, int order)
{
if(_groupsOfElementsBuilt)
return;
_groupsOfElementsBuilt=true;
_model = model;
std::vector<GEntity*> entities;
model->getEntities(entities);
std::map<int, std::vector<MElement *> >localElements;
int nlocal=0;
for(unsigned int i = 0; i < entities.size(); i++){
GEntity *entity = entities[i];
if(entity->dim() == dim){
for (int iel=0; iel<entity->getNumMeshElements(); iel++){
MElement *el=entity->getMeshElement(iel);
if(el->getPartition()==Msg::GetCommRank()+1 || el->getPartition()==0){
localElements[el->getType()].push_back(el);
nlocal++;
}
}
}
}
// do a group of elements for every element type in the mesh
int id=_elementGroups.size();
for (std::map<int, std::vector<MElement *> >::iterator it = localElements.begin(); it !=localElements.end() ; ++it){
dgGroupOfElements *newGroup=new dgGroupOfElements(it->second,order);
_elementGroups.push_back(newGroup);
id++;
}
}
// Finally, group of interfaces are created
// -) Groups of faces internal to a given group
// -) Groups of faces between groups.
void dgGroupCollection::buildGroupsOfInterfaces() {
if(_groupsOfInterfacesBuilt)
return;
_groupsOfInterfacesBuilt=true;
int dim = _elementGroups[0]->getElement(0)->getDim();
int order = _elementGroups[0]->getOrder();
std::map<const std::string,std::set<MVertex*> > boundaryVertices;
std::map<const std::string,std::set<MEdge, Less_Edge> > boundaryEdges;
std::map<const std::string,std::set<MFace, Less_Face> > boundaryFaces;
std::vector<std::map<int, std::vector<MElement *> > >ghostElements(Msg::GetCommSize()); // [partition][elementType]
int nghosts=0;
std::multimap<MElement*, short> &ghostsCells = _model->getGhostCells();
std::vector<GEntity*> entities;
_model->getEntities(entities);
for(unsigned int i = 0; i < entities.size(); i++){
GEntity *entity = entities[i];
if(entity->dim() == dim-1){
for(unsigned int j = 0; j < entity->physicals.size(); j++){
const std::string physicalName = _model->getPhysicalName(entity->dim(), entity->physicals[j]);
for (int k = 0; k < entity->getNumMeshElements(); k++) {
MElement *element = entity->getMeshElement(k);
switch(dim) {
case 1:
boundaryVertices[physicalName].insert( element->getVertex(0) );
break;
case 2:
boundaryEdges[physicalName].insert( element->getEdge(0) );
break;
case 3:
boundaryFaces[physicalName].insert( element->getFace(0));
break;
default :
throw;
}
}
}
}
else if(entity->dim() == dim){
for (int iel=0; iel<entity->getNumMeshElements(); iel++){
MElement *el=entity->getMeshElement(iel);
if( ! (el->getPartition()==Msg::GetCommRank()+1 || el->getPartition()==0) ){
std::multimap<MElement*, short>::iterator ghost=ghostsCells.lower_bound(el);
while(ghost!= ghostsCells.end() && ghost->first==el){
if(abs(ghost->second)-1==Msg::GetCommRank()){
ghostElements[el->getPartition()-1][el->getType()].push_back(el);
nghosts+=1;
}
ghost++;
}
}
}
}
}
for (int i=0;i<_elementGroups.size();i++){
// create a group of faces on the boundary for every group of elements
switch(dim) {
case 1 : {
std::map<const std::string, std::set<MVertex*> >::iterator mapIt;
for(mapIt=boundaryVertices.begin(); mapIt!=boundaryVertices.end(); mapIt++) {
dgGroupOfFaces *gof = new dgGroupOfFaces(*_elementGroups[i],mapIt->first,order,mapIt->second);
if (gof->getNbElements())
_boundaryGroups.push_back(gof);
else
delete gof;
break;
}
}
case 2 : {
std::map<const std::string, std::set<MEdge, Less_Edge> >::iterator mapIt;
for(mapIt=boundaryEdges.begin(); mapIt!=boundaryEdges.end(); mapIt++) {
dgGroupOfFaces *gof=new dgGroupOfFaces(*_elementGroups[i],mapIt->first,order,mapIt->second);
if(gof->getNbElements())
_boundaryGroups.push_back(gof);
else
delete gof;
}
break;
}
case 3 : {
std::map<const std::string, std::set<MFace, Less_Face> >::iterator mapIt;
for(mapIt=boundaryFaces.begin(); mapIt!=boundaryFaces.end(); mapIt++) {
dgGroupOfFaces *gof=new dgGroupOfFaces(*_elementGroups[i],mapIt->first,order,mapIt->second);
if(gof->getNbElements())
_boundaryGroups.push_back(gof);
else
delete gof;
}
break;
}
}
// create a group of faces for every face that is common to elements of the same group
dgGroupOfFaces *gof=new dgGroupOfFaces(*_elementGroups[i],order);
if(gof->getNbElements())
_faceGroups.push_back(gof);
else
delete gof;
// create a groupe of d
for (int j=i+1;j<_elementGroups.size();j++){
dgGroupOfFaces *gof = new dgGroupOfFaces(*_elementGroups[i],*_elementGroups[j],order);
if (gof->getNbElements())
_faceGroups.push_back(gof);
else
delete gof;
}
}
//create ghost groups
for(int i=0;i<Msg::GetCommSize();i++){
for (std::map<int, std::vector<MElement *> >::iterator it = ghostElements[i].begin(); it !=ghostElements[i].end() ; ++it){
dgGroupOfElements *gof=new dgGroupOfElements(it->second,order,i);
if (gof->getNbElements())
_ghostGroups.push_back(gof);
else
delete gof;
}
}
//create face group for ghostGroups
for (int i=0; i<_ghostGroups.size(); i++){
for (int j=0;j<_elementGroups.size();j++){
dgGroupOfFaces *gof = new dgGroupOfFaces(*_ghostGroups[i],*_elementGroups[j],order);
if (gof->getNbElements())
_faceGroups.push_back(gof);
else
delete gof;
}
}
// build the ghosts structure
int *nGhostElements = new int[Msg::GetCommSize()];
int *nParentElements = new int[Msg::GetCommSize()];
for (int i=0;i<Msg::GetCommSize();i++) {
nGhostElements[i]=0;
}
for (size_t i = 0; i< getNbGhostGroups(); i++){
dgGroupOfElements *group = getGhostGroup(i);
nGhostElements[group->getGhostPartition()] += group->getNbElements();
}
#ifdef HAVE_MPI
MPI_Alltoall(nGhostElements,1,MPI_INT,nParentElements,1,MPI_INT,MPI_COMM_WORLD);
#else
nParentElements[0]=nGhostElements[0];
#endif
int *shiftSend = new int[Msg::GetCommSize()];
int *shiftRecv = new int[Msg::GetCommSize()];
int *curShiftSend = new int[Msg::GetCommSize()];
int totalSend=0,totalRecv=0;
for(int i= 0; i<Msg::GetCommSize();i++){
shiftSend[i] = (i==0 ? 0 : shiftSend[i-1]+nGhostElements[i-1]);
curShiftSend[i] = shiftSend[i];
shiftRecv[i] = (i==0 ? 0 : shiftRecv[i-1]+nParentElements[i-1]);
totalSend += nGhostElements[i];
totalRecv += nParentElements[i];
}
int *idSend = new int[totalSend];
int *idRecv = new int[totalRecv];
for (int i = 0; i<getNbGhostGroups(); i++){
dgGroupOfElements *group = getGhostGroup(i);
int part = group->getGhostPartition();
for (int j=0; j< group->getNbElements() ; j++){
idSend[curShiftSend[part]++] = group->getElement(j)->getNum();
}
}
#ifdef HAVE_MPI
MPI_Alltoallv(idSend,nGhostElements,shiftSend,MPI_INT,idRecv,nParentElements,shiftRecv,MPI_INT,MPI_COMM_WORLD);
#else
memcpy(idRecv,idSend,nParentElements[0]*sizeof(int));
#endif
//create a Map elementNum :: group, position in group
std::map<int, std::pair<int,int> > elementMap;
for(size_t i = 0; i< getNbElementGroups(); i++) {
dgGroupOfElements *group = getElementGroup(i);
for(int j=0; j< group->getNbElements(); j++){
elementMap[group->getElement(j)->getNum()]=std::pair<int,int>(i,j);
}
}
_elementsToSend.resize(Msg::GetCommSize());
for(int i = 0; i<Msg::GetCommSize();i++){
_elementsToSend[i].resize(nParentElements[i]);
for(int j=0;j<nParentElements[i];j++){
int num = idRecv[shiftRecv[i]+j];
_elementsToSend[i][j]=elementMap[num];
}
}
delete []idRecv;
delete []idSend;
delete []curShiftSend;
delete []shiftSend;
delete []shiftRecv;
}
// Split the groups of elements depending on their local time step
double dgGroupCollection::splitGroupsForMultirate(int maxLevels,dgConservationLaw *claw, dgDofContainer *solution){
Msg::Info("Splitting Groups for multirate time stepping");
maxLevels--;
int maxNumElems=getElementGroup(0)->getElement(0)->getGlobalNumber()+1;
std::vector<int>oldGroupIds;
oldGroupIds.resize(maxNumElems);
std::vector<MElement*>allElements;
allElements.resize(maxNumElems);
for(int iGroup=0;iGroup<getNbElementGroups();iGroup++){
dgGroupOfElements *elGroup=getElementGroup(iGroup);
for(int iElement=0;iElement<elGroup->getNbElements();iElement++){
MElement *el=elGroup->getElement(iElement);
oldGroupIds[el->getNum()]=iGroup;
allElements[el->getNum()]=el;
}
}
std::vector<int>newGroupIds;
newGroupIds.assign(maxNumElems,-1);
std::vector<std::vector<int> >elementToNeighbors;
elementToNeighbors.resize(maxNumElems);
switch(getElementGroup(0)->getElement(0)->getDim()){
case 1:
{
std::map<MVertex*,int> vertexMap;
for(int iGroup=0;iGroup<getNbElementGroups();iGroup++){
dgGroupOfElements *elGroup=getElementGroup(iGroup);
for(int iElement=0; iElement<elGroup->getNbElements(); iElement++){
MElement *el = elGroup->getElement(iElement);
for (int iVertex=0; iVertex<el->getNumVertices(); iVertex++){
MVertex* vertex = el->getVertex(iVertex);
if(vertexMap.find(vertex) == vertexMap.end()){
vertexMap[vertex] = el->getNum();
}else{
elementToNeighbors[vertexMap[vertex]].push_back(el->getNum());
elementToNeighbors[el->getNum()].push_back(vertexMap[vertex]);
}
}
}
}
vertexMap.clear();
}
break;
case 2:
{
std::map<MEdge,int,Less_Edge> edgeMap;
for(int iGroup=0;iGroup<getNbElementGroups();iGroup++){
dgGroupOfElements *elGroup=getElementGroup(iGroup);
for(int iElement=0; iElement<elGroup->getNbElements(); iElement++){
MElement *el = elGroup->getElement(iElement);
for (int iEdge=0; iEdge<el->getNumEdges(); iEdge++){
MEdge edge = el->getEdge(iEdge);
if(edgeMap.find(edge) == edgeMap.end()){
edgeMap[edge] = el->getNum();
}else{
elementToNeighbors[edgeMap[edge]].push_back(el->getNum());
elementToNeighbors[el->getNum()].push_back(edgeMap[edge]);
}
}
}
}
edgeMap.clear();
}
break;
case 3:
{
std::map<MFace,int,Less_Face> faceMap;
for(int iGroup=0;iGroup<getNbElementGroups();iGroup++){
dgGroupOfElements *elGroup=getElementGroup(iGroup);
for(int iElement=0; iElement<elGroup->getNbElements(); iElement++){
MElement *el = elGroup->getElement(iElement);
for (int iFace=0; iFace<el->getNumFaces(); iFace++){
MFace face = el->getFace(iFace);
if(faceMap.find(face) == faceMap.end()){
faceMap[face] = el->getNum();
}else{
elementToNeighbors[faceMap[face]].push_back(el->getNum());
elementToNeighbors[el->getNum()].push_back(faceMap[face]);
}
}
}
}
faceMap.clear();
}
break;
default:
break;
}
// find the range of time steps
double dtMin = DBL_MAX;
double dtMax = 0;
std::vector<double> *DTS=new std::vector<double>[getNbElementGroups()];
for (int i=0;i<getNbElementGroups();i++){
dgAlgorithm::computeElementaryTimeSteps(*claw, *getElementGroup(i), solution->getGroupProxy(i), DTS[i]);
for (int k=0;k<DTS[i].size();k++){
dtMin = std::min(dtMin,DTS[i][k]);
dtMax = std::max(dtMax,DTS[i][k]);
}
}
std::vector<double>localDt;
localDt.resize(maxNumElems);
for (int i=0;i<getNbElementGroups();i++){
dgGroupOfElements *elGroup=getElementGroup(i);
for(int j=0;j<DTS[i].size();j++){
MElement *el=elGroup->getElement(j);
localDt[el->getNum()]=DTS[i][j];
}
}
delete []DTS;
#ifdef HAVE_MPI
double dtMin_min;
MPI_Allreduce((void *)&dtMin, &dtMin_min, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
dtMin=dtMin_min;
double dtMax_max;
MPI_Allreduce((void *)&dtMax, &dtMax_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
dtMax=dtMax_max;
#endif
// dtMin is the time step for the most constrained element.
Msg::Info("Time step for standard RK should be %e",dtMin);
Msg::Info("Multirate base time step should be %e",dtMax);
double dtRef=dtMax*0.8;
// time steps are dtRef*2^(-dtExponent), with dtExponent ranging in [0:dtMaxExponent]
int dtMaxExponent=0;
while(dtRef/pow(2.0,(double)dtMaxExponent)>dtMin)
dtMaxExponent++;
if(dtMaxExponent>maxLevels){
dtRef*=1.0/pow(2.0,(double)(dtMaxExponent-maxLevels));
dtMaxExponent=maxLevels;
}
_dtMaxExponent=dtMaxExponent;
std::vector<MElement *>currentNewGroup;
std::vector< dgGroupOfElements* >newGroups;// indexed by newGroupId
std::map<int,int>oldToNewGroupsMap;// oldGroupId to newGroupId
int lowerLevelGroupIdStart=-1;
int lowerLevelGroupIdEnd=-1;
bool isOuterBufferLayer=false;
int currentNewGroupId=0;
int loopId=0;
for(int currentExponent=dtMaxExponent;currentExponent>=0;(!isOuterBufferLayer)?currentExponent--:currentExponent=currentExponent){
double currentDt=dtRef/pow(2.0,(double)currentExponent);
std::map<int,std::vector<MElement*> >mapNewGroups;
if(lowerLevelGroupIdStart==-1){
lowerLevelGroupIdStart=0;
}
else{
// Add the neighbors elements to the new groups
int _lowerLevelGroupIdStart=lowerLevelGroupIdStart;
int _lowerLevelGroupIdEnd=lowerLevelGroupIdEnd;
lowerLevelGroupIdStart=lowerLevelGroupIdEnd;
for(int iNewGroup=_lowerLevelGroupIdStart;iNewGroup<_lowerLevelGroupIdEnd;iNewGroup++){
for(int iElement=0; iElement<newGroups[iNewGroup]->getNbElements(); iElement++){
MElement *el = newGroups[iNewGroup]->getElement(iElement);
for(int iNeighbor=0;iNeighbor<elementToNeighbors[el->getNum()].size();iNeighbor++){
int neighId=elementToNeighbors[el->getNum()][iNeighbor];
if(newGroupIds[neighId]==-1){
mapNewGroups[oldGroupIds[neighId]].push_back(allElements[neighId]);
newGroupIds[neighId]=-2;
}
}
}
}
}
if(!isOuterBufferLayer){
for(int iGroup=0;iGroup<getNbElementGroups();iGroup++){
dgGroupOfElements *elGroup=getElementGroup(iGroup);
for(int iElement=0;iElement<elGroup->getNbElements();iElement++){
MElement *el=elGroup->getElement(iElement);
if(localDt[el->getNum()]>=currentDt && (localDt[el->getNum()]<currentDt*2 || currentExponent==0)){
if(newGroupIds[el->getNum()]==-1){
mapNewGroups[iGroup].push_back(el);
newGroupIds[el->getNum()]=-2;
}
}
}
}
lowerLevelGroupIdStart=currentNewGroupId;
for (std::map<int, std::vector<MElement *> >::iterator it = mapNewGroups.begin(); it !=mapNewGroups.end() ; ++it){
if(!it->second.empty()){
std::vector<MElement *>forBulk;
std::vector<MElement *>forInnerBuffer;
for(int i=0;i<it->second.size();i++){
MElement* el=it->second[i];
bool inInnerBuffer=false;
for(int iNeighbor=0;iNeighbor<elementToNeighbors[el->getNum()].size();iNeighbor++){
int neighId=elementToNeighbors[el->getNum()][iNeighbor];
if(newGroupIds[neighId]==-1){
inInnerBuffer=true;
continue;
}
}
if(inInnerBuffer){
forInnerBuffer.push_back(el);
}
else{
forBulk.push_back(el);
}
}
for(int i=0;i<forBulk.size();i++){
newGroupIds[it->second[i]->getNum()]=currentNewGroupId;
}
dgGroupOfElements *oldGroup=getElementGroup(it->first);
dgGroupOfElements *newGroup;
if(!forBulk.empty()){
newGroup=new dgGroupOfElements(forBulk,oldGroup->getOrder(),oldGroup->getGhostPartition());
newGroup->copyPrivateDataFrom(oldGroup);
newGroup->_multirateExponent=currentExponent;
newGroup->_multirateOuterBuffer=false;
newGroup->_multirateInnerBuffer=false;
newGroups.resize(currentNewGroupId+1);
newGroups[currentNewGroupId]=newGroup;
oldToNewGroupsMap[it->first]=currentNewGroupId;
currentNewGroupId++;
}
if(!forInnerBuffer.empty()){
newGroup=new dgGroupOfElements(forInnerBuffer,oldGroup->getOrder(),oldGroup->getGhostPartition());
newGroup->copyPrivateDataFrom(oldGroup);
newGroup->_multirateExponent=currentExponent;
newGroup->_multirateOuterBuffer=false;
newGroup->_multirateInnerBuffer=true;
newGroups.resize(currentNewGroupId+1);
newGroups[currentNewGroupId]=newGroup;
oldToNewGroupsMap[it->first]=currentNewGroupId;
currentNewGroupId++;
}
}
else
Msg::Info("Empty Group !!!!!!!!!!!!!!!!!!");
}
}
else{
for (std::map<int, std::vector<MElement *> >::iterator it = mapNewGroups.begin(); it !=mapNewGroups.end() ; ++it){
if(!it->second.empty()){
for(int i=0;i<it->second.size();i++){
newGroupIds[it->second[i]->getNum()]=currentNewGroupId;
}
dgGroupOfElements *oldGroup=getElementGroup(it->first);
dgGroupOfElements *newGroup=new dgGroupOfElements(it->second,oldGroup->getOrder(),oldGroup->getGhostPartition());
newGroup->copyPrivateDataFrom(oldGroup);
newGroup->_multirateExponent=currentExponent;
newGroup->_multirateOuterBuffer=true;
newGroup->_multirateInnerBuffer=false;
newGroups.resize(currentNewGroupId+1);
newGroups[currentNewGroupId]=newGroup;
oldToNewGroupsMap[it->first]=currentNewGroupId;
currentNewGroupId++;
}
else
Msg::Info("Empty Group !!!!!!!!!!!!!!!!!!");
}
}
lowerLevelGroupIdEnd=currentNewGroupId;
isOuterBufferLayer=!isOuterBufferLayer;
}
int count=0;
for(int i=0;i<newGroups.size();i++){
Msg::Info("%d New group # %d has %d elements",newGroups[i]->getMultirateExponent(),i,newGroups[i]->getNbElements());
if(newGroups[i]->getIsInnerMultirateBuffer())
Msg::Info("InnerBuffer");
else if(newGroups[i]->getIsOuterMultirateBuffer())
Msg::Info("OuterBuffer");
else
Msg::Info("Not Buffer");
count+=newGroups[i]->getNbElements();
}
Msg::Info("That makes a total of %d elements",count);
_elementGroups.clear();
_elementGroups=newGroups;
return dtRef;
}
dgGroupCollection::dgGroupCollection()
{
_groupsOfElementsBuilt=false;_groupsOfInterfacesBuilt=false;
}
dgGroupCollection::dgGroupCollection(GModel *model, int dimension, int order)
{
_groupsOfElementsBuilt=false;_groupsOfInterfacesBuilt=false;
buildGroupsOfElements(model,dimension,order);
}
dgGroupCollection::~dgGroupCollection() {
for (int i=0; i< _elementGroups.size(); i++)
delete _elementGroups[i];
for (int i=0; i< _faceGroups.size(); i++)
delete _faceGroups[i];
for (int i=0; i< _boundaryGroups.size(); i++)
delete _boundaryGroups[i];
for (int i=0; i< _ghostGroups.size(); i++)
delete _ghostGroups[i];
}
void dgGroupCollection::find (MElement*e, int &ig, int &index){
for (ig=0;ig<_elementGroups.size();ig++){
index = _elementGroups[ig]->getIndexOfElement(e);
if (index != -1)return;
}
}
#include "LuaBindings.h"
void dgGroupCollection::registerBindings(binding *b){
classBinding *cb;
methodBinding *cm;
cb = b->addClass<dgGroupOfElements>("dgGroupOfElements");
cb->setDescription("a group of element sharing the same properties");
cb = b->addClass<dgGroupOfFaces>("dgGroupOfFaces");
cb->setDescription("a group of faces. All faces of this group are either interior of the same group of elements or at the boundary between two group of elements");
cb = b->addClass<dgGroupCollection>("dgGroupCollection");
cb->setDescription("The GroupCollection class let you access to group partitioning functions");
cm = cb->setConstructor<dgGroupCollection,GModel*,int,int>();
cm->setDescription("Build the group of elements, separated by element type and element order. Additional partitioning can be done using splitGroupsForXXX specific functions");
cm->setArgNames("model","dimension","order",NULL);
cm = cb->addMethod("buildGroupsOfInterfaces",&dgGroupCollection::buildGroupsOfInterfaces);
cm->setDescription("Build the group of interfaces, i.e. boundary interfaces and inter-element interfaces");
cm = cb->addMethod("splitGroupsForMultirate",&dgGroupCollection::splitGroupsForMultirate);
cm->setDescription("Split the groups according to their own stable time step");
cm->setArgNames("maxLevels","claw","solution",NULL);
cm = cb->addMethod("getNbElementGroups", &dgGroupCollection::getNbElementGroups);
cm->setDescription("return the number of dgGroupOfElements");
cm = cb->addMethod("getNbFaceGroups", &dgGroupCollection::getNbFaceGroups);
cm->setDescription("return the number of dgGroupOfFaces (interior ones, not the domain boundaries)");
cm = cb->addMethod("getNbBoundaryGroups", &dgGroupCollection::getNbBoundaryGroups);
cm->setDescription("return the number of group of boundary faces");
cm = cb->addMethod("getElementGroup", &dgGroupCollection::getElementGroup);
cm->setDescription("get 1 group of elements");
cm->setArgNames("id", NULL);
cm = cb->addMethod("getFaceGroup", &dgGroupCollection::getFaceGroup);
cm->setDescription("get 1 group of faces");
cm->setArgNames("id", NULL);
cm = cb->addMethod("getBoundaryGroup", &dgGroupCollection::getBoundaryGroup);
cm->setDescription("get 1 group of boundary faces");
cm->setArgNames("id", NULL);
}