diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp index 86afd52ec3d0bf05e8925cdb39ae5ce73c8130e0..f75eb1c4712b8a264d15c9e5013993e7b222e04a 100644 --- a/Post/PViewDataGModel.cpp +++ b/Post/PViewDataGModel.cpp @@ -1,4 +1,4 @@ -// $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; } diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h index 4447e860c61354f312a4bbf5af013b860d2cd8d1..af4d2067719d676b26f6745b7b8106718aa8a302 100644 --- a/Post/PViewDataGModel.h +++ b/Post/PViewDataGModel.h @@ -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 diff --git a/Post/PViewDataGModelIO.cpp b/Post/PViewDataGModelIO.cpp index 7ad18cac200b1a0afc9eed4278dee4ebc9709c60..65e9d97b2c0896a34df3dfdc0a8886ebcde03349 100644 --- a/Post/PViewDataGModelIO.cpp +++ b/Post/PViewDataGModelIO.cpp @@ -1,4 +1,4 @@ -// $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); - - if(!_nodeData[timeStep]) _nodeData[timeStep] = new stepData<double>(); + while(timeStep >= (int)_nodeData.size()) + _nodeData.push_back(new stepData<double>(numComp)); + + _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"); } }