Forked from
gmsh / gmsh
14999 commits behind the upstream repository.
-
Christophe Geuzaine authored
- renamed functionSpace into polynomialBasis (functionSpace will be much higher level)
Christophe Geuzaine authored- renamed functionSpace into polynomialBasis (functionSpace will be much higher level)
PViewDataGModel.cpp 15.26 KiB
// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#include "PViewDataGModel.h"
#include "MLine.h"
#include "MTriangle.h"
#include "MQuadrangle.h"
#include "MTetrahedron.h"
#include "MHexahedron.h"
#include "MPrism.h"
#include "MPyramid.h"
#include "Numeric.h"
#include "GmshMessage.h"
PViewDataGModel::PViewDataGModel(DataType type)
: PViewData(), _min(VAL_INF), _max(-VAL_INF), _type(type)
{
}
PViewDataGModel::~PViewDataGModel()
{
for(unsigned int i = 0; i < _steps.size(); i++) delete _steps[i];
}
bool PViewDataGModel::finalize()
{
_min = VAL_INF;
_max = -VAL_INF;
for(int step = 0; step < getNumTimeSteps(); step++){
_steps[step]->setMin(VAL_INF);
_steps[step]->setMax(-VAL_INF);
if(_type == NodeData || _type == ElementData){
// treat these 2 special cases separately for maximum efficiency
int numComp = _steps[step]->getNumComponents();
for(int i = 0; i < _steps[step]->getNumData(); i++){
double *d = _steps[step]->getData(i);
if(d){
double val = ComputeScalarRep(numComp, d);
_steps[step]->setMin(std::min(_steps[step]->getMin(), val));
_steps[step]->setMax(std::max(_steps[step]->getMax(), val));
}
}
}
else{
// general case (slower)
for(int ent = 0; ent < getNumEntities(step); ent++){
for(int ele = 0; ele < getNumElements(step, ent); ele++){
if(skipElement(step, ent, ele)) continue;
for(int nod = 0; nod < getNumNodes(step, ent, ele); nod++){
double val;
getScalarValue(step, ent, ele, nod, val);
_steps[step]->setMin(std::min(_steps[step]->getMin(), val));
_steps[step]->setMax(std::max(_steps[step]->getMax(), val));
}
}
}
}
_min = std::min(_min, _steps[step]->getMin());
_max = std::max(_max, _steps[step]->getMax());
}
// add interpolation data for known element types (this might be
// overidden later)
for(int step = 0; step < getNumTimeSteps(); step++){
GModel *m = _steps[step]->getModel();
for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++){
if((*it)->lines.size())
_addInterpolationMatricesForElement((*it)->lines[0]);
}
for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
if((*it)->triangles.size())
_addInterpolationMatricesForElement((*it)->triangles[0]);
if((*it)->quadrangles.size())
_addInterpolationMatricesForElement((*it)->quadrangles[0]);
}
for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
if((*it)->tetrahedra.size())
_addInterpolationMatricesForElement((*it)->tetrahedra[0]);
if((*it)->hexahedra.size())
_addInterpolationMatricesForElement((*it)->hexahedra[0]);
if((*it)->prisms.size())
_addInterpolationMatricesForElement((*it)->prisms[0]);
if((*it)->pyramids.size())
_addInterpolationMatricesForElement((*it)->pyramids[0]);
}
}
return PViewData::finalize();
}
void PViewDataGModel::_addInterpolationMatricesForElement(MElement *e)
{
int type = e->getType();
const polynomialBasis *fs = e->getFunctionSpace();
if(fs){
if(e->getPolynomialOrder() > 1)
setInterpolationMatrices(type, fs->coefficients, fs->monomials,
fs->coefficients, fs->monomials);
else
setInterpolationMatrices(type, fs->coefficients, fs->monomials);
}
}
MElement *PViewDataGModel::_getElement(int step, int ent, int ele)
{
static int lastStep = -1, lastEnt = -1, lastEle = -1;
static MElement *curr = 0;
if(step != lastStep || ent != lastEnt || ele != lastEle)
curr = _steps[step]->getEntity(ent)->getMeshElement(ele);
return curr;
}
int PViewDataGModel::getNumTimeSteps()
{
return _steps.size();
}
double PViewDataGModel::getTime(int step)
{
if(_steps.empty()) return 0.;
return _steps[step]->getTime();
}
double PViewDataGModel::getMin(int step)
{
if(step < 0 || _steps.empty()) return _min;
return _steps[step]->getMin();
}
double PViewDataGModel::getMax(int step)
{
if(step < 0 || _steps.empty()) return _max;
return _steps[step]->getMax();
}
SBoundingBox3d PViewDataGModel::getBoundingBox(int step)
{
if(step < 0 || _steps.empty()){
SBoundingBox3d tmp;
for(unsigned int i = 0; i < _steps.size(); i++)
tmp += _steps[i]->getBoundingBox();
return tmp;
}
return _steps[step]->getBoundingBox();
}
int PViewDataGModel::getNumScalars(int step)
{
if(_steps.empty()) return 0;
// to generalize
if(_steps[0]->getNumComponents() == 1) return getNumElements(0);
return 0;
}
int PViewDataGModel::getNumVectors(int step)
{
if(_steps.empty()) return 0;
// to generalize
if(_steps[0]->getNumComponents() == 3) return getNumElements(0);
return 0;
}
int PViewDataGModel::getNumTensors(int step)
{
if(_steps.empty()) return 0;
// to generalize
if(_steps[0]->getNumComponents() == 9) return getNumElements(0);
return 0;
}
int PViewDataGModel::getNumPoints(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::viter it = m->firstVertex(); it != m->lastVertex(); ++it)
n += (*it)->points.size();
return n;
}
int PViewDataGModel::getNumLines(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); ++it)
n += (*it)->lines.size();
return n;
}
int PViewDataGModel::getNumTriangles(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
n += (*it)->triangles.size();
return n;
}
int PViewDataGModel::getNumQuadrangles(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
n += (*it)->quadrangles.size();
return n;
}
int PViewDataGModel::getNumTetrahedra(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
n += (*it)->tetrahedra.size();
return n;
}
int PViewDataGModel::getNumHexahedra(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
n += (*it)->hexahedra.size();
return n;
}
int PViewDataGModel::getNumPrisms(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
n += (*it)->prisms.size();
return n;
}
int PViewDataGModel::getNumPyramids(int step)
{
if(_steps.empty()) return 0;
GModel *m = _steps[0]->getModel(); // to generalize
int n = 0;
for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
n += (*it)->pyramids.size();
return n;
}
int PViewDataGModel::getNumEntities(int step)
{
if(_steps.empty()) return 0;
// to generalize
if(step < 0) return _steps[0]->getNumEntities();
return _steps[step]->getNumEntities();
}
int PViewDataGModel::getNumElements(int step, int ent)
{
if(_steps.empty()) return 0;
// to generalize
if(step < 0 && ent < 0) return _steps[0]->getModel()->getNumMeshElements();
if(step < 0) return _steps[0]->getEntity(ent)->getNumMeshElements();
if(ent < 0) return _steps[step]->getModel()->getNumMeshElements();
return _steps[step]->getEntity(ent)->getNumMeshElements();
}
int PViewDataGModel::getDimension(int step, int ent, int ele)
{
return _getElement(step, ent, ele)->getDim();
}
int PViewDataGModel::getNumNodes(int step, int ent, int ele)
{
MElement *e = _getElement(step, ent, ele);
if(_type == GaussPointData){
return _steps[step]->getGaussPoints(e->getTypeForMSH()).size() / 3;
}
else{
if(isAdaptive())
return e->getNumVertices();
else
return e->getNumPrimaryVertices();
}
}
int PViewDataGModel::getNode(int step, int ent, int ele, int nod,
double &x, double &y, double &z)
{
MElement *e = _getElement(step, ent, ele);
if(_type == GaussPointData){
std::vector<double> &p(_steps[step]->getGaussPoints(e->getTypeForMSH()));
if(p[0] == 1.e22){
// hack: the points are the element vertices
x = e->getVertex(nod)->x();
y = e->getVertex(nod)->y();
z = e->getVertex(nod)->z();
}
else{
double vx[8], vy[8], vz[8];
for(int i = 0; i < e->getNumPrimaryVertices(); i++){
vx[i] = e->getVertex(i)->x();
vy[i] = e->getVertex(i)->y();
vz[i] = e->getVertex(i)->z();
}
x = e->interpolate(vx, p[3 * nod], p[3 * nod + 1], p[3 * nod + 2], 1, 1);
y = e->interpolate(vy, p[3 * nod], p[3 * nod + 1], p[3 * nod + 2], 1, 1);
z = e->interpolate(vz, p[3 * nod], p[3 * nod + 1], p[3 * nod + 2], 1, 1);
}
return 0;
}
else{
MVertex *v = e->getVertex(nod);
x = v->x();
y = v->y();
z = v->z();
return v->getIndex();
}
}
void PViewDataGModel::setNode(int step, int ent, int ele, int nod,
double x, double y, double z)
{
MVertex *v = _getElement(step, ent, ele)->getVertex(nod);
v->x() = x;
v->y() = y;
v->z() = z;
}
void PViewDataGModel::tagNode(int step, int ent, int ele, int nod, int tag)
{
MVertex *v = _getElement(step, ent, ele)->getVertex(nod);
v->setIndex(tag);
}
int PViewDataGModel::getNumComponents(int step, int ent, int ele)
{
return _steps[step]->getNumComponents();
}
int PViewDataGModel::getNumValues(int step, int ent, int ele)
{
if(_type == ElementNodeData || _type == NodeData){
return getNumNodes(step, ent, ele) * getNumComponents(step, ent, ele);
}
else if(_type == ElementData){
return getNumComponents(step, ent, ele);
}
else{
Msg::Error("getNumValue() should not be used on this type of view");
return getNumComponents(step, ent, ele);
}
}
void PViewDataGModel::getValue(int step, int ent, int ele, int idx, double &val)
{
MElement *e = _getElement(step, ent, ele);
if(_type == ElementNodeData || _type == ElementData){
val = _steps[step]->getData(e->getNum())[idx];
}
else if(_type == NodeData){
int numcomp = _steps[step]->getNumComponents();
int nod = idx / numcomp;
int comp = idx % numcomp;
val = _steps[step]->getData(e->getVertex(nod)->getNum())[comp];
}
else{
Msg::Error("getValue(index) should not be used on this type of view");
}
}
void PViewDataGModel::getValue(int step, int ent, int ele, int nod, int comp, double &val)
{
MElement *e = _getElement(step, ent, ele);
switch(_type){
case NodeData:
val = _steps[step]->getData(e->getVertex(nod)->getNum())[comp];
break;
case ElementNodeData:
case GaussPointData:
val = _steps[step]->getData(e->getNum())[_steps[step]->getNumComponents() * nod + comp];
break;
case ElementData:
default:
val = _steps[step]->getData(e->getNum())[comp];
break;
}
}
void PViewDataGModel::setValue(int step, int ent, int ele, int nod, int comp, double val)
{
MElement *e = _getElement(step, ent, ele);
switch(_type){
case NodeData:
_steps[step]->getData(e->getVertex(nod)->getNum())[comp] = val;
break;
case ElementNodeData:
case GaussPointData:
_steps[step]->getData(e->getNum())[_steps[step]->getNumComponents() * nod + comp] = val;
break;
case ElementData:
default:
_steps[step]->getData(e->getNum())[comp] = val;
break;
}
}
int PViewDataGModel::getNumEdges(int step, int ent, int ele)
{
return _getElement(step, ent, ele)->getNumEdges();
}
int PViewDataGModel::getType(int step, int ent, int ele)
{
return _getElement(step, ent, ele)->getType();
}
void PViewDataGModel::revertElement(int step, int ent, int ele)
{
if(!step) _getElement(step, ent, ele)->revert();
}
void PViewDataGModel::smooth()
{
if(_type == NodeData || _type == GaussPointData) return;
std::vector<stepData<double>*> _steps2;
for(unsigned int step = 0; step < _steps.size(); step++){
GModel *m = _steps[step]->getModel();
int numComp = _steps[step]->getNumComponents();
_steps2.push_back(new stepData<double>(m, numComp, _steps[step]->getFileName(),
_steps[step]->getFileIndex()));
std::map<int, int> nodeConnect;
for(int ent = 0; ent < getNumEntities(step); ent++){
for(int ele = 0; ele < getNumElements(step, ent); ele++){
MElement *e = _steps[step]->getEntity(ent)->getMeshElement(ele);
double val;
if(!getValueByIndex(step, e->getNum(), 0, 0, val)) continue;
for(int nod = 0; nod < e->getNumVertices(); nod++){
MVertex *v = e->getVertex(nod);
if(nodeConnect.count(v->getNum()))
nodeConnect[v->getNum()]++;
else
nodeConnect[v->getNum()] = 1;
double *d = _steps2.back()->getData(v->getNum(), true);
for(int j = 0; j < numComp; j++)
if(getValueByIndex(step, e->getNum(), nod, j, val)) d[j] += val;
}
}
}
for(int i = 0; i < _steps2.back()->getNumData(); i++){
double *d = _steps2.back()->getData(i);
if(d){
double f = nodeConnect[i];
if(f) for(int j = 0; j < numComp; j++) d[j] /= f;
}
}
}
for(unsigned int i = 0; i < _steps.size(); i++) delete _steps[i];
_steps = _steps2;
_type = NodeData;
finalize();
}
bool PViewDataGModel::skipEntity(int step, int ent)
{
if(step >= getNumTimeSteps()) return true;
return !_steps[step]->getEntity(ent)->getVisibility();
}
bool PViewDataGModel::skipElement(int step, int ent, int ele, bool checkVisibility)
{
if(step >= getNumTimeSteps()) return true;
stepData<double> *sd = _steps[step];
if(!_steps[step]->getNumData()) return true;
MElement *e = _getElement(step, ent, ele);
if(checkVisibility && !e->getVisibility()) return true;
if(_type == NodeData){
for(int i = 0; i < e->getNumVertices(); i++)
if(!sd->getData(e->getVertex(i)->getNum())) return true;
}
else{
if(!sd->getData(e->getNum())) return true;
}
return false;
}
bool PViewDataGModel::hasTimeStep(int step)
{
if(step < getNumTimeSteps() && _steps[step]->getNumData()) return true;
return false;
}
bool PViewDataGModel::hasPartition(int part)
{
return _partitions.find(part) != _partitions.end();
}
bool PViewDataGModel::hasMultipleMeshes()
{
if(_steps.size() <= 1) return false;
GModel *m = _steps[0]->getModel();
for(unsigned int i = 1; i < _steps.size(); i++)
if(m != _steps[i]->getModel()) return true;
return false;
}
bool PViewDataGModel::hasModel(GModel *model, int step)
{
if(step < 0){
for(unsigned int i = 0; i < _steps.size(); i++)
if(model == _steps[i]->getModel()) return true;
return false;
}
return (model == _steps[step]->getModel());
}
GEntity *PViewDataGModel::getEntity(int step, int ent)
{
return _steps[step]->getEntity(ent);
}
bool PViewDataGModel::getValueByIndex(int step, int dataIndex, int nod, int comp, double &val)
{
double *d = _steps[step]->getData(dataIndex);
if(!d) return false;
if(_type == NodeData || _type == ElementData)
val = d[comp];
else
val = d[_steps[step]->getNumComponents() * nod + comp];
return true;
}