From 6af628b3dfdddd279aaa29862925ef69abf8c230 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Wed, 16 Oct 2013 19:45:55 +0000 Subject: [PATCH] new PostProcessing.ForceNodeData to force saving NodeData datasets, even for potentially discontinuous list-type datasets --- Common/Context.h | 2 +- Common/DefaultOptions.h | 3 + Common/Options.cpp | 7 ++ Common/Options.h | 1 + Post/PViewData.h | 5 +- Post/PViewDataGModel.h | 3 +- Post/PViewDataGModelIO.cpp | 11 +-- Post/PViewDataIO.cpp | 4 +- Post/PViewDataList.h | 3 +- Post/PViewDataListIO.cpp | 140 ++++++++++++++++++++++++------------- Post/PViewIO.cpp | 6 +- doc/texinfo/opt_post.texi | 5 ++ doc/texinfo/opt_view.texi | 2 +- 13 files changed, 131 insertions(+), 61 deletions(-) diff --git a/Common/Context.h b/Common/Context.h index 2c21f2c4ee..14337412ec 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -229,7 +229,7 @@ class CTX { struct{ int draw, link, horizontalScales; int smooth, animCycle, animStep, combineTime, combineRemoveOrig; - int fileFormat, plugins; + int fileFormat, plugins, forceNodeData; double animDelay; }post; // solver options diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 2b131522be..a54ea64ec1 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1226,6 +1226,9 @@ StringXNumber PostProcessingOptions_Number[] = { { F|O, "CombineRemoveOriginal" , opt_post_combine_remove_orig , 1. , "Remove original views after a Combine operation" }, + { F|O, "ForceNodeData" , opt_post_force_node_data , 0. , + "Try to force saving datasets as NodeData" }, + { F|O, "Format" , opt_post_file_format , 10. , "Default file format for post-processing views (0=ASCII view, 1=binary " "view, 2=parsed view, 3=STL triangulation, 4=raw text, 5=Gmsh mesh, 6=MED file, " diff --git a/Common/Options.cpp b/Common/Options.cpp index f980418be9..378842645f 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -6293,6 +6293,13 @@ double opt_post_file_format(OPT_ARGS_NUM) return CTX::instance()->post.fileFormat; } +double opt_post_force_node_data(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->post.forceNodeData = (int)val; + return CTX::instance()->post.forceNodeData; +} + double opt_view_nb_timestep(OPT_ARGS_NUM) { #if defined(HAVE_POST) diff --git a/Common/Options.h b/Common/Options.h index 1007a85cad..7829fa9b84 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -519,6 +519,7 @@ double opt_post_combine_remove_orig(OPT_ARGS_NUM); double opt_post_plugins(OPT_ARGS_NUM); double opt_post_nb_views(OPT_ARGS_NUM); double opt_post_file_format(OPT_ARGS_NUM); +double opt_post_force_node_data(OPT_ARGS_NUM); double opt_view_nb_timestep(OPT_ARGS_NUM); double opt_view_nb_non_empty_timestep(OPT_ARGS_NUM); double opt_view_timestep(OPT_ARGS_NUM); diff --git a/Post/PViewData.h b/Post/PViewData.h index b572b48328..a4ef4f1bb3 100644 --- a/Post/PViewData.h +++ b/Post/PViewData.h @@ -270,8 +270,9 @@ class PViewData { virtual bool writePOS(const std::string &fileName, bool binary=false, bool parsed=true, bool append=false); virtual bool writeMSH(const std::string &fileName, double version=2.2, bool binary=false, - bool savemesh=true, bool multipleView=false, - int partitionNum=0, bool saveInterpolationMatrices=true); + bool saveMesh=true, bool multipleView=false, + int partitionNum=0, bool saveInterpolationMatrices=true, + bool forceNodeData=false); virtual bool writeMED(const std::string &fileName); virtual bool toVector(std::vector<std::vector<double> > &vec); virtual bool fromVector(const std::vector<std::vector<double> > &vec); diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h index 8eab94d303..e1d94fdfe8 100644 --- a/Post/PViewDataGModel.h +++ b/Post/PViewDataGModel.h @@ -251,7 +251,8 @@ class PViewDataGModel : public PViewData { const std::string &interpolationScheme); virtual bool writeMSH(const std::string &fileName, double version=2.2, bool binary=false, bool savemesh=true, bool multipleView=false, - int partitionNum=0, bool saveInterpolationMatrices=true); + int partitionNum=0, bool saveInterpolationMatrices=true, + bool forceNodeData=false); bool readMED(const std::string &fileName, int fileIndex); bool writeMED(const std::string &fileName); }; diff --git a/Post/PViewDataGModelIO.cpp b/Post/PViewDataGModelIO.cpp index 6efae75ded..acfc0df79f 100644 --- a/Post/PViewDataGModelIO.cpp +++ b/Post/PViewDataGModelIO.cpp @@ -133,8 +133,8 @@ bool PViewDataGModel::readMSH(const std::string &viewName, const std::string &fi } bool PViewDataGModel::writeMSH(const std::string &fileName, double version, bool binary, - bool savemesh, bool multipleView, int partitionNum, - bool saveInterpolationMatrices) + bool saveMesh, bool multipleView, int partitionNum, + bool saveInterpolationMatrices, bool forceNodeData) { if(_steps.empty()) return true; @@ -143,11 +143,14 @@ bool PViewDataGModel::writeMSH(const std::string &fileName, double version, bool return false; } + if(forceNodeData && _type != NodeData){ + Msg::Warning("Cannot force NodeData for this dataset: saving native data"); + } + GModel *model = _steps[0]->getModel(); - bool writeNodesAndElements = savemesh; FILE *fp; - if(writeNodesAndElements){ + if(saveMesh){ if(!model->writeMSH(fileName, version, binary, false, false, 1.0, 0, 0, multipleView)) return false; // append data diff --git a/Post/PViewDataIO.cpp b/Post/PViewDataIO.cpp index 9e3eac75e8..bff69ef56c 100644 --- a/Post/PViewDataIO.cpp +++ b/Post/PViewDataIO.cpp @@ -179,8 +179,8 @@ bool PViewData::writePOS(const std::string &fileName, bool binary, bool parsed, } bool PViewData::writeMSH(const std::string &fileName, double version, bool binary, - bool savemesh, bool multipleView, int partitionNum, - bool saveInterpolationMatrices) + bool saveMesh, bool multipleView, int partitionNum, + bool saveInterpolationMatrices, bool forceNodeData) { Msg::Error("MSH export not implemented for this view type"); return false; diff --git a/Post/PViewDataList.h b/Post/PViewDataList.h index 5b2dd2abb1..dd2d763a29 100644 --- a/Post/PViewDataList.h +++ b/Post/PViewDataList.h @@ -128,7 +128,8 @@ class PViewDataList : public PViewData { bool append=false); virtual bool writeMSH(const std::string &fileName, double version=2.2, bool binary=false, bool savemesh=true, bool multipleView=false, - int partitionNum=0, bool saveInterpolationMatrices=true); + int partitionNum=0, bool saveInterpolationMatrices=true, + bool forceNodeData=false); virtual void importLists(int N[24], std::vector<double> *V[24]); virtual void getListPointers(int N[24], std::vector<double> *V[24]); }; diff --git a/Post/PViewDataListIO.cpp b/Post/PViewDataListIO.cpp index 6ad08a7f14..03dda33b1c 100644 --- a/Post/PViewDataListIO.cpp +++ b/Post/PViewDataListIO.cpp @@ -450,9 +450,21 @@ static void createVertices(std::vector<double> &list, int nbelm, int nbnod, } } +class nodeData{ +public: + int nbnod; + int nod; + double *data; + nodeData() + : nbnod(0), nod(0), data(0) {} + nodeData(int _nbnod, int _nod, double *_data) + : nbnod(_nbnod), nod(_nod), data(_data) {} +}; + static void createElements(std::vector<double> &list, int nbelm, int nbnod, MVertexPositionSet &pos, std::vector<MElement*> &elements, - double eps, int type) + double eps, int type, + std::map<MVertex*, nodeData> *vertexData) { if(!nbelm) return; int t = 0; @@ -519,16 +531,20 @@ static void createElements(std::vector<double> &list, int nbelm, int nbnod, double *y = &list[i + nbnod]; double *z = &list[i + 2 * nbnod]; std::vector<MVertex*> verts(nbnod); - for(int j = 0; j < nbnod; j++) + for(int j = 0; j < nbnod; j++){ verts[j] = pos.find(x[j], y[j], z[j], eps); + if(vertexData) + (*vertexData)[verts[j]] = nodeData(nbnod, j, &list[i + 3 * nbnod]); + } MElement *e = factory.create(t, verts); elements.push_back(e); } } bool PViewDataList::writeMSH(const std::string &fileName, double version, bool binary, - bool savemesh, bool multipleView, - int partitionNum, bool saveInterpolationMatrices) + bool saveMesh, bool multipleView, + int partitionNum, bool saveInterpolationMatrices, + bool forceNodeData) { if(_adaptive){ Msg::Warning("Writing adapted dataset (will only export current time step)"); @@ -557,39 +573,45 @@ bool PViewDataList::writeMSH(const std::string &fileName, double version, bool b } MVertexPositionSet pos(vertices); + std::map<MVertex *, nodeData> vertexData; + for(int i = 0; i < 24; i++){ std::vector<double> *list = 0; int *numEle = 0, numComp, numNodes; int typ = _getRawData(i, &list, &numEle, &numComp, &numNodes); - createElements(*list, *numEle, numNodes, pos, elements, eps, typ); + createElements(*list, *numEle, numNodes, pos, elements, eps, typ, + forceNodeData ? &vertexData : 0); } - int num = 0; + int globalNumNodes = 0; for(unsigned int i = 0; i < vertices.size(); i++) if(vertices[i]->getIndex() < 0) - vertices[i]->setIndex(++num); + vertices[i]->setIndex(++globalNumNodes); fprintf(fp, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"); - fprintf(fp, "$Nodes\n"); - fprintf(fp, "%d\n", num); - for(unsigned int i = 0; i < vertices.size(); i++){ - MVertex *v = vertices[i]; - if(v->getIndex() > 0) - fprintf(fp, "%d %.16g %.16g %.16g\n", v->getIndex(), v->x(), v->y(), v->z()); - } - fprintf(fp, "$EndNodes\n"); - - fprintf(fp, "$Elements\n"); - fprintf(fp, "%d\n", (int)elements.size()); - for(unsigned int i = 0; i < elements.size(); i++){ - if(version > 2.2) - Msg::Warning("Unable to write file in version '%g': using version 2.2", - version); - elements[i]->writeMSH2(fp, 2.2, false, i + 1); - } - fprintf(fp, "$EndElements\n"); - - if(saveInterpolationMatrices && haveInterpolationMatrices()){ + + if(saveMesh){ + fprintf(fp, "$Nodes\n"); + fprintf(fp, "%d\n", globalNumNodes); + for(unsigned int i = 0; i < vertices.size(); i++){ + MVertex *v = vertices[i]; + if(v->getIndex() > 0) + fprintf(fp, "%d %.16g %.16g %.16g\n", v->getIndex(), v->x(), v->y(), v->z()); + } + fprintf(fp, "$EndNodes\n"); + + fprintf(fp, "$Elements\n"); + fprintf(fp, "%d\n", (int)elements.size()); + for(unsigned int i = 0; i < elements.size(); i++){ + if(version > 2.2) + Msg::Warning("Unable to write file in version '%g': using version 2.2", + version); + elements[i]->writeMSH2(fp, 2.2, false, i + 1); + } + fprintf(fp, "$EndElements\n"); + } + + if(saveInterpolationMatrices && haveInterpolationMatrices() && !forceNodeData){ fprintf(fp, "$InterpolationScheme\n"); fprintf(fp, "\"INTERPOLATION_SCHEME\"\n"); fprintf(fp, "%d\n", (int)_interpolation.size()); @@ -612,37 +634,61 @@ bool PViewDataList::writeMSH(const std::string &fileName, double version, bool b } for(int ts = 0; ts < NbTimeStep; ts++){ - fprintf(fp, "$ElementNodeData\n"); - if(saveInterpolationMatrices && haveInterpolationMatrices()) + if(forceNodeData) + fprintf(fp, "$NodeData\n"); + else + fprintf(fp, "$ElementNodeData\n"); + if(saveInterpolationMatrices && haveInterpolationMatrices() && !forceNodeData) fprintf(fp, "2\n\"%s\"\n\"INTERPOLATION_SCHEME\"\n", getName().c_str()); else fprintf(fp, "1\n\"%s\"\n", getName().c_str()); fprintf(fp, "1\n%.16g\n", getTime(ts)); + int size = forceNodeData ? globalNumNodes : (int)elements.size(); if(partitionNum) - fprintf(fp, "4\n%d\n%d\n%d\n%d\n", ts, numComponents, (int)elements.size(), + fprintf(fp, "4\n%d\n%d\n%d\n%d\n", ts, numComponents, size, partitionNum); else - fprintf(fp, "3\n%d\n%d\n%d\n", ts, numComponents, (int)elements.size()); - num = 0; - for(int i = 0; i < 24; i++){ - std::vector<double> *list = 0; - int *numEle = 0, numComp, numNodes; - int typ = _getRawData(i, &list, &numEle, &numComp, &numNodes); - if(*numEle){ - int mult = numNodes; - if(_interpolation.count(typ)) - mult = _interpolation[typ][0]->size1(); - int nb = list->size() / *numEle; - for(unsigned int i = 0; i < list->size(); i += nb){ - double *v = &(*list)[i + 3 * numNodes]; - fprintf(fp, "%d %d", ++num, mult); - for(int j = 0; j < numComponents * mult; j++) - fprintf(fp, " %.16g", v[numComponents * mult * ts + j]); + fprintf(fp, "3\n%d\n%d\n%d\n", ts, numComponents, size); + + if(forceNodeData){ + for(unsigned int i = 0; i < vertices.size(); i++){ + MVertex *v = vertices[i]; + if(v->getIndex() > 0){ + fprintf(fp, "%d", v->getIndex()); + int nbnod = vertexData[v].nbnod; + int nod = vertexData[v].nod; + double *d = vertexData[v].data; + for(int j = 0; j < numComponents; j++) + fprintf(fp, " %.16g", + d[numComponents * nbnod * ts + numComponents * nod + j]); fprintf(fp, "\n"); } } + fprintf(fp, "$EndNodeData\n"); + } + else{ + int num = 0; + for(int i = 0; i < 24; i++){ + std::vector<double> *list = 0; + int *numEle = 0, numComp, numNodes; + int typ = _getRawData(i, &list, &numEle, &numComp, &numNodes); + if(*numEle){ + int mult = numNodes; + if(_interpolation.count(typ)) + mult = _interpolation[typ][0]->size1(); + int nb = list->size() / *numEle; + for(unsigned int i = 0; i < list->size(); i += nb){ + double *v = &(*list)[i + 3 * numNodes]; + fprintf(fp, "%d %d", ++num, mult); + for(int j = 0; j < numComponents * mult; j++) + fprintf(fp, " %.16g", v[numComponents * mult * ts + j]); + fprintf(fp, "\n"); + } + } + } + fprintf(fp, "$EndElementNodeData\n"); } - fprintf(fp, "$EndElementNodeData\n"); + } fclose(fp); diff --git a/Post/PViewIO.cpp b/Post/PViewIO.cpp index df3e0edaee..c0f8f972ce 100644 --- a/Post/PViewIO.cpp +++ b/Post/PViewIO.cpp @@ -295,7 +295,8 @@ bool PView::write(const std::string &fileName, int format, bool append) case 3: ret = _data->writeSTL(fileName); break; case 4: ret = _data->writeTXT(fileName); break; case 5: ret = _data->writeMSH(fileName, CTX::instance()->mesh.mshFileVersion, - CTX::instance()->mesh.binary); break; + CTX::instance()->mesh.binary, true, false, + 0, true, CTX::instance()->post.forceNodeData); break; case 6: ret = _data->writeMED(fileName); break; case 10: { @@ -306,7 +307,8 @@ bool PView::write(const std::string &fileName, int format, bool append) ret = _data->writeSTL(fileName); else if(ext == ".msh") ret = _data->writeMSH(fileName, CTX::instance()->mesh.mshFileVersion, - CTX::instance()->mesh.binary); + CTX::instance()->mesh.binary, true, false, + 0, true, CTX::instance()->post.forceNodeData); else if(ext == ".med") ret = _data->writeMED(fileName); else diff --git a/doc/texinfo/opt_post.texi b/doc/texinfo/opt_post.texi index 0534f4c266..7a1b034137 100644 --- a/doc/texinfo/opt_post.texi +++ b/doc/texinfo/opt_post.texi @@ -24,6 +24,11 @@ Remove original views after a Combine operation@* Default value: @code{1}@* Saved in: @code{General.OptionsFileName} +@item PostProcessing.ForceNodeData +Try to force saving datasets as NodeData@* +Default value: @code{0}@* +Saved in: @code{General.OptionsFileName} + @item PostProcessing.Format Default file format for post-processing views (0=ASCII view, 1=binary view, 2=parsed view, 3=STL triangulation, 4=raw text, 5=Gmsh mesh, 6=MED file, 10=automatic)@* Default value: @code{10}@* diff --git a/doc/texinfo/opt_view.texi b/doc/texinfo/opt_view.texi index 81a5db1afd..f4d30b6676 100644 --- a/doc/texinfo/opt_view.texi +++ b/doc/texinfo/opt_view.texi @@ -216,7 +216,7 @@ Saved in: @code{General.OptionsFileName} @item View.CenterGlyphs Center glyphs (arrows, numbers, etc.)? (0=left, 1=centered, 2=right)@* -Default value: @code{0}@* +Default value: @code{1}@* Saved in: @code{General.OptionsFileName} @item View.Clip -- GitLab