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
//
......@@ -41,8 +41,8 @@ PViewDataGModel::PViewDataGModel(GModel *model)
PViewDataGModel::~PViewDataGModel()
{
for(unsigned int i = 0; i < _nodeData.size(); i++)
if(_nodeData[i]) delete _nodeData[i];
for(unsigned int i = 0; i < _nodeData.size(); i++) delete _nodeData[i];
for(unsigned int i = 0; i < _elementData.size(); i++) delete _elementData[i];
}
bool PViewDataGModel::finalize()
......@@ -50,10 +50,8 @@ bool PViewDataGModel::finalize()
_min = VAL_INF;
_max = -VAL_INF;
for(unsigned int i = 0; i < _nodeData.size(); i++){
if(_nodeData[i]){
_min = std::min(_min, _nodeData[i]->min);
_max = std::max(_max, _nodeData[i]->max);
}
_min = std::min(_min, _nodeData[i]->getMin());
_max = std::max(_max, _nodeData[i]->getMax());
}
setDirty(false);
return true;
......@@ -66,22 +64,22 @@ int PViewDataGModel::getNumTimeSteps()
double PViewDataGModel::getTime(int step)
{
if(step < (int)_nodeData.size() && _nodeData[step])
return _nodeData[step]->time;
if(step < (int)_nodeData.size())
return _nodeData[step]->getTime();
return 0.;
}
double PViewDataGModel::getMin(int step)
{
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.;
}
double PViewDataGModel::getMax(int step)
{
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.;
}
......@@ -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)
{
MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(0);
int index = v->getDataIndex();
// no range check here: we assume this call is guarded by skipElement()
return _nodeData[step]->values[index].size();
// no range check here: we assume this is guarded by skipElement()
return _nodeData[step]->getNumComp();
}
void PViewDataGModel::getValue(int ent, int ele, int nod, int comp, int step, double &val)
{
MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(nod);
int index = v->getDataIndex();
// no range check here: we assume this call is guarded by skipElement()
val = _nodeData[step]->values[index][comp];
// no range check here: we assume this is guarded by skipElement()
val = _nodeData[step]->getData(index)[comp];
}
int PViewDataGModel::getNumEdges(int ent, int ele)
......@@ -142,21 +138,21 @@ bool PViewDataGModel::skipEntity(int ent)
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);
if(!e->getVisibility()) return true;
for(int i = 0; i < e->getNumVertices(); i++){
int index = e->getVertex(i)->getDataIndex();
if(index < 0 || index >= (int)_nodeData[step]->values.size()) return true;
if(_nodeData[step]->values[index].empty()) return true;
if(index < 0 || index >= (int)_nodeData[step]->getNumData()) return true;
if(!_nodeData[step]->getData(index)) return true;
}
return false;
}
bool PViewDataGModel::hasTimeStep(int step)
{
if(step < (int)_nodeData.size() && _nodeData[step]) return true;
if(step < (int)_elementData.size() && _elementData[step]) return true;
if(step < (int)_nodeData.size() && _nodeData[step]->getNumData()) return true;
if(step < (int)_elementData.size() && _elementData[step]->getNumData()) return true;
return false;
}
......
......@@ -27,17 +27,62 @@
template<class real>
class stepData{
public:
private:
// the file the data was read from
std::string fileName;
std::string _fileName;
// the index in the file
int fileIndex;
// the value of the time step and associated min/max
double time, min, max;
// the vector of data, indexed by dataIndex
std::vector<std::vector<real> > values;
stepData() : fileIndex(-1), time(0.), min(VAL_INF), max(-VAL_INF){}
~stepData() {}
int _fileIndex;
// the value of the time step and value min/max
double _time, _min, _max;
// the number of components in the data (stepData only contain a
// single field type!)
int _numComp;
// 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
......
// $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
//
......@@ -29,18 +29,6 @@
#include "Numeric.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 binary, bool swap, int timeStep, double time,
int partition, int numComp, int numNodes)
......@@ -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",
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;
_nodeData[timeStep]->fileIndex = fileIndex;
_nodeData[timeStep]->time = time;
_nodeData[timeStep]->values.resize(numNodes);
// if we already have maxSteps for this view, return
int numSteps = 0, maxSteps = 1000000000;
for(unsigned int i = 0; i < _nodeData.size(); i++)
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++){
int num;
......@@ -79,21 +71,18 @@ bool PViewDataGModel::readMSH(std::string fileName, int fileIndex, FILE *fp,
v->setDataIndex(max + 1);
}
int index = v->getDataIndex();
if(index >= (int)_nodeData[timeStep]->values.size())
_nodeData[timeStep]->values.resize(index + 100); // optimize this
double *d = _nodeData[timeStep]->getData(index, true);
if(binary){
if((int)fread(&tmp[0], sizeof(double), numComp, fp) != numComp) return false;
if(swap) swapBytes((char*)&tmp[0], sizeof(double), numComp);
if((int)fread(d, sizeof(double), numComp, fp) != numComp) return false;
if(swap) swapBytes((char*)d, sizeof(double), numComp);
}
else{
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++)
_nodeData[timeStep]->values[index].push_back(tmp[j]);
double s = ComputeScalarRep(numComp, &_nodeData[timeStep]->values[index][0]);
_nodeData[timeStep]->min = std::min(_nodeData[timeStep]->min, s);
_nodeData[timeStep]->max = std::max(_nodeData[timeStep]->max, s);
double s = ComputeScalarRep(numComp, d);
_nodeData[timeStep]->setMin(std::min(_nodeData[timeStep]->getMin(), s));
_nodeData[timeStep]->setMax(std::max(_nodeData[timeStep]->getMax(), s));
}
_partitions.insert(partition);
......@@ -125,29 +114,25 @@ bool PViewDataGModel::writeMSH(std::string name, bool binary)
}
}
for(unsigned int ts = 0; ts < _nodeData.size(); ts++){
if(!_nodeData[ts]) continue;
int numNodes = 0, numComp = 100;
for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){
if(_nodeData[ts]->values[i].size()){
numComp = std::min(numComp, (int)_nodeData[ts]->values[i].size());
numNodes++;
}
}
if(numNodes && numComp){
for(unsigned int step = 0; step < _nodeData.size(); step++){
int numNodes = 0, numComp = _nodeData[step]->getNumComp();
for(unsigned int i = 0; i < _nodeData[step]->getNumData(); i++)
if(_nodeData[step]->getData(i)) numNodes++;
if(numNodes){
fprintf(fp, "$NodeData\n");
fprintf(fp, "\"%s\"\n", getName().c_str());
fprintf(fp, "%d %.16g 0 0 %d %d\n", ts, _nodeData[ts]->time, numComp, numNodes);
for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){
if((int)_nodeData[ts]->values[i].size() >= numComp){
fprintf(fp, "%d %.16g 0 0 %d %d\n", step, _nodeData[step]->getTime(),
numComp, numNodes);
for(unsigned int i = 0; i < _nodeData[step]->getNumData(); i++){
if(_nodeData[step]->getData(i)){
if(binary){
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{
fprintf(fp, "%d", tags[i]);
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");
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment