Skip to content
Snippets Groups Projects
Commit a65e992c authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

more efficient implementation of stepData (reduce memory + more flexible w.r.t

selective loading of steps)
parent bf40f116
Branches
Tags
No related merge requests found
// $Id: PViewDataGModel.cpp,v 1.26 2008-03-12 21:28:53 geuzaine Exp $ // $Id: PViewDataGModel.cpp,v 1.27 2008-03-13 22:02:08 geuzaine Exp $
// //
// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
// //
...@@ -41,8 +41,8 @@ PViewDataGModel::PViewDataGModel(GModel *model) ...@@ -41,8 +41,8 @@ PViewDataGModel::PViewDataGModel(GModel *model)
PViewDataGModel::~PViewDataGModel() PViewDataGModel::~PViewDataGModel()
{ {
for(unsigned int i = 0; i < _nodeData.size(); i++) for(unsigned int i = 0; i < _nodeData.size(); i++) delete _nodeData[i];
if(_nodeData[i]) delete _nodeData[i]; for(unsigned int i = 0; i < _elementData.size(); i++) delete _elementData[i];
} }
bool PViewDataGModel::finalize() bool PViewDataGModel::finalize()
...@@ -50,10 +50,8 @@ bool PViewDataGModel::finalize() ...@@ -50,10 +50,8 @@ bool PViewDataGModel::finalize()
_min = VAL_INF; _min = VAL_INF;
_max = -VAL_INF; _max = -VAL_INF;
for(unsigned int i = 0; i < _nodeData.size(); i++){ for(unsigned int i = 0; i < _nodeData.size(); i++){
if(_nodeData[i]){ _min = std::min(_min, _nodeData[i]->getMin());
_min = std::min(_min, _nodeData[i]->min); _max = std::max(_max, _nodeData[i]->getMax());
_max = std::max(_max, _nodeData[i]->max);
}
} }
setDirty(false); setDirty(false);
return true; return true;
...@@ -66,22 +64,22 @@ int PViewDataGModel::getNumTimeSteps() ...@@ -66,22 +64,22 @@ int PViewDataGModel::getNumTimeSteps()
double PViewDataGModel::getTime(int step) double PViewDataGModel::getTime(int step)
{ {
if(step < (int)_nodeData.size() && _nodeData[step]) if(step < (int)_nodeData.size())
return _nodeData[step]->time; return _nodeData[step]->getTime();
return 0.; return 0.;
} }
double PViewDataGModel::getMin(int step) double PViewDataGModel::getMin(int step)
{ {
if(step < 0) return _min; if(step < 0) return _min;
if(step < (int)_nodeData.size() && _nodeData[step]) return _nodeData[step]->min; if(step < (int)_nodeData.size()) return _nodeData[step]->getMin();
return 0.; return 0.;
} }
double PViewDataGModel::getMax(int step) double PViewDataGModel::getMax(int step)
{ {
if(step < 0) return _max; if(step < 0) return _max;
if(step < (int)_nodeData.size() && _nodeData[step]) return _nodeData[step]->max; if(step < (int)_nodeData.size()) return _nodeData[step]->getMax();
return 0.; return 0.;
} }
...@@ -116,18 +114,16 @@ void PViewDataGModel::getNode(int ent, int ele, int nod, double &x, double &y, d ...@@ -116,18 +114,16 @@ void PViewDataGModel::getNode(int ent, int ele, int nod, double &x, double &y, d
int PViewDataGModel::getNumComponents(int ent, int ele, int step) int PViewDataGModel::getNumComponents(int ent, int ele, int step)
{ {
MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(0); // no range check here: we assume this is guarded by skipElement()
int index = v->getDataIndex(); return _nodeData[step]->getNumComp();
// no range check here: we assume this call is guarded by skipElement()
return _nodeData[step]->values[index].size();
} }
void PViewDataGModel::getValue(int ent, int ele, int nod, int comp, int step, double &val) void PViewDataGModel::getValue(int ent, int ele, int nod, int comp, int step, double &val)
{ {
MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(nod); MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(nod);
int index = v->getDataIndex(); int index = v->getDataIndex();
// no range check here: we assume this call is guarded by skipElement() // no range check here: we assume this is guarded by skipElement()
val = _nodeData[step]->values[index][comp]; val = _nodeData[step]->getData(index)[comp];
} }
int PViewDataGModel::getNumEdges(int ent, int ele) int PViewDataGModel::getNumEdges(int ent, int ele)
...@@ -142,21 +138,21 @@ bool PViewDataGModel::skipEntity(int ent) ...@@ -142,21 +138,21 @@ bool PViewDataGModel::skipEntity(int ent)
bool PViewDataGModel::skipElement(int ent, int ele, int step) bool PViewDataGModel::skipElement(int ent, int ele, int step)
{ {
if(step >= (int)_nodeData.size() || !_nodeData[step]) return true; if(step >= (int)_nodeData.size() || !_nodeData[step]->getNumData()) return true;
MElement *e = _entities[ent]->getMeshElement(ele); MElement *e = _entities[ent]->getMeshElement(ele);
if(!e->getVisibility()) return true; if(!e->getVisibility()) return true;
for(int i = 0; i < e->getNumVertices(); i++){ for(int i = 0; i < e->getNumVertices(); i++){
int index = e->getVertex(i)->getDataIndex(); int index = e->getVertex(i)->getDataIndex();
if(index < 0 || index >= (int)_nodeData[step]->values.size()) return true; if(index < 0 || index >= (int)_nodeData[step]->getNumData()) return true;
if(_nodeData[step]->values[index].empty()) return true; if(!_nodeData[step]->getData(index)) return true;
} }
return false; return false;
} }
bool PViewDataGModel::hasTimeStep(int step) bool PViewDataGModel::hasTimeStep(int step)
{ {
if(step < (int)_nodeData.size() && _nodeData[step]) return true; if(step < (int)_nodeData.size() && _nodeData[step]->getNumData()) return true;
if(step < (int)_elementData.size() && _elementData[step]) return true; if(step < (int)_elementData.size() && _elementData[step]->getNumData()) return true;
return false; return false;
} }
......
...@@ -27,17 +27,62 @@ ...@@ -27,17 +27,62 @@
template<class real> template<class real>
class stepData{ class stepData{
public: private:
// the file the data was read from // the file the data was read from
std::string fileName; std::string _fileName;
// the index in the file // the index in the file
int fileIndex; int _fileIndex;
// the value of the time step and associated min/max // the value of the time step and value min/max
double time, min, max; double _time, _min, _max;
// the vector of data, indexed by dataIndex // the number of components in the data (stepData only contain a
std::vector<std::vector<real> > values; // single field type!)
stepData() : fileIndex(-1), time(0.), min(VAL_INF), max(-VAL_INF){} int _numComp;
~stepData() {} // the values, indexed by dataIndex in MVertex or MElement
std::vector<real*> *_data;
public:
stepData(int numComp, std::string fileName="", int fileIndex=-1, double time=0.,
double min=VAL_INF, double max=-VAL_INF)
: _numComp(numComp), _fileName(fileName), _fileIndex(fileIndex), _time(time),
_min(min), _max(max), _data(0)
{
}
~stepData(){ destroyData(); }
int getNumComp(){ return _numComp; }
std::string getFileName(){ return _fileName; }
void setFileName(std::string name){ _fileName = name; }
int getFileIndex(){ return _fileIndex; }
void setFileIndex(int index){ _fileIndex = index; }
double getTime(){ return _time; }
void setTime(double time){ _time = time; }
double getMin(){ return _min; }
void setMin(double min ){ _min = min; }
double getMax(){ return _max; }
void setMax(double max){ _max = max; }
int getNumData()
{
if(!_data) return 0;
return _data->size();
}
void resizeData(int n)
{
if(!_data) _data = new std::vector<real*>(n, (real*)0);
if(n < _data->size()) _data->resize(n, (real*)0);
}
real *getData(int index, bool allocIfNeeded=false)
{
if(!_data || index >= _data->size()) resizeData(index + 100); // optimize this
if(allocIfNeeded && !(*_data)[index]) (*_data)[index] = new real[_numComp];
return (*_data)[index];
}
void destroyData()
{
if(_data){
for(unsigned int i = 0; i < _data->size(); i++)
if((*_data)[i]) delete [] (*_data)[i];
delete _data;
}
_data = 0;
}
}; };
// data container using elements from a GModel // data container using elements from a GModel
......
// $Id: PViewDataGModelIO.cpp,v 1.7 2008-03-12 21:28:53 geuzaine Exp $ // $Id: PViewDataGModelIO.cpp,v 1.8 2008-03-13 22:02:08 geuzaine Exp $
// //
// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
// //
...@@ -29,18 +29,6 @@ ...@@ -29,18 +29,6 @@
#include "Numeric.h" #include "Numeric.h"
#include "StringUtils.h" #include "StringUtils.h"
// Todo: slightly change this as follows:
// - always populate the _dataXX vector with stepData (for all time steps)
// - make the actual data allocatable (e.g. ptr to vector<vector>>)
// - only alloc data if...
// - e.g. only alloc data for first time step
// in "skipElement": if no data, read it from file (using fileName/Index info
// in stepData) and free another if...
//
// usage should be as simple as: "gmsh *.pos". This would not load all
// time steps by default: only the 1st one(s). Then load/cache the
// others as needed on the fly.
bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp, bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp,
bool binary, bool swap, int timeStep, double time, bool binary, bool swap, int timeStep, double time,
int partition, int numComp, int numNodes) int partition, int numComp, int numNodes)
...@@ -48,16 +36,20 @@ bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp, ...@@ -48,16 +36,20 @@ bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp,
Msg(INFO, "Reading step %d (time %g) partition %d: %d nodes", Msg(INFO, "Reading step %d (time %g) partition %d: %d nodes",
timeStep, time, partition, numNodes); timeStep, time, partition, numNodes);
while(timeStep >= (int)_nodeData.size()) _nodeData.push_back(0); while(timeStep >= (int)_nodeData.size())
_nodeData.push_back(new stepData<double>(numComp));
if(!_nodeData[timeStep]) _nodeData[timeStep] = new stepData<double>();
_nodeData[timeStep]->setFileName(fileName);
_nodeData[timeStep]->setFileIndex(fileIndex);
_nodeData[timeStep]->setTime(time);
_nodeData[timeStep]->fileName = fileName; // if we already have maxSteps for this view, return
_nodeData[timeStep]->fileIndex = fileIndex; int numSteps = 0, maxSteps = 1000000000;
_nodeData[timeStep]->time = time; for(unsigned int i = 0; i < _nodeData.size(); i++)
_nodeData[timeStep]->values.resize(numNodes); numSteps += _nodeData[i]->getNumData() ? 1 : 0;
if(numSteps > maxSteps) return true;
std::vector<double> tmp(numComp, 0.); _nodeData[timeStep]->resizeData(numNodes);
for(int i = 0; i < numNodes; i++){ for(int i = 0; i < numNodes; i++){
int num; int num;
...@@ -79,21 +71,18 @@ bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp, ...@@ -79,21 +71,18 @@ bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp,
v->setDataIndex(max + 1); v->setDataIndex(max + 1);
} }
int index = v->getDataIndex(); int index = v->getDataIndex();
if(index >= (int)_nodeData[timeStep]->values.size()) double *d = _nodeData[timeStep]->getData(index, true);
_nodeData[timeStep]->values.resize(index + 100); // optimize this
if(binary){ if(binary){
if((int)fread(&tmp[0], sizeof(double), numComp, fp) != numComp) return false; if((int)fread(d, sizeof(double), numComp, fp) != numComp) return false;
if(swap) swapBytes((char*)&tmp[0], sizeof(double), numComp); if(swap) swapBytes((char*)d, sizeof(double), numComp);
} }
else{ else{
for(int j = 0; j < numComp; j++) for(int j = 0; j < numComp; j++)
if(fscanf(fp, "%lf", &tmp[j]) != 1) return false; if(fscanf(fp, "%lf", &d[j]) != 1) return false;
} }
for(int j = 0; j < numComp; j++) double s = ComputeScalarRep(numComp, d);
_nodeData[timeStep]->values[index].push_back(tmp[j]); _nodeData[timeStep]->setMin(std::min(_nodeData[timeStep]->getMin(), s));
double s = ComputeScalarRep(numComp, &_nodeData[timeStep]->values[index][0]); _nodeData[timeStep]->setMax(std::max(_nodeData[timeStep]->getMax(), s));
_nodeData[timeStep]->min = std::min(_nodeData[timeStep]->min, s);
_nodeData[timeStep]->max = std::max(_nodeData[timeStep]->max, s);
} }
_partitions.insert(partition); _partitions.insert(partition);
...@@ -125,29 +114,25 @@ bool PViewDataGModel::writeMSH(std::string name, bool binary) ...@@ -125,29 +114,25 @@ bool PViewDataGModel::writeMSH(std::string name, bool binary)
} }
} }
for(unsigned int ts = 0; ts < _nodeData.size(); ts++){ for(unsigned int step = 0; step < _nodeData.size(); step++){
if(!_nodeData[ts]) continue; int numNodes = 0, numComp = _nodeData[step]->getNumComp();
int numNodes = 0, numComp = 100; for(unsigned int i = 0; i < _nodeData[step]->getNumData(); i++)
for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){ if(_nodeData[step]->getData(i)) numNodes++;
if(_nodeData[ts]->values[i].size()){ if(numNodes){
numComp = std::min(numComp, (int)_nodeData[ts]->values[i].size());
numNodes++;
}
}
if(numNodes && numComp){
fprintf(fp, "$NodeData\n"); fprintf(fp, "$NodeData\n");
fprintf(fp, "\"%s\"\n", getName().c_str()); fprintf(fp, "\"%s\"\n", getName().c_str());
fprintf(fp, "%d %.16g 0 0 %d %d\n", ts, _nodeData[ts]->time, numComp, numNodes); fprintf(fp, "%d %.16g 0 0 %d %d\n", step, _nodeData[step]->getTime(),
for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){ numComp, numNodes);
if((int)_nodeData[ts]->values[i].size() >= numComp){ for(unsigned int i = 0; i < _nodeData[step]->getNumData(); i++){
if(_nodeData[step]->getData(i)){
if(binary){ if(binary){
fwrite(&tags[i], sizeof(int), 1, fp); fwrite(&tags[i], sizeof(int), 1, fp);
fwrite(&_nodeData[ts]->values[i][0], sizeof(double), numComp, fp); fwrite(_nodeData[step]->getData(i), sizeof(double), numComp, fp);
} }
else{ else{
fprintf(fp, "%d", tags[i]); fprintf(fp, "%d", tags[i]);
for(int k = 0; k < numComp; k++) for(int k = 0; k < numComp; k++)
fprintf(fp, " %.16g", _nodeData[ts]->values[i][k]); fprintf(fp, " %.16g", _nodeData[step]->getData(i)[k]);
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment