From 6216caddfac70cf02b29e51f0446cc48b4938631 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 10 May 2011 18:15:00 +0000
Subject: [PATCH] refined algorithm to set interpolation matrices for
 model-based views

---
 Post/PViewData.cpp       |   8 ++
 Post/PViewData.h         |   2 +-
 Post/PViewDataGModel.cpp | 177 +++++++++++++++++++++++++--------------
 Post/PViewDataGModel.h   |   2 -
 4 files changed, 123 insertions(+), 66 deletions(-)

diff --git a/Post/PViewData.cpp b/Post/PViewData.cpp
index 9263c9c1b3..dd56dc81ca 100644
--- a/Post/PViewData.cpp
+++ b/Post/PViewData.cpp
@@ -118,6 +118,14 @@ int PViewData::getInterpolationMatrices(int type, std::vector<fullMatrix<double>
   return 0;
 }
 
+bool PViewData::haveInterpolationMatrices(int type)
+{ 
+  if(!type) 
+    return !_interpolation.empty();
+  else
+    return _interpolation.count(type) ? true : false;
+}
+
 void PViewData::removeInterpolationScheme(const std::string &name)
 {
   std::map<std::string, interpolationMatrices>::iterator it = _interpolationSchemes.find(name);
diff --git a/Post/PViewData.h b/Post/PViewData.h
index 2dca280807..bbf47d872c 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -200,7 +200,7 @@ class PViewData {
                                 const fullMatrix<double> &coefGeo, 
                                 const fullMatrix<double> &expGeo);
   int getInterpolationMatrices(int type, std::vector<fullMatrix<double>*> &p);
-  inline bool haveInterpolationMatrices(){ return !_interpolation.empty(); }
+  bool haveInterpolationMatrices(int type=0);
 
   // access to global interpolation schemes
   static void removeInterpolationScheme(const std::string &name);
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index ecba42296c..96fadd77b9 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -4,6 +4,7 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include "PViewDataGModel.h"
+#include "MPoint.h"
 #include "MLine.h"
 #include "MTriangle.h"
 #include "MQuadrangle.h"
@@ -25,6 +26,63 @@ PViewDataGModel::~PViewDataGModel()
   for(unsigned int i = 0; i < _steps.size(); i++) delete _steps[i];
 }
 
+static MElement *_getOneElementOfGivenType(GModel *m, int type)
+{
+  switch(type){
+  case TYPE_PNT:
+    for(GModel::viter it = m->firstVertex(); it != m->lastVertex(); it++){
+      if((*it)->points.size()) return (*it)->points[0];
+    }
+    break;
+  case TYPE_LIN: 
+    for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++){
+      if((*it)->lines.size()) return (*it)->lines[0];
+    }
+    break;
+  case TYPE_TRI:
+    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
+      if((*it)->triangles.size()) return (*it)->triangles[0];
+    }
+    break;
+  case TYPE_QUA:
+    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
+      if((*it)->quadrangles.size()) return (*it)->quadrangles[0];
+    }
+    break;
+  case TYPE_POLYG:
+    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
+      if((*it)->polygons.size()) return (*it)->polygons[0];
+    }
+    break;
+  case TYPE_TET:
+    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
+      if((*it)->tetrahedra.size()) return (*it)->tetrahedra[0];
+    }
+    break;
+  case TYPE_HEX:
+    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
+      if((*it)->hexahedra.size()) return (*it)->hexahedra[0];
+    }
+    break;
+  case TYPE_PRI:
+    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
+      if((*it)->prisms.size()) return (*it)->prisms[0];
+    }
+    break;
+  case TYPE_PYR:
+    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
+      if((*it)->pyramids.size()) return (*it)->pyramids[0];
+    }
+    break;
+  case TYPE_POLYH:
+    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
+      if((*it)->polyhedra.size()) return (*it)->polyhedra[0];
+    }
+    break;
+  }
+  return 0;
+}
+
 bool PViewDataGModel::finalize(bool computeMinMax, const std::string &interpolationScheme)
 {
   if(computeMinMax){
@@ -64,75 +122,68 @@ bool PViewDataGModel::finalize(bool computeMinMax, const std::string &interpolat
     }
   }
 
-  if(interpolationScheme.size()){
-    interpolationMatrices m = _interpolationSchemes[interpolationScheme];
-    if(m.size())
-      Msg::Info("Setting interpolation matrices from scheme '%s'", 
-                interpolationScheme.c_str());
-    else
-      Msg::Error("Could not find interpolation scheme '%s'", 
-                 interpolationScheme.c_str());
-    for(interpolationMatrices::iterator it = m.begin(); it != m.end(); it++){
-      if(it->second.size() == 2){
-        setInterpolationMatrices(it->first, *(it->second[0]), *(it->second[1]));
-        // we should maybe automatically add the geometrical
-        // interpolation matrices here (if geometrically the elements
-        // are of order > 1)
-      }
-      else if(it->second.size() == 4)
-        setInterpolationMatrices(it->first, *it->second[0], *it->second[1],
-                                 *it->second[2], *it->second[3]);
+  // set up interpolation matrices
+  if(!haveInterpolationMatrices()){
+
+    GModel *model = _steps[0]->getModel();
+    
+    // if an interpolation scheme is explicitly provided, use it
+    if(interpolationScheme.size()){
+      interpolationMatrices m = _interpolationSchemes[interpolationScheme];
+      if(m.size())
+        Msg::Info("Setting interpolation matrices from scheme '%s'", 
+                  interpolationScheme.c_str());
       else
-        Msg::Error("Wrong number of interpolation matrices (%d) for scheme '%s'",
-                   (int)it->second.size(), interpolationScheme.c_str());
-    }
-  }
-  else if(!haveInterpolationMatrices()){
-    // add default interpolation matrices for known element types
-    for(int step = 0; step < getNumTimeSteps(); step++){
-      if(!_steps[step]->getNumData()) continue;
-      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]);
-        if((*it)->polygons.size())
-          _addInterpolationMatricesForElement((*it)->polygons[0]);
+        Msg::Error("Could not find interpolation scheme '%s'", 
+                   interpolationScheme.c_str());
+      for(interpolationMatrices::iterator it = m.begin(); it != m.end(); it++){
+        if(it->second.size() == 2){
+          // use provided interpolation matrices for field interpolation
+          // and use geometrical interpolation matrices from the mesh if
+          // the mesh is curved
+          MElement *e = _getOneElementOfGivenType(model, it->first);
+          if(e && e->getPolynomialOrder() > 1 && e->getFunctionSpace()){
+            const polynomialBasis *fs = e->getFunctionSpace();
+            setInterpolationMatrices(it->first, *(it->second[0]), *(it->second[1]),
+                                     fs->coefficients, fs->monomials);
+          }
+          else
+            setInterpolationMatrices(it->first, *(it->second[0]), *(it->second[1]));
+        }
+        else if(it->second.size() == 4){
+          // use provided matrices for field and geometry
+          setInterpolationMatrices(it->first, *it->second[0], *it->second[1],
+                                   *it->second[2], *it->second[3]);
+        }
+        else
+          Msg::Error("Wrong number of interpolation matrices (%d) for scheme '%s'",
+                     (int)it->second.size(), interpolationScheme.c_str());
       }
-      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]);
-        if((*it)->polyhedra.size())
-          _addInterpolationMatricesForElement((*it)->polyhedra[0]);
+    }
+    
+    // if we don't have interpolation matrices for a given element type,
+    // assume isoparametric elements
+    int types[] = {TYPE_PNT, TYPE_LIN, TYPE_TRI, TYPE_QUA, TYPE_TET, TYPE_HEX,
+                   TYPE_PRI, TYPE_PYR, TYPE_POLYG, TYPE_POLYH};
+    for(int i = 0; i < sizeof(types) / sizeof(types[0]); i++){
+      if(!haveInterpolationMatrices(types[i])){
+        MElement *e = _getOneElementOfGivenType(model, types[i]);
+        if(e){
+          const polynomialBasis *fs = e->getFunctionSpace();
+          if(fs){
+            if(e->getPolynomialOrder() > 1)
+              setInterpolationMatrices(types[i], fs->coefficients, fs->monomials,
+                                       fs->coefficients, fs->monomials);
+            else
+              setInterpolationMatrices(types[i], fs->coefficients, fs->monomials);
+          }
+        }
       }
     }
-  }
 
-  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);
   }
+  
+  return PViewData::finalize();
 }
 
 MElement *PViewDataGModel::_getElement(int step, int ent, int ele)
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index 5acdad0557..783c7cad6b 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -166,8 +166,6 @@ class PViewDataGModel : public PViewData {
   // cache last element to speed up loops
   MElement *_getElement(int step, int ent, int ele);
   MVertex *_getNode(MElement *e, int nod);
-  // helper function to populate the interpolation matrix list
-  void _addInterpolationMatricesForElement(MElement *e);
  public:
   PViewDataGModel(DataType type=NodeData);
   ~PViewDataGModel();
-- 
GitLab