Salome HOME
PR: downward connectivity
authorprascle <prascle>
Thu, 1 Jul 2010 14:46:31 +0000 (14:46 +0000)
committerprascle <prascle>
Thu, 1 Jul 2010 14:46:31 +0000 (14:46 +0000)
26 files changed:
doc/salome/tui/doxyfile.in
src/OBJECT/SMESH_vtkPVUpdateSuppressor.cxx
src/OBJECT/SMESH_vtkPVUpdateSuppressor.h
src/SMDS/Makefile.am
src/SMDS/ObjectPool.hxx
src/SMDS/SMDS_Downward.cxx [new file with mode: 0644]
src/SMDS/SMDS_Downward.hxx [new file with mode: 0644]
src/SMDS/SMDS_LinearEdge.cxx
src/SMDS/SMDS_LinearEdge.hxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_MeshCell.cxx
src/SMDS/SMDS_MeshCell.hxx
src/SMDS/SMDS_MeshNodeIDFactory.cxx
src/SMDS/SMDS_MeshNodeIDFactory.hxx
src/SMDS/SMDS_UnstructuredGrid.cxx
src/SMDS/SMDS_UnstructuredGrid.hxx
src/SMDS/SMDS_VtkCellIterator.cxx
src/SMDS/SMDS_VtkCellIterator.hxx
src/SMDS/SMDS_VtkEdge.cxx
src/SMDS/SMDS_VtkFace.cxx
src/SMDS/SMDS_VtkVolume.cxx
src/SMDS/SMDS_VtkVolume.hxx
src/SMDS/chrono.cxx [new file with mode: 0644]
src/SMDS/chrono.hxx [new file with mode: 0644]
src/SMESH/memoire.h
src/SMESHDS/SMESHDS_Mesh.cxx

index 0eb988674db325136cc85fca3ca960aa56fed6ee..27fa7ebdc6ba517e0e9f8366aa86be643c06aaf5 100755 (executable)
@@ -40,6 +40,7 @@ STRIP_FROM_PATH        = @top_srcdir@ @top_builddir@
 STRIP_FROM_INC_PATH    = 
 SHORT_NAMES            = NO
 JAVADOC_AUTOBRIEF      = YES
+QT_AUTOBRIEF           = YES
 MULTILINE_CPP_IS_BRIEF = NO
 DETAILS_AT_TOP         = NO
 INHERIT_DOCS           = YES
index a9fd819dcf2df3c7c081e98ef6aa53ee9ff3c400..bbab763f93cb72f6290635123083fb64fd7997ed 100644 (file)
@@ -1,17 +1,17 @@
 /*=========================================================================
 
 Program:   ParaView
 Module:    $RCSfile$
+ Program:   ParaView
+ Module:    $RCSfile$
 
 Copyright (c) Kitware, Inc.
 All rights reserved.
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
+ Copyright (c) Kitware, Inc.
+ All rights reserved.
+ See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
 
    This software is distributed WITHOUT ANY WARRANTY; without even
    the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    PURPOSE.  See the above copyright notice for more information.
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the above copyright notice for more information.
 
-=========================================================================*/
+ =========================================================================*/
 #include "SMESH_vtkPVUpdateSuppressor.h"
 
 #include "vtkAlgorithmOutput.h"
 # define vtkMyDebug(x)
 #endif
 
-vtkCxxRevisionMacro(vtkPVUpdateSuppressor, "$Revision$");
-vtkStandardNewMacro(vtkPVUpdateSuppressor);
+vtkCxxRevisionMacro(vtkPVUpdateSuppressor, "$Revision$")
+;
+vtkStandardNewMacro(vtkPVUpdateSuppressor)
+;
 //----------------------------------------------------------------------------
 vtkPVUpdateSuppressor::vtkPVUpdateSuppressor()
 {
@@ -51,16 +53,15 @@ vtkPVUpdateSuppressor::vtkPVUpdateSuppressor()
   this->UpdateTime = 0.0;
   this->UpdateTimeInitialized = false;
 
-
   this->Enabled = 1;
 
-//  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
-//
-//  if (pm)
-//    {
-//    this->UpdateNumberOfPieces = pm->GetNumberOfLocalPartitions();
-//    this->UpdatePiece = pm->GetPartitionId();
-//    }
+  //  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
+  //
+  //  if (pm)
+  //    {
+  //    this->UpdateNumberOfPieces = pm->GetNumberOfLocalPartitions();
+  //    this->UpdatePiece = pm->GetPartitionId();
+  //    }
 }
 
 //----------------------------------------------------------------------------
@@ -74,8 +75,8 @@ void vtkPVUpdateSuppressor::SetUpdateTime(double utime)
   this->UpdateTimeInitialized = true;
   if (this->UpdateTime != utime)
     {
-    this->Modified();
-    this->UpdateTime = utime;
+      this->Modified();
+      this->UpdateTime = utime;
     }
 }
 
@@ -84,29 +85,29 @@ void vtkPVUpdateSuppressor::SetEnabled(int enable)
 {
   if (this->Enabled == enable)
     {
-    return;
+      return;
     }
   this->Enabled = enable;
   this->Modified();
-//  vtkUpdateSuppressorPipeline* executive =
-//    vtkUpdateSuppressorPipeline::SafeDownCast(this->GetExecutive());
-//  if (executive)
-//    {
-//    executive->SetEnabled(enable);
-//    }
+  //  vtkUpdateSuppressorPipeline* executive =
+  //    vtkUpdateSuppressorPipeline::SafeDownCast(this->GetExecutive());
+  //  if (executive)
+  //    {
+  //    executive->SetEnabled(enable);
+  //    }
 }
 
 //----------------------------------------------------------------------------
 void vtkPVUpdateSuppressor::ForceUpdate()
-{    
+{
   // Make sure that output type matches input type
   this->UpdateInformation();
 
   vtkDataObject *input = this->GetInput();
   if (input == 0)
     {
-    vtkErrorMacro("No valid input.");
-    return;
+      vtkErrorMacro("No valid input.");
+      return;
     }
   vtkDataObject *output = this->GetOutput();
 
@@ -115,41 +116,38 @@ void vtkPVUpdateSuppressor::ForceUpdate()
   // Client needs to modify the collection filter because it is not
   // connected to a pipeline.
   vtkAlgorithm *source = input->GetProducerPort()->GetProducer();
-  if (source &&
-      (source->IsA("vtkMPIMoveData") ||
-       source->IsA("vtkCollectPolyData") ||
-       source->IsA("vtkM2NDuplicate") ||
-       source->IsA("vtkM2NCollect") ||
-       source->IsA("vtkOrderedCompositeDistributor") || 
-       source->IsA("vtkClientServerMoveData")))
+  if (source && (source->IsA("vtkMPIMoveData")
+      || source->IsA("vtkCollectPolyData") || source->IsA("vtkM2NDuplicate")
+      || source->IsA("vtkM2NCollect")
+      || source->IsA("vtkOrderedCompositeDistributor")
+      || source->IsA("vtkClientServerMoveData")))
     {
-    source->Modified();
+      source->Modified();
     }
 
   vtkInformation* info = input->GetPipelineInformation();
-  vtkStreamingDemandDrivenPipeline* sddp = 
-    vtkStreamingDemandDrivenPipeline::SafeDownCast(
-      vtkExecutive::PRODUCER()->GetExecutive(info));
+  vtkStreamingDemandDrivenPipeline
+      * sddp =
+          vtkStreamingDemandDrivenPipeline::SafeDownCast(
+                                                         vtkExecutive::PRODUCER()->GetExecutive(
+                                                                                                info));
   if (sddp)
     {
-    sddp->SetUpdateExtent(info,
-                          this->UpdatePiece, 
-                          this->UpdateNumberOfPieces, 
-                          0);
+      sddp->SetUpdateExtent(info, this->UpdatePiece,
+                            this->UpdateNumberOfPieces, 0);
     }
   else
     {
-    input->SetUpdatePiece(this->UpdatePiece);
-    input->SetUpdateNumberOfPieces(this->UpdateNumberOfPieces);
-    input->SetUpdateGhostLevel(0);
-    }
-  vtkMyDebug("ForceUpdate ");
+      input->SetUpdatePiece(this->UpdatePiece);
+      input->SetUpdateNumberOfPieces(this->UpdateNumberOfPieces);
+      input->SetUpdateGhostLevel(0);
+    } vtkMyDebug("ForceUpdate ");
   if (this->UpdateTimeInitialized)
     {
-    info->Set(vtkCompositeDataPipeline::UPDATE_TIME_STEPS(), &this->UpdateTime, 1);
-    vtkMyDebug(this->UpdateTime);
-    }
-  vtkMyDebug(endl);
+      info->Set(vtkCompositeDataPipeline::UPDATE_TIME_STEPS(),
+                &this->UpdateTime, 1);
+      vtkMyDebug(this->UpdateTime);
+    } vtkMyDebug(endl);
 
   input->Update();
   // Input may have changed, we obtain the pointer again.
@@ -159,7 +157,6 @@ void vtkPVUpdateSuppressor::ForceUpdate()
   this->PipelineUpdateTime.Modified();
 }
 
-
 //----------------------------------------------------------------------------
 vtkExecutive* vtkPVUpdateSuppressor::CreateDefaultExecutive()
 {
@@ -170,35 +167,36 @@ vtkExecutive* vtkPVUpdateSuppressor::CreateDefaultExecutive()
 
 //----------------------------------------------------------------------------
 int vtkPVUpdateSuppressor::RequestDataObject(
-  vtkInformation* vtkNotUsed(reqInfo), 
-  vtkInformationVector** inputVector , 
-  vtkInformationVector* outputVector)
+                                             vtkInformation* vtkNotUsed(reqInfo),
+                                             vtkInformationVector** inputVector,
+                                             vtkInformationVector* outputVector)
 {
   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
   if (!inInfo)
     {
-    return 0;
+      return 0;
     }
-  
+
   vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT());
   if (input)
     {
-    // for each output
-    for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
-      {
-      vtkInformation* outInfo = outputVector->GetInformationObject(i);
-      vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT());
-    
-      if (!output || !output->IsA(input->GetClassName())) 
+      // for each output
+      for (int i = 0; i < this->GetNumberOfOutputPorts(); ++i)
         {
-        vtkDataObject* newOutput = input->NewInstance();
-        newOutput->SetPipelineInformation(outInfo);
-        newOutput->Delete();
-        this->GetOutputPortInformation(i)->Set(
-          vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType());
+          vtkInformation* outInfo = outputVector->GetInformationObject(i);
+          vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT());
+
+          if (!output || !output->IsA(input->GetClassName()))
+            {
+              vtkDataObject* newOutput = input->NewInstance();
+              newOutput->SetPipelineInformation(outInfo);
+              newOutput->Delete();
+              this->GetOutputPortInformation(i)->Set(
+                                                     vtkDataObject::DATA_EXTENT_TYPE(),
+                                                     newOutput->GetExtentType());
+            }
         }
-      }
-    return 1;
+      return 1;
     }
   return 0;
 
@@ -223,9 +221,10 @@ int vtkPVUpdateSuppressor::RequestData(vtkInformation* vtkNotUsed(reqInfo),
 //----------------------------------------------------------------------------
 void vtkPVUpdateSuppressor::PrintSelf(ostream& os, vtkIndent indent)
 {
-  this->Superclass::PrintSelf(os,indent);
+  this->Superclass::PrintSelf(os, indent);
   os << indent << "UpdatePiece: " << this->UpdatePiece << endl;
-  os << indent << "UpdateNumberOfPieces: " << this->UpdateNumberOfPieces << endl;
+  os << indent << "UpdateNumberOfPieces: " << this->UpdateNumberOfPieces
+      << endl;
   os << indent << "Enabled: " << this->Enabled << endl;
   os << indent << "UpdateTime: " << this->UpdateTime << endl;
 }
index bf023a45b54f31f0f251fccc223861e5664e4a73..4cd0624e757d4ce76de1c4dc08097d84bc6e2387 100644 (file)
@@ -1,17 +1,17 @@
 /*=========================================================================
 
 Program:   ParaView
 Module:    $RCSfile$
+ Program:   ParaView
+ Module:    $RCSfile$
 
 Copyright (c) Kitware, Inc.
 All rights reserved.
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
+ Copyright (c) Kitware, Inc.
+ All rights reserved.
+ See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
 
    This software is distributed WITHOUT ANY WARRANTY; without even
    the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    PURPOSE.  See the above copyright notice for more information.
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the above copyright notice for more information.
 
-=========================================================================*/
+ =========================================================================*/
 // .NAME vtkPVUpdateSuppressor - prevents propagation of update
 // .SECTION Description 
 // vtkPVUpdateSuppressor now uses the vtkProcessModule singleton to set up the
 
 #include "vtkDataObjectAlgorithm.h"
 
-class VTK_EXPORT vtkPVUpdateSuppressor : public vtkDataObjectAlgorithm
+class VTK_EXPORT vtkPVUpdateSuppressor: public vtkDataObjectAlgorithm
 {
 public:
-  vtkTypeRevisionMacro(vtkPVUpdateSuppressor,vtkDataObjectAlgorithm);
+vtkTypeRevisionMacro(vtkPVUpdateSuppressor,vtkDataObjectAlgorithm)
+  ;
   void PrintSelf(ostream& os, vtkIndent indent);
 
   // Description:
@@ -44,30 +45,37 @@ public:
   // This causes the filter to ingore the request from the output.
   // It is here because the user may not have celled update on the output
   // before calling force update (it is an easy fix).
-  vtkSetMacro(UpdatePiece, int);
-  vtkGetMacro(UpdatePiece, int);
-  vtkSetMacro(UpdateNumberOfPieces, int);
-  vtkGetMacro(UpdateNumberOfPieces, int);
+  vtkSetMacro(UpdatePiece, int)
+  ;
+  vtkGetMacro(UpdatePiece, int)
+  ;
+  vtkSetMacro(UpdateNumberOfPieces, int)
+  ;
+  vtkGetMacro(UpdateNumberOfPieces, int)
+  ;
 
   // Description:
   // Get/Set if the update suppressor is enabled. If the update suppressor 
   // is not enabled, it won't supress any updates. Enabled by default.
   void SetEnabled(int);
-  vtkGetMacro(Enabled, int);
+  vtkGetMacro(Enabled, int)
+  ;
 
   // Description:
   // Get/Set the update time that is sent up the pipeline.
   void SetUpdateTime(double utime);
-  vtkGetMacro(UpdateTime, double);
+  vtkGetMacro(UpdateTime, double)
+  ;
 
 protected:
   vtkPVUpdateSuppressor();
   ~vtkPVUpdateSuppressor();
 
-  int RequestDataObject(vtkInformation* request, vtkInformationVector **inputVector,
-    vtkInformationVector *outputVector);
+  int RequestDataObject(vtkInformation* request,
+                        vtkInformationVector **inputVector,
+                        vtkInformationVector *outputVector);
   int RequestData(vtkInformation* request, vtkInformationVector **inputVector,
-    vtkInformationVector *outputVector);
+                  vtkInformationVector *outputVector);
 
   int UpdatePiece;
   int UpdateNumberOfPieces;
@@ -79,13 +87,12 @@ protected:
 
   vtkTimeStamp PipelineUpdateTime;
 
-
   // Create a default executive.
   virtual vtkExecutive* CreateDefaultExecutive();
 
 private:
-  vtkPVUpdateSuppressor(const vtkPVUpdateSuppressor&);  // Not implemented.
-  void operator=(const vtkPVUpdateSuppressor&);  // Not implemented.
+  vtkPVUpdateSuppressor(const vtkPVUpdateSuppressor&); // Not implemented.
+  void operator=(const vtkPVUpdateSuppressor&); // Not implemented.
 };
 
 #endif
index dc6e47408b3b713e041e5ff200784b45a79fd301..c4dd2bf11c7c77be9e3e16169f712a3c5ba065d1 100644 (file)
@@ -27,6 +27,7 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am
 
 # header files 
 salomeinclude_HEADERS = \
+    chrono.hxx \
        ObjectPool.hxx \
        SMDS_TypeOfPosition.hxx \
        SMDSAbs_ElementType.hxx \
@@ -71,6 +72,7 @@ salomeinclude_HEADERS = \
        SMESH_SMDS.hxx \
        SMDS_MeshInfo.hxx \
        SMDS_UnstructuredGrid.hxx \
+       SMDS_Downward.hxx \
        SMDS_StdIterator.hxx
 
 
@@ -78,6 +80,7 @@ salomeinclude_HEADERS = \
 
 lib_LTLIBRARIES = libSMDS.la
 dist_libSMDS_la_SOURCES = \
+    chrono.cxx \
        SMDS_MeshObject.cxx \
        SMDS_MeshElement.cxx \
        SMDS_MeshCell.cxx \
@@ -112,7 +115,8 @@ dist_libSMDS_la_SOURCES = \
        SMDS_QuadraticEdge.cxx \
        SMDS_QuadraticFaceOfNodes.cxx \
        SMDS_QuadraticVolumeOfNodes.cxx \
-       SMDS_UnstructuredGrid.cxx
+       SMDS_UnstructuredGrid.cxx \
+       SMDS_Downward.cxx
 
 # additionnal information to compil and link file
 libSMDS_la_CPPFLAGS = \
index d800bc4ee2da8ab4c485744c73eac2292ecd3bbb..6e2fc1d2abdc140ad39226848239158c92c762c2 100644 (file)
@@ -19,10 +19,10 @@ private:
   {
     for (int i = _nextFree; i < _maxAvail; i++)
       if (_freeList[i] == true)
-      {
-        return i;
-        break;
-      }
+        {
+          return i;
+          break;
+        }
     return _maxAvail;
   }
 
@@ -60,21 +60,21 @@ public:
     X *obj = 0;
     _nextFree = getNextFree();
     if (_nextFree == _maxAvail)
-    {
-      X* newChunk = new X[_chunkSize];
-      _chunkList.push_back(newChunk);
-      _freeList.insert(_freeList.end(), _chunkSize, true);
-      _maxAvail += _chunkSize;
-      _freeList[_nextFree] = false;
-      obj = newChunk; // &newChunk[0];
-    }
+      {
+        X* newChunk = new X[_chunkSize];
+        _chunkList.push_back(newChunk);
+        _freeList.insert(_freeList.end(), _chunkSize, true);
+        _maxAvail += _chunkSize;
+        _freeList[_nextFree] = false;
+        obj = newChunk; // &newChunk[0];
+      }
     else
-    {
-      int chunkId = _nextFree / _chunkSize;
-      int rank = _nextFree - chunkId * _chunkSize;
-      _freeList[_nextFree] = false;
-      obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
-    }
+      {
+        int chunkId = _nextFree / _chunkSize;
+        int rank = _nextFree - chunkId * _chunkSize;
+        _freeList[_nextFree] = false;
+        obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
+      }
     //obj->init();
     return obj;
   }
@@ -83,32 +83,32 @@ public:
   {
     long adrobj = (long) (obj);
     for (int i = 0; i < _chunkList.size(); i++)
-    {
-      X* chunk = _chunkList[i];
-      long adrmin = (long) (chunk);
-      if (adrobj < adrmin)
-        continue;
-      long adrmax = (long) (chunk + _chunkSize);
-      if (adrobj >= adrmax)
-        continue;
-      int rank = (adrobj - adrmin) / sizeof(X);
-      int toFree = i * _chunkSize + rank;
-      _freeList[toFree] = true;
-      if (toFree < _nextFree)
-        _nextFree = toFree;
-      //obj->clean();
-      //checkDelete(i); compactage non fait
-      break;
-    }
+      {
+        X* chunk = _chunkList[i];
+        long adrmin = (long) (chunk);
+        if (adrobj < adrmin)
+          continue;
+        long adrmax = (long) (chunk + _chunkSize);
+        if (adrobj >= adrmax)
+          continue;
+        int rank = (adrobj - adrmin) / sizeof(X);
+        int toFree = i * _chunkSize + rank;
+        _freeList[toFree] = true;
+        if (toFree < _nextFree)
+          _nextFree = toFree;
+        //obj->clean();
+        //checkDelete(i); compactage non fait
+        break;
+      }
   }
 
-//  void destroy(int toFree)
-//  {
-//    // no control 0<= toFree < _freeList.size()
-//    _freeList[toFree] = true;
-//    if (toFree < _nextFree)
-//      _nextFree = toFree;
-//  }
+  //  void destroy(int toFree)
+  //  {
+  //    // no control 0<= toFree < _freeList.size()
+  //    _freeList[toFree] = true;
+  //    if (toFree < _nextFree)
+  //      _nextFree = toFree;
+  //  }
 
 };
 
diff --git a/src/SMDS/SMDS_Downward.cxx b/src/SMDS/SMDS_Downward.cxx
new file mode 100644 (file)
index 0000000..561b10b
--- /dev/null
@@ -0,0 +1,1889 @@
+/*
+ * SMDS_Downward.cxx
+ *
+ *  Created on: Jun 3, 2010
+ *      Author: prascle
+ */
+
+#include "SMDS_Downward.hxx"
+#include "SMDS_Mesh.hxx"
+#include "utilities.h"
+
+#include <vtkCellType.h>
+#include <vtkCellLinks.h>
+
+#include <map>
+
+using namespace std;
+
+// ---------------------------------------------------------------------------
+
+vector<int> SMDS_Downward::_cellDimension;
+
+/*! get the dimension of a cell (1,2,3 for 1D, 2D 3D) given the vtk cell type
+ *
+ * @param cellType vtk cell type @see vtkCellType.h
+ * @return 1,2 or 3
+ */
+int SMDS_Downward::getCellDimension(unsigned char cellType)
+{
+  return _cellDimension[cellType];
+}
+
+// ---------------------------------------------------------------------------
+
+/*! Generic constructor for all the downward connectivity structures (one per vtk cell type).
+ *  The static structure for cell dimension is set only once.
+ * @param grid unstructured grid associated to the mesh.
+ * @param nbDownCells number of downward entities associated to this vtk type of cell.
+ * @return
+ */
+SMDS_Downward::SMDS_Downward(SMDS_UnstructuredGrid *grid, int nbDownCells) :
+  _grid(grid), _nbDownCells(nbDownCells)
+{
+  this->_maxId = 0;
+  this->_cellIds.clear();
+  this->_cellTypes.clear();
+  if (_cellDimension.empty())
+    {
+      _cellDimension.resize(VTK_QUADRATIC_PYRAMID + 1, 0);
+      _cellDimension[VTK_LINE] = 1;
+      _cellDimension[VTK_QUADRATIC_EDGE] = 1;
+      _cellDimension[VTK_TRIANGLE] = 2;
+      _cellDimension[VTK_QUADRATIC_TRIANGLE] = 2;
+      _cellDimension[VTK_QUAD] = 2;
+      _cellDimension[VTK_QUADRATIC_QUAD] = 2;
+      _cellDimension[VTK_TETRA] = 3;
+      _cellDimension[VTK_QUADRATIC_TETRA] = 3;
+      _cellDimension[VTK_HEXAHEDRON] = 3;
+      _cellDimension[VTK_QUADRATIC_HEXAHEDRON] = 3;
+      _cellDimension[VTK_WEDGE] = 3;
+      _cellDimension[VTK_QUADRATIC_WEDGE] = 3;
+      _cellDimension[VTK_PYRAMID] = 3;
+      _cellDimension[VTK_QUADRATIC_PYRAMID] = 3;
+    }
+}
+
+SMDS_Downward::~SMDS_Downward()
+{
+}
+
+/*! Give or create an entry for downward connectivity structure relative to a cell.
+ * If the entry already exists, just return its id, otherwise, create it.
+ * The internal storage memory is allocated if needed.
+ * The SMDS_UnstructuredGrid::_cellIdToDownId vector is completed for vtkUnstructuredGrid cells.
+ * @param vtkId for a vtkUnstructuredGrid cell  or -1 (default) for a created downward cell.
+ * @return the rank in downward[vtkType] structure.
+ */
+int SMDS_Downward::addCell(int vtkId)
+{
+  int localId = -1;
+  if (vtkId >= 0)
+    localId = _grid->CellIdToDownId(vtkId);
+  if (localId >= 0)
+    return localId;
+
+  localId = this->_maxId;
+  this->_maxId++;
+  this->allocate(_maxId);
+  if (vtkId >= 0)
+    {
+      this->_vtkCellIds[localId] = vtkId;
+      _grid->setCellIdToDownId(vtkId, localId);
+    }
+  this->initCell(localId);
+  return localId;
+}
+
+/*! generic method do nothing. see derived methods
+ *
+ * @param cellId
+ */
+void SMDS_Downward::initCell(int cellId)
+{
+}
+
+/*! Get the number of downward entities associated to a cell (always the same for a given vtk type of cell)
+ *
+ * @param cellId not used here.
+ * @return
+ */
+int SMDS_Downward::getNumberOfDownCells(int cellId)
+{
+  return _nbDownCells;
+}
+
+/*! get a pointer on the downward entities id's associated to a cell.
+ * @see SMDS_Downward::getNumberOfDownCells for the number of downward entities.
+ * @see SMDS_Downward::getDownTypes for the vtk cell types associated to the downward entities.
+ * @param cellId index of the cell in the downward structure relative to a given vtk cell type.
+ * @return table of downward entities id's.
+ */
+const int* SMDS_Downward::getDownCells(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return &_cellIds[_nbDownCells * cellId];
+}
+
+/*! get a list of vtk cell types associated to downward entities of a given cell, in the same order
+ * than the downward entities id's list (@see SMDS_Downward::getDownCells).
+ *
+ * @param cellId index of the cell in the downward structure relative to a vtk cell type.
+ * @return table of downward entities types.
+ */
+const unsigned char* SMDS_Downward::getDownTypes(int cellId)
+{
+  return &_cellTypes[0];
+}
+
+/*! add a downward entity of dimension n-1 (cell or node) to a given cell.
+ * Actual implementation is done in derived methods.
+ * @param cellId index of the parent cell (dimension n) in the downward structure relative to a vtk cell type.
+ * @param lowCellId index of the children cell to add (dimension n-1)
+ * @param aType vtk cell type of the cell to add (needed to find the SMDS_Downward structure containing the cell to add).
+ */
+void SMDS_Downward::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  ASSERT(0); // must be re-implemented in derived class
+}
+
+/*! add a downward entity of dimension n+1 to a given cell.
+ * Actual implementation is done in derived methods.
+ * @param cellId index of the children cell (dimension n) in the downward structure relative to a vtk cell type.
+ * @param upCellId index of the parent cell to add (dimension n+1)
+ * @param aType vtk cell type of the cell to add (needed to find the SMDS_Downward structure containing the cell to add).
+ */
+void SMDS_Downward::addUpCell(int cellId, int upCellId, unsigned char aType)
+{
+  ASSERT(0); // must be re-implemented in derived class
+}
+
+int SMDS_Downward::getNodeSet(int cellId, int* nodeSet)
+{
+  return 0;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_Down1D::SMDS_Down1D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
+  SMDS_Downward(grid, nbDownCells)
+{
+  _upCellIdsVector.clear();
+  _upCellTypesVector.clear();
+  _upCellIds.clear();
+  _upCellTypes.clear();
+  _upCellIndex.clear();
+}
+
+SMDS_Down1D::~SMDS_Down1D()
+{
+}
+
+/*! clear vectors used to reference 2D cells containing the edge
+ *
+ * @param cellId
+ */
+void SMDS_Down1D::initCell(int cellId)
+{
+  _upCellIdsVector[cellId].clear();
+  _upCellTypesVector[cellId].clear();
+}
+
+/*! Resize the downward connectivity storage vector if needed.
+ *
+ * @param nbElems total number of elements of the same type required
+ */
+void SMDS_Down1D::allocate(int nbElems)
+{
+  if (nbElems >= _vtkCellIds.size())
+    {
+      _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
+      _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
+      _upCellIdsVector.resize(nbElems + SMDS_Mesh::chunkSize);
+      _upCellTypesVector.resize(nbElems + SMDS_Mesh::chunkSize);
+    }
+}
+
+void SMDS_Down1D::compactStorage()
+{
+  _cellIds.resize(_nbDownCells * _maxId);
+  _vtkCellIds.resize(_maxId);
+
+  int sizeUpCells = 0;
+  for (int i = 0; i < _maxId; i++)
+    sizeUpCells += _upCellIdsVector[i].size();
+  _upCellIds.resize(sizeUpCells, -1);
+  _upCellTypes.resize(sizeUpCells);
+  _upCellIndex.resize(_maxId + 1, -1); // id and types of rank i correspond to [ _upCellIndex[i], _upCellIndex[i+1] [
+  int current = 0;
+  for (int i = 0; i < _maxId; i++)
+    {
+      _upCellIndex[i] = current;
+      for (int j = 0; j < _upCellIdsVector[i].size(); j++)
+        {
+          _upCellIds[current] = _upCellIdsVector[i][j];
+          _upCellTypes[current] = _upCellTypesVector[i][j];
+          current++;
+        }
+    }
+  _upCellIndex[_maxId] = current;
+
+  _upCellIdsVector.clear();
+  _upCellTypesVector.clear();
+}
+
+void SMDS_Down1D::addUpCell(int cellId, int upCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  int nbFaces = _upCellIdsVector[cellId].size();
+  for (int i = 0; i < nbFaces; i++)
+    {
+      if ((_upCellIdsVector[cellId][i] == upCellId) && (_upCellTypesVector[cellId][i] == aType))
+        {
+          return; // already done
+        }
+    }
+  _upCellIdsVector[cellId].push_back(upCellId);
+  _upCellTypesVector[cellId].push_back(aType);
+}
+
+int SMDS_Down1D::getNumberOfUpCells(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return _upCellIndex[cellId + 1] - _upCellIndex[cellId];
+}
+
+const int* SMDS_Down1D::getUpCells(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return &_upCellIds[_upCellIndex[cellId]];
+}
+
+const unsigned char* SMDS_Down1D::getUpTypes(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return &_upCellTypes[_upCellIndex[cellId]];
+}
+
+int SMDS_Down1D::getNodeSet(int cellId, int* nodeSet)
+{
+  for (int i = 0; i < _nbDownCells; i++)
+    nodeSet[i] = _cellIds[_nbDownCells * cellId + i];
+  return _nbDownCells;
+}
+
+void SMDS_Down1D::setNodes(int cellId, int vtkId)
+{
+  vtkIdType npts = 0;
+  vtkIdType *pts; // will refer to the point id's of the face
+  _grid->GetCellPoints(vtkId, npts, pts);
+  // MESSAGE(vtkId << " " << npts << "  " << _nbDownCells);
+  //ASSERT(npts == _nbDownCells);
+  for (int i = 0; i < npts; i++)
+    {
+      _cellIds[_nbDownCells * cellId + i] = pts[i];
+    }
+}
+
+void SMDS_Down1D::setNodes(int cellId, const int* nodeIds)
+{
+  //ASSERT(nodeIds.size() == _nbDownCells);
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      _cellIds[_nbDownCells * cellId + i] = nodeIds[i];
+    }
+}
+
+/*! Build the list of vtkUnstructuredGrid cells containing the edge.
+ * We keep in the list the cells that contains all the nodes, we keep only volumes and faces.
+ * @param cellId id of the edge in the downward structure
+ * @param vtkIds vector of vtk id's
+ * @return number of vtk cells (size of vector)
+ */
+int SMDS_Down1D::computeVtkCells(int cellId, std::vector<int>& vtkIds)
+{
+  vtkIds.clear();
+
+  // --- find all the cells the points belong to, and how many of the points belong to a given cell
+
+  int *pts = &_cellIds[_nbDownCells * cellId];
+  int ncells = this->computeVtkCells(pts, vtkIds);
+  return ncells;
+}
+
+/*! Build the list of vtkUnstructuredGrid cells containing the edge.
+ *
+ * @param pts list of points id's defining an edge
+ * @param vtkIds vector of vtk id's
+ * @return number of vtk cells (size of vector)
+ */
+int SMDS_Down1D::computeVtkCells(int *pts, std::vector<int>& vtkIds)
+{
+
+  // --- find all the cells the points belong to, and how many of the points belong to a given cell
+
+  int cellIds[100];
+  int cellCnt[100];
+  int cnt = 0;
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      vtkIdType point = pts[i];
+      int numCells = _grid->GetLinks()->GetNcells(point);
+      vtkIdType *cells = _grid->GetLinks()->GetCells(point);
+      for (int j = 0; j < numCells; j++)
+        {
+          int vtkCellId = cells[j];
+          bool found = false;
+          for (int k = 0; k < cnt; k++)
+            {
+              if (cellIds[k] == vtkCellId)
+                {
+                  cellCnt[k] += 1;
+                  found = true;
+                  break;
+                }
+            }
+          if (!found)
+            {
+              cellIds[cnt] = vtkCellId;
+              cellCnt[cnt] = 1;
+              // TODO ASSERT(cnt<100);
+              cnt++;
+            }
+        }
+    }
+
+  // --- find the face and volume cells: they contains all the points and are of type volume or face
+
+  int ncells = 0;
+  for (int i = 0; i < cnt; i++)
+    {
+      if (cellCnt[i] == _nbDownCells)
+        {
+          int vtkElemId = cellIds[i];
+          int vtkType = _grid->GetCellType(vtkElemId);
+          if (SMDS_Downward::getCellDimension(vtkType) > 1)
+            {
+              vtkIds.push_back(vtkElemId);
+              ncells++;
+            }
+        }
+    }
+
+  return ncells;
+}
+
+/*! Build the list of downward faces from a list of vtk cells.
+ *
+ * @param cellId id of the edge in the downward structure
+ * @param vtkIds vector of vtk id's
+ * @param downFaces vector of face id's in downward structures
+ * @param downTypes vector of face types
+ * @return number of downward faces
+ */
+int SMDS_Down1D::computeFaces(int cellId, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes)
+{
+  int *pts = &_cellIds[_nbDownCells * cellId];
+  int nbFaces = this->computeFaces(pts, vtkIds, nbcells, downFaces, downTypes);
+  return nbFaces;
+}
+
+/*! Build the list of downward faces from a list of vtk cells.
+ *
+ * @param pts list of points id's defining an edge
+ * @param vtkIds vector of vtk id's
+ * @param downFaces vector of face id's in downward structures
+ * @param downTypes vector of face types
+ * @return number of downward faces
+ */
+int SMDS_Down1D::computeFaces(int* pts, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes)
+{
+  int cnt = 0;
+  for (int i = 0; i < nbcells; i++)
+    {
+      int vtkId = vtkIds[i];
+      int vtkType = _grid->GetCellType(vtkId);
+      if (SMDS_Downward::getCellDimension(vtkType) == 2)
+        {
+          int faceId = _grid->CellIdToDownId(vtkId);
+          downFaces[cnt] = faceId;
+          downTypes[cnt] = vtkType;
+          cnt++;
+        }
+      else
+        {
+          int volId = _grid->CellIdToDownId(vtkId);
+          SMDS_Downward * downvol = _grid->getDownArray(vtkType);
+          const int *downIds = downvol->getDownCells(volId);
+          const unsigned char* downTypesVol = downvol->getDownTypes(volId);
+          int nbFaces = downvol->getNumberOfDownCells(volId);
+          const int* faceIds = downvol->getDownCells(volId);
+          for (int n = 0; n < nbFaces; n++)
+            {
+              SMDS_Down2D *downFace = static_cast<SMDS_Down2D*> (_grid->getDownArray(downTypesVol[n]));
+              bool isInFace = downFace->isInFace(faceIds[n], pts, _nbDownCells);
+              if (isInFace)
+                {
+                  bool alreadySet = false;
+                  for (int k = 0; k < cnt; k++)
+                    if (faceIds[n] == downFaces[k])
+                      {
+                        alreadySet = true;
+                        break;
+                      }
+                  if (!alreadySet)
+                    {
+                      downFaces[cnt] = faceIds[n];
+                      downTypes[cnt] = downTypesVol[n];
+                      cnt++;
+                    }
+                }
+            }
+        }
+    }
+  return cnt;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_Down2D::SMDS_Down2D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
+  SMDS_Downward(grid, nbDownCells)
+{
+  _upCellIds.clear();
+  _upCellTypes.clear();
+  _tempNodes.clear();
+  _nbNodes = 0;
+}
+
+SMDS_Down2D::~SMDS_Down2D()
+{
+}
+
+int SMDS_Down2D::getNumberOfUpCells(int cellId)
+{
+  int nbup = 0;
+  if (_upCellIds[2 * cellId] >= 0)
+    nbup++;
+  if (_upCellIds[2 * cellId + 1] >= 0)
+    nbup++;
+  return nbup;
+}
+
+const int* SMDS_Down2D::getUpCells(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return &_upCellIds[2 * cellId];
+}
+
+const unsigned char* SMDS_Down2D::getUpTypes(int cellId)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  return &_upCellTypes[2 * cellId];
+}
+
+/*! Find in vtkUnstructuredGrid the volumes containing a face already stored in vtkUnstructuredGrid.
+ * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
+ * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
+ * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
+ * @param cellId the face cell id in vkUnstructuredGrid
+ * @param ids a couple of vtkId, initialized at -1 (no parent volume)
+ * @return number of volumes (0, 1 or 2)
+ */
+int SMDS_Down2D::computeVolumeIds(int cellId, int* ids)
+{
+  // --- find point id's of the face
+
+  vtkIdType npts = 0;
+  vtkIdType *pts; // will refer to the point id's of the face
+  _grid->GetCellPoints(cellId, npts, pts);
+  vector<int> nodes;
+  for (int i = 0; i < npts; i++)
+    nodes.push_back(pts[i]);
+  int nvol = this->computeVolumeIdsFromNodesFace(&nodes[0], npts, ids);
+  return nvol;
+}
+
+/*! Find in vtkUnstructuredGrid the volumes containing a face described by it's nodes
+ * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
+ * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
+ * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
+ * @param faceByNodes
+ * @param ids a couple of vtkId, initialized at -1 (no parent volume)
+ * @return number of volumes (0, 1 or 2)
+ */
+int SMDS_Down2D::computeVolumeIds(ElemByNodesType& faceByNodes, int* ids)
+{
+  int nvol = this->computeVolumeIdsFromNodesFace(&faceByNodes.nodeIds[0], faceByNodes.nbNodes, ids);
+  return nvol;
+}
+
+/*! Find in vtkUnstructuredGrid the volumes containing a face described by it's nodes
+ * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
+ * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
+ * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
+ * @param pts array of vtk node id's
+ * @param npts number of nodes
+ * @param ids
+ * @return number of volumes (0, 1 or 2)
+ */
+int SMDS_Down2D::computeVolumeIdsFromNodesFace(int* pts, int npts, int* ids)
+{
+
+  // --- find all the cells the points belong to, and how many of the points belong to a given cell
+
+  int cellIds[100];
+  int cellCnt[100];
+  int cnt = 0;
+  for (int i = 0; i < npts; i++)
+    {
+      vtkIdType point = pts[i];
+      int numCells = _grid->GetLinks()->GetNcells(point);
+      //MESSAGE("cells pour " << i << " " << numCells);
+      vtkIdType *cells = _grid->GetLinks()->GetCells(point);
+      for (int j = 0; j < numCells; j++)
+        {
+          int vtkCellId = cells[j];
+          bool found = false;
+          for (int k = 0; k < cnt; k++)
+            {
+              if (cellIds[k] == vtkCellId)
+                {
+                  cellCnt[k] += 1;
+                  found = true;
+                  break;
+                }
+            }
+          if (!found)
+            {
+              cellIds[cnt] = vtkCellId;
+              cellCnt[cnt] = 1;
+              // TODO ASSERT(cnt<100);
+              cnt++;
+            }
+        }
+    }
+
+  // --- find the volume cells: they contains all the points and are of type volume
+
+  int nvol = 0;
+  for (int i = 0; i < cnt; i++)
+    {
+      //MESSAGE("cell " << cellIds[i] << " points " << cellCnt[i]);
+      if (cellCnt[i] == npts)
+        {
+          int vtkElemId = cellIds[i];
+          int vtkType = _grid->GetCellType(vtkElemId);
+          if (SMDS_Downward::getCellDimension(vtkType) == 3)
+            {
+              ids[nvol] = vtkElemId; // store the volume id in given vector
+              nvol++;
+            }
+        }
+      if (nvol == 2)
+        break;
+    }
+
+  return nvol;
+}
+
+void SMDS_Down2D::setTempNodes(int cellId, int vtkId)
+{
+  vtkIdType npts = 0;
+  vtkIdType *pts; // will refer to the point id's of the face
+  _grid->GetCellPoints(vtkId, npts, pts);
+  // MESSAGE(vtkId << " " << npts << "  " << _nbNodes);
+  //ASSERT(npts == _nbNodes);
+  for (int i = 0; i < npts; i++)
+    {
+      _tempNodes[_nbNodes * cellId + i] = pts[i];
+    }
+}
+
+void SMDS_Down2D::setTempNodes(int cellId, ElemByNodesType& faceByNodes)
+{
+  for (int i = 0; i < faceByNodes.nbNodes; i++)
+    _tempNodes[_nbNodes * cellId + i] = faceByNodes.nodeIds[i];
+}
+
+/*! Find if all the nodes belongs to the face.
+ *
+ * @param cellId the face cell Id
+ * @param nodeSet set of node id's to be found in the face list of nodes
+ * @return
+ */
+bool SMDS_Down2D::isInFace(int cellId, int *pts, int npts)
+{
+  int nbFound = 0;
+  int *nodes = &_tempNodes[_nbNodes * cellId];
+  for (int j = 0; j < npts; j++)
+    {
+      int point = pts[j];
+      for (int i = 0; i < _nbNodes; i++)
+        {
+          if (nodes[i] == point)
+            {
+              nbFound++;
+              break;
+            }
+        }
+    }
+  return (nbFound == npts);
+}
+
+/*! Resize the downward connectivity storage vector if needed.
+ *
+ * @param nbElems total number of elements of the same type required
+ */
+void SMDS_Down2D::allocate(int nbElems)
+{
+  if (nbElems >= _vtkCellIds.size())
+    {
+      _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
+      _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
+      _upCellIds.resize(2 * (nbElems + SMDS_Mesh::chunkSize), -1);
+      _upCellTypes.resize(2 * (nbElems + SMDS_Mesh::chunkSize), -1);
+      _tempNodes.resize(_nbNodes * (nbElems + SMDS_Mesh::chunkSize), -1);
+    }
+}
+
+void SMDS_Down2D::compactStorage()
+{
+  _cellIds.resize(_nbDownCells * _maxId);
+  _upCellIds.resize(2 * _maxId);
+  _upCellTypes.resize(2 * _maxId);
+  _vtkCellIds.resize(_maxId);
+  _tempNodes.clear();
+}
+
+void SMDS_Down2D::addUpCell(int cellId, int upCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  int *vols = &_upCellIds[2 * cellId];
+  unsigned char *types = &_upCellTypes[2 * cellId];
+  for (int i = 0; i < 2; i++)
+    {
+      if (vols[i] < 0)
+        {
+          vols[i] = upCellId; // use non affected volume
+          types[i] = aType;
+          return;
+        }
+      if ((vols[i] == upCellId) && (types[i] == aType)) // already done
+        return;
+    }
+  ASSERT(0);
+}
+
+int SMDS_Down2D::getNodeSet(int cellId, int* nodeSet)
+{
+  for (int i = 0; i < _nbNodes; i++)
+    nodeSet[i] = _tempNodes[_nbNodes * cellId + i];
+  return _nbNodes;
+}
+
+int SMDS_Down2D::FindEdgeByNodes(int cellId, ElemByNodesType& edgeByNodes)
+{
+  int *edges = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if ((edges[i] >= 0) && (edgeByNodes.vtkType == _cellTypes[i]))
+        {
+          int nodeSet[3];
+          int npts = this->_grid->getDownArray(edgeByNodes.vtkType)->getNodeSet(edges[i], nodeSet);
+          bool found = false;
+          for (int j = 0; j < npts; j++)
+            {
+              int point = edgeByNodes.nodeIds[j];
+              found = false;
+              for (int k = 0; k < npts; k++)
+                {
+                  if (nodeSet[k] == point)
+                    {
+                      found = true;
+                      break;
+                    }
+                }
+              if (!found)
+                break;
+            }
+          if (found)
+            return edges[i];
+        }
+    }
+  return -1;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_Down3D::SMDS_Down3D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
+  SMDS_Downward(grid, nbDownCells)
+{
+}
+
+SMDS_Down3D::~SMDS_Down3D()
+{
+}
+
+void SMDS_Down3D::allocate(int nbElems)
+{
+  if (nbElems >= _vtkCellIds.size())
+    {
+      _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
+      _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
+    }
+}
+
+void SMDS_Down3D::compactStorage()
+{
+  // nothing to do, size was known before
+}
+
+int SMDS_Down3D::getNumberOfUpCells(int cellId)
+{
+  return 0;
+}
+
+const int* SMDS_Down3D::getUpCells(int cellId)
+{
+  return 0;
+}
+
+const unsigned char* SMDS_Down3D::getUpTypes(int cellId)
+{
+  return 0;
+}
+
+int SMDS_Down3D::FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes)
+{
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  int faceNodeSet[10];
+  int npoints = 0;
+
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if ((faces[i] >= 0) && (faceByNodes.vtkType == _cellTypes[i]))
+        {
+          if (npoints == 0)
+            {
+              for (int j = 0; j < faceByNodes.nbNodes; j++)
+                faceNodeSet[j] = faceByNodes.nodeIds[j];
+              npoints = faceByNodes.nbNodes;
+            }
+
+          int nodeSet[10];
+          int npts = this->_grid->getDownArray(faceByNodes.vtkType)->getNodeSet(faces[i], nodeSet);
+          if (npts != npoints)
+            continue; // skip this face
+          bool found = false;
+          for (int j = 0; j < npts; j++)
+            {
+              int point = faceByNodes.nodeIds[j];
+              found = false;
+              for (int k = 0; k < npts; k++)
+                {
+                  if (nodeSet[k] == point)
+                    {
+                      found = true;
+                      break; // point j is in the 2 faces, skip remaining k values
+                    }
+                }
+              if (!found)
+                break; // point j is not in the 2 faces, skip the remaining tests
+            }
+          if (found)
+            return faces[i];
+        }
+    }
+  return -1;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownEdge::SMDS_DownEdge(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down1D(grid, 2)
+{
+  _cellTypes.push_back(VTK_VERTEX);
+  _cellTypes.push_back(VTK_VERTEX);
+}
+
+SMDS_DownEdge::~SMDS_DownEdge()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadEdge::SMDS_DownQuadEdge(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down1D(grid, 3)
+{
+  _cellTypes.push_back(VTK_VERTEX);
+  _cellTypes.push_back(VTK_VERTEX);
+  _cellTypes.push_back(VTK_VERTEX);
+}
+
+SMDS_DownQuadEdge::~SMDS_DownQuadEdge()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownTriangle::SMDS_DownTriangle(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down2D(grid, 3)
+{
+  _cellTypes.push_back(VTK_LINE);
+  _cellTypes.push_back(VTK_LINE);
+  _cellTypes.push_back(VTK_LINE);
+  _nbNodes = 3;
+}
+
+SMDS_DownTriangle::~SMDS_DownTriangle()
+{
+}
+
+void SMDS_DownTriangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
+{
+  int *nodes = &_tempNodes[_nbNodes * cellId];
+  edgesWithNodes.nbElems = 3;
+
+  edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  edgesWithNodes.elems[0].nbNodes = 2;
+  edgesWithNodes.elems[0].vtkType = VTK_LINE;
+
+  edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  edgesWithNodes.elems[1].nbNodes = 2;
+  edgesWithNodes.elems[1].vtkType = VTK_LINE;
+
+  edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
+  edgesWithNodes.elems[2].nodeIds[1] = nodes[0];
+  edgesWithNodes.elems[2].nbNodes = 2;
+  edgesWithNodes.elems[2].vtkType = VTK_LINE;
+}
+
+void SMDS_DownTriangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_LINE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadTriangle::SMDS_DownQuadTriangle(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down2D(grid, 3)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _nbNodes = 6;
+}
+
+SMDS_DownQuadTriangle::~SMDS_DownQuadTriangle()
+{
+}
+
+void SMDS_DownQuadTriangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
+{
+  int *nodes = &_tempNodes[_nbNodes * cellId];
+  edgesWithNodes.nbElems = 3;
+
+  edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  edgesWithNodes.elems[0].nodeIds[2] = nodes[3];
+  edgesWithNodes.elems[0].nbNodes = 3;
+  edgesWithNodes.elems[0].vtkType = VTK_QUADRATIC_EDGE;
+
+  edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  edgesWithNodes.elems[1].nodeIds[2] = nodes[4];
+  edgesWithNodes.elems[1].nbNodes = 3;
+  edgesWithNodes.elems[1].vtkType = VTK_QUADRATIC_EDGE;
+
+  edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
+  edgesWithNodes.elems[2].nodeIds[1] = nodes[0];
+  edgesWithNodes.elems[2].nodeIds[2] = nodes[5];
+  edgesWithNodes.elems[2].nbNodes = 3;
+  edgesWithNodes.elems[2].vtkType = VTK_QUADRATIC_EDGE;
+}
+
+void SMDS_DownQuadTriangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_QUADRATIC_EDGE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadrangle::SMDS_DownQuadrangle(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down2D(grid, 4)
+{
+  _cellTypes.push_back(VTK_LINE);
+  _cellTypes.push_back(VTK_LINE);
+  _cellTypes.push_back(VTK_LINE);
+  _cellTypes.push_back(VTK_LINE);
+  _nbNodes = 4;
+}
+
+SMDS_DownQuadrangle::~SMDS_DownQuadrangle()
+{
+}
+
+void SMDS_DownQuadrangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
+{
+  int *nodes = &_tempNodes[_nbNodes * cellId];
+  edgesWithNodes.nbElems = 4;
+
+  edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  edgesWithNodes.elems[0].nbNodes = 2;
+  edgesWithNodes.elems[0].vtkType = VTK_LINE;
+
+  edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  edgesWithNodes.elems[1].nbNodes = 2;
+  edgesWithNodes.elems[1].vtkType = VTK_LINE;
+
+  edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
+  edgesWithNodes.elems[2].nodeIds[1] = nodes[3];
+  edgesWithNodes.elems[2].nbNodes = 2;
+  edgesWithNodes.elems[2].vtkType = VTK_LINE;
+
+  edgesWithNodes.elems[3].nodeIds[0] = nodes[3];
+  edgesWithNodes.elems[3].nodeIds[1] = nodes[0];
+  edgesWithNodes.elems[3].nbNodes = 2;
+  edgesWithNodes.elems[3].vtkType = VTK_LINE;
+}
+
+void SMDS_DownQuadrangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_LINE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadQuadrangle::SMDS_DownQuadQuadrangle(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down2D(grid, 4)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _cellTypes.push_back(VTK_QUADRATIC_EDGE);
+  _nbNodes = 8;
+}
+
+SMDS_DownQuadQuadrangle::~SMDS_DownQuadQuadrangle()
+{
+}
+
+void SMDS_DownQuadQuadrangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
+{
+  int *nodes = &_tempNodes[_nbNodes * cellId];
+  edgesWithNodes.nbElems = 4;
+
+  edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  edgesWithNodes.elems[0].nodeIds[2] = nodes[4];
+  edgesWithNodes.elems[0].nbNodes = 3;
+  edgesWithNodes.elems[0].vtkType = VTK_QUADRATIC_EDGE;
+
+  edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  edgesWithNodes.elems[1].nodeIds[2] = nodes[5];
+  edgesWithNodes.elems[1].nbNodes = 3;
+  edgesWithNodes.elems[1].vtkType = VTK_QUADRATIC_EDGE;
+
+  edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
+  edgesWithNodes.elems[2].nodeIds[1] = nodes[3];
+  edgesWithNodes.elems[2].nodeIds[2] = nodes[6];
+  edgesWithNodes.elems[2].nbNodes = 3;
+  edgesWithNodes.elems[2].vtkType = VTK_QUADRATIC_EDGE;
+
+  edgesWithNodes.elems[3].nodeIds[0] = nodes[3];
+  edgesWithNodes.elems[3].nodeIds[1] = nodes[0];
+  edgesWithNodes.elems[3].nodeIds[2] = nodes[7];
+  edgesWithNodes.elems[3].nbNodes = 3;
+  edgesWithNodes.elems[3].vtkType = VTK_QUADRATIC_EDGE;
+}
+
+void SMDS_DownQuadQuadrangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_QUADRATIC_EDGE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownTetra::SMDS_DownTetra(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 4)
+{
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+}
+
+SMDS_DownTetra::~SMDS_DownTetra()
+{
+}
+
+void SMDS_DownTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_TRIANGLE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The linear tetrahedron is defined by four points.
+ * @see vtkTetra.h in Filtering.
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownTetra::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 4;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nbNodes = 3;
+  facesWithNodes.elems[0].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[1].nbNodes = 3;
+  facesWithNodes.elems[1].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[2].nbNodes = 3;
+  facesWithNodes.elems[2].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[3].nbNodes = 3;
+  facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadTetra::SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 4)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+}
+
+SMDS_DownQuadTetra::~SMDS_DownQuadTetra()
+{
+}
+
+void SMDS_DownQuadTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The ordering of the ten points defining the quadratic tetrahedron cell is point id's (0-3,4-9)
+ * where id's 0-3 are the four tetrahedron vertices;
+ * and point id's 4-9 are the mid-edge nodes between (0,1), (1,2), (2,0), (0,3), (1,3), and (2,3).
+ * @see vtkQuadraticTetra.h in Filtering.
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownQuadTetra::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 4;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[0].nodeIds[4] = nodes[5];
+  facesWithNodes.elems[0].nodeIds[5] = nodes[6];
+  facesWithNodes.elems[0].nbNodes = 6;
+  facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[1].nodeIds[4] = nodes[7];
+  facesWithNodes.elems[1].nodeIds[5] = nodes[8];
+  facesWithNodes.elems[1].nbNodes = 6;
+  facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[6];
+  facesWithNodes.elems[2].nodeIds[4] = nodes[7];
+  facesWithNodes.elems[2].nodeIds[5] = nodes[9];
+  facesWithNodes.elems[2].nbNodes = 6;
+  facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[3];
+  facesWithNodes.elems[3].nodeIds[3] = nodes[5];
+  facesWithNodes.elems[3].nodeIds[4] = nodes[8];
+  facesWithNodes.elems[3].nodeIds[5] = nodes[9];
+  facesWithNodes.elems[3].nbNodes = 6;
+  facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownPyramid::SMDS_DownPyramid(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 5)
+{
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+}
+
+SMDS_DownPyramid::~SMDS_DownPyramid()
+{
+}
+
+void SMDS_DownPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  if (aType == VTK_QUAD)
+    {
+      if (faces[0] < 0)
+        {
+          faces[0] = lowCellId;
+          return;
+        }
+      if (faces[0] == lowCellId)
+        return;
+    }
+  else
+    {
+      //ASSERT(aType == VTK_TRIANGLE);
+      for (int i = 1; i < _nbDownCells; i++)
+        {
+          if (faces[i] < 0)
+            {
+              faces[i] = lowCellId;
+              return;
+            }
+          if (faces[i] == lowCellId)
+            return;
+        }
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The pyramid is defined by the five points (0-4) where (0,1,2,3) is the base of the pyramid which,
+ * using the right hand rule, forms a quadrilateral whose normal points in the direction of the
+ * pyramid apex at vertex #4.
+ * @see vtkPyramid.h in Filtering.
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownPyramid::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 5;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nbNodes = 4;
+  facesWithNodes.elems[0].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[1].nbNodes = 3;
+  facesWithNodes.elems[1].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[2].nbNodes = 3;
+  facesWithNodes.elems[2].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[3];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[3].nbNodes = 3;
+  facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[0];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[4].nbNodes = 3;
+  facesWithNodes.elems[4].vtkType = VTK_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadPyramid::SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 5)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+}
+
+SMDS_DownQuadPyramid::~SMDS_DownQuadPyramid()
+{
+}
+
+void SMDS_DownQuadPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  if (aType == VTK_QUADRATIC_QUAD)
+    {
+      if (faces[0] < 0)
+        {
+          faces[0] = lowCellId;
+          return;
+        }
+      if (faces[0] == lowCellId)
+        return;
+    }
+  else
+    {
+      //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
+      for (int i = 1; i < _nbDownCells; i++)
+        {
+          if (faces[i] < 0)
+            {
+              faces[i] = lowCellId;
+              return;
+            }
+          if (faces[i] == lowCellId)
+            return;
+        }
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The ordering of the thirteen points defining the quadratic pyramid cell is point id's (0-4,5-12)
+ * where point id's 0-4 are the five corner vertices of the pyramid; followed
+ * by eight mid-edge nodes (5-12). Note that these mid-edge nodes lie on the edges defined by
+ * 5(0,1), 6(1,2), 7(2,3), 8(3,0), 9(0,4), 10(1,4), 11(2,4), 12(3,4).
+ * @see vtkQuadraticPyramid.h in Filtering.
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownQuadPyramid::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 5;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nodeIds[4] = nodes[5];
+  facesWithNodes.elems[0].nodeIds[5] = nodes[6];
+  facesWithNodes.elems[0].nodeIds[6] = nodes[7];
+  facesWithNodes.elems[0].nodeIds[7] = nodes[8];
+  facesWithNodes.elems[0].nbNodes = 8;
+  facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[5];
+  facesWithNodes.elems[1].nodeIds[4] = nodes[9];
+  facesWithNodes.elems[1].nodeIds[5] = nodes[10];
+  facesWithNodes.elems[1].nbNodes = 6;
+  facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[6];
+  facesWithNodes.elems[2].nodeIds[4] = nodes[10];
+  facesWithNodes.elems[2].nodeIds[5] = nodes[11];
+  facesWithNodes.elems[2].nbNodes = 6;
+  facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[3];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[3].nodeIds[3] = nodes[7];
+  facesWithNodes.elems[3].nodeIds[4] = nodes[11];
+  facesWithNodes.elems[3].nodeIds[5] = nodes[12];
+  facesWithNodes.elems[3].nbNodes = 6;
+  facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[0];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[4].nodeIds[3] = nodes[8];
+  facesWithNodes.elems[4].nodeIds[4] = nodes[9];
+  facesWithNodes.elems[4].nodeIds[5] = nodes[12];
+  facesWithNodes.elems[4].nbNodes = 6;
+  facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownPenta::SMDS_DownPenta(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 5)
+{
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_TRIANGLE);
+  _cellTypes.push_back(VTK_TRIANGLE);
+}
+
+SMDS_DownPenta::~SMDS_DownPenta()
+{
+}
+
+void SMDS_DownPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  if (aType == VTK_QUAD)
+    for (int i = 0; i < 2; i++)
+      {
+        if (faces[i] < 0)
+          {
+            faces[i] = lowCellId;
+            return;
+          }
+        if (faces[i] == lowCellId)
+          return;
+      }
+  else
+    {
+      //ASSERT(aType == VTK_TRIANGLE);
+      for (int i = 2; i < _nbDownCells; i++)
+        {
+          if (faces[i] < 0)
+            {
+              faces[i] = lowCellId;
+              return;
+            }
+          if (faces[i] == lowCellId)
+            return;
+        }
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's.
+ * A wedge or pentahedron consists of two triangular and three quadrilateral faces
+ * and is defined by the six points (0-5) where (0,1,2) is the base of the wedge which,
+ * using the right hand rule, forms a triangle whose normal points outward
+ * (away from the triangular face (3,4,5)).
+ * @see vtkWedge.h in Filtering
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownPenta::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 5;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nbNodes = 4;
+  facesWithNodes.elems[0].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[1].nbNodes = 4;
+  facesWithNodes.elems[1].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[2].nbNodes = 4;
+  facesWithNodes.elems[2].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[3].nbNodes = 3;
+  facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[4];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[4].nbNodes = 3;
+  facesWithNodes.elems[4].vtkType = VTK_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadPenta::SMDS_DownQuadPenta(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 5)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+  _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
+}
+
+SMDS_DownQuadPenta::~SMDS_DownQuadPenta()
+{
+}
+
+void SMDS_DownQuadPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0) && (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  if (aType == VTK_QUADRATIC_QUAD)
+    for (int i = 0; i < 2; i++)
+      {
+        if (faces[i] < 0)
+          {
+            faces[i] = lowCellId;
+            return;
+          }
+        if (faces[i] == lowCellId)
+          return;
+      }
+  else
+    {
+      //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
+      for (int i = 2; i < _nbDownCells; i++)
+        {
+          if (faces[i] < 0)
+            {
+              faces[i] = lowCellId;
+              return;
+            }
+          if (faces[i] == lowCellId)
+            return;
+        }
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The quadratic wedge (or pentahedron) is defined by fifteen points.
+ * The ordering of the fifteen points defining the cell is point id's (0-5,6-14)
+ * where point id's 0-5 are the six corner vertices of the wedge, followed by
+ * nine mid-edge nodes (6-14). Note that these mid-edge nodes lie on the edges defined by
+ * (0,1), (1,2), (2,0), (3,4), (4,5), (5,3), (0,3), (1,4), (2,5).
+ * @see vtkQuadraticWedge.h in Filtering
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownQuadPenta::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 5;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nodeIds[4] = nodes[8];
+  facesWithNodes.elems[0].nodeIds[5] = nodes[14];
+  facesWithNodes.elems[0].nodeIds[6] = nodes[11];
+  facesWithNodes.elems[0].nodeIds[7] = nodes[12];
+  facesWithNodes.elems[0].nbNodes = 8;
+  facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[1].nodeIds[4] = nodes[7];
+  facesWithNodes.elems[1].nodeIds[5] = nodes[14];
+  facesWithNodes.elems[1].nodeIds[6] = nodes[10];
+  facesWithNodes.elems[1].nodeIds[7] = nodes[13];
+  facesWithNodes.elems[1].nbNodes = 8;
+  facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[2].nodeIds[4] = nodes[6];
+  facesWithNodes.elems[2].nodeIds[5] = nodes[13];
+  facesWithNodes.elems[2].nodeIds[6] = nodes[9];
+  facesWithNodes.elems[2].nodeIds[7] = nodes[12];
+  facesWithNodes.elems[2].nbNodes = 8;
+  facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[3] = nodes[6];
+  facesWithNodes.elems[3].nodeIds[4] = nodes[7];
+  facesWithNodes.elems[3].nodeIds[5] = nodes[8];
+  facesWithNodes.elems[3].nbNodes = 6;
+  facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[4];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[4].nodeIds[3] = nodes[9];
+  facesWithNodes.elems[4].nodeIds[4] = nodes[10];
+  facesWithNodes.elems[4].nodeIds[5] = nodes[11];
+  facesWithNodes.elems[4].nbNodes = 6;
+  facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_TRIANGLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownHexa::SMDS_DownHexa(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 6)
+{
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+  _cellTypes.push_back(VTK_QUAD);
+}
+
+SMDS_DownHexa::~SMDS_DownHexa()
+{
+}
+
+void SMDS_DownHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+  // MESSAGE("-------------------------------------> trop de faces ! " << cellId << " " << lowCellId);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The hexahedron is defined by the eight points (0-7), where (0,1,2,3) is the base
+ * of the hexahedron which, using the right hand rule, forms a quadrilateral whose normal
+ * points in the direction of the opposite face (4,5,6,7).
+ * @see vtkHexahedron.h in Filtering
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownHexa::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 6;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nbNodes = 4;
+  facesWithNodes.elems[0].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[4];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[5];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[6];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[7];
+  facesWithNodes.elems[1].nbNodes = 4;
+  facesWithNodes.elems[1].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[2].nbNodes = 4;
+  facesWithNodes.elems[2].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[6];
+  facesWithNodes.elems[3].nodeIds[3] = nodes[5];
+  facesWithNodes.elems[3].nbNodes = 4;
+  facesWithNodes.elems[3].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[2];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[6];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[7];
+  facesWithNodes.elems[4].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[4].nbNodes = 4;
+  facesWithNodes.elems[4].vtkType = VTK_QUAD;
+
+  facesWithNodes.elems[5].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[5].nodeIds[1] = nodes[7];
+  facesWithNodes.elems[5].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[5].nodeIds[3] = nodes[0];
+  facesWithNodes.elems[5].nbNodes = 4;
+  facesWithNodes.elems[5].vtkType = VTK_QUAD;
+}
+
+// ---------------------------------------------------------------------------
+
+SMDS_DownQuadHexa::SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid) :
+  SMDS_Down3D(grid, 6)
+{
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+  _cellTypes.push_back(VTK_QUADRATIC_QUAD);
+}
+
+SMDS_DownQuadHexa::~SMDS_DownQuadHexa()
+{
+}
+
+void SMDS_DownQuadHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
+{
+  //ASSERT((cellId >=0)&& (cellId < _maxId));
+  int *faces = &_cellIds[_nbDownCells * cellId];
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      if (faces[i] < 0)
+        {
+          faces[i] = lowCellId;
+          return;
+        }
+      if (faces[i] == lowCellId)
+        return;
+    }
+  ASSERT(0);
+}
+
+/*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
+ * The ordering of the twenty points defining the quadratic hexahedron cell is point id's (0-7,8-19)
+ * where point id's 0-7 are the eight corner vertices of the cube, followed by twelve mid-edge nodes (8-19).
+ * Note that these mid-edge nodes lie on the edges defined by
+ * (0,1), (1,2), (2,3), (3,0), (4,5), (5,6), (6,7), (7,4), (0,4), (1,5), (2,6), (3,7).
+ * @see vtkQuadraticHexahedron.h in Filtering
+ * @param cellId volumeId in vtkUnstructuredGrid
+ * @param facesWithNodes vector of face descriptors to be filled
+ */
+void SMDS_DownQuadHexa::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
+{
+  // --- find point id's of the volume
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(cellId, npts, nodes);
+
+  // --- create all the ordered list of node id's for each face
+
+  facesWithNodes.nbElems = 6;
+
+  facesWithNodes.elems[0].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[0].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[0].nodeIds[2] = nodes[2];
+  facesWithNodes.elems[0].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[0].nodeIds[4] = nodes[8];
+  facesWithNodes.elems[0].nodeIds[5] = nodes[9];
+  facesWithNodes.elems[0].nodeIds[6] = nodes[10];
+  facesWithNodes.elems[0].nodeIds[7] = nodes[11];
+  facesWithNodes.elems[0].nbNodes = 8;
+  facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[1].nodeIds[0] = nodes[4];
+  facesWithNodes.elems[1].nodeIds[1] = nodes[5];
+  facesWithNodes.elems[1].nodeIds[2] = nodes[6];
+  facesWithNodes.elems[1].nodeIds[3] = nodes[7];
+  facesWithNodes.elems[1].nodeIds[4] = nodes[12];
+  facesWithNodes.elems[1].nodeIds[5] = nodes[13];
+  facesWithNodes.elems[1].nodeIds[6] = nodes[14];
+  facesWithNodes.elems[1].nodeIds[7] = nodes[15];
+  facesWithNodes.elems[1].nbNodes = 8;
+  facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[2].nodeIds[0] = nodes[0];
+  facesWithNodes.elems[2].nodeIds[1] = nodes[1];
+  facesWithNodes.elems[2].nodeIds[2] = nodes[5];
+  facesWithNodes.elems[2].nodeIds[3] = nodes[4];
+  facesWithNodes.elems[2].nodeIds[4] = nodes[8];
+  facesWithNodes.elems[2].nodeIds[5] = nodes[17];
+  facesWithNodes.elems[2].nodeIds[6] = nodes[12];
+  facesWithNodes.elems[2].nodeIds[7] = nodes[16];
+  facesWithNodes.elems[2].nbNodes = 8;
+  facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[3].nodeIds[0] = nodes[1];
+  facesWithNodes.elems[3].nodeIds[1] = nodes[2];
+  facesWithNodes.elems[3].nodeIds[2] = nodes[6];
+  facesWithNodes.elems[3].nodeIds[3] = nodes[5];
+  facesWithNodes.elems[3].nodeIds[4] = nodes[9];
+  facesWithNodes.elems[3].nodeIds[5] = nodes[18];
+  facesWithNodes.elems[3].nodeIds[6] = nodes[13];
+  facesWithNodes.elems[3].nodeIds[7] = nodes[17];
+  facesWithNodes.elems[3].nbNodes = 8;
+  facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[4].nodeIds[0] = nodes[2];
+  facesWithNodes.elems[4].nodeIds[1] = nodes[6];
+  facesWithNodes.elems[4].nodeIds[2] = nodes[7];
+  facesWithNodes.elems[4].nodeIds[3] = nodes[3];
+  facesWithNodes.elems[4].nodeIds[4] = nodes[18];
+  facesWithNodes.elems[4].nodeIds[5] = nodes[14];
+  facesWithNodes.elems[4].nodeIds[6] = nodes[19];
+  facesWithNodes.elems[4].nodeIds[7] = nodes[10];
+  facesWithNodes.elems[4].nbNodes = 8;
+  facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_QUAD;
+
+  facesWithNodes.elems[5].nodeIds[0] = nodes[3];
+  facesWithNodes.elems[5].nodeIds[1] = nodes[7];
+  facesWithNodes.elems[5].nodeIds[2] = nodes[4];
+  facesWithNodes.elems[5].nodeIds[3] = nodes[0];
+  facesWithNodes.elems[5].nodeIds[4] = nodes[19];
+  facesWithNodes.elems[5].nodeIds[5] = nodes[15];
+  facesWithNodes.elems[5].nodeIds[6] = nodes[16];
+  facesWithNodes.elems[5].nodeIds[7] = nodes[11];
+  facesWithNodes.elems[5].nbNodes = 8;
+  facesWithNodes.elems[5].vtkType = VTK_QUADRATIC_QUAD;
+}
+
+// ---------------------------------------------------------------------------
+
diff --git a/src/SMDS/SMDS_Downward.hxx b/src/SMDS/SMDS_Downward.hxx
new file mode 100644 (file)
index 0000000..fd4eca0
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * SMDS_Downward.hxx
+ *
+ *  Created on: Jun 3, 2010
+ *      Author: prascle
+ */
+
+#ifndef SMDS_DOWNWARD_HXX_
+#define SMDS_DOWNWARD_HXX_
+
+#include "SMDS_UnstructuredGrid.hxx"
+
+#include <vector>
+#include <set>
+
+typedef struct
+{
+  int nodeIds[8]; //!< max number of nodes in a face or edge: quad quad = 8
+  int nbNodes;
+  unsigned char vtkType;
+} ElemByNodesType; // TODO resize for polyhedrons
+
+typedef struct
+{
+  ElemByNodesType elems[6]; //!< max number of faces in a volume or edges in a face : hexahedron = 6
+  int nbElems;
+} ListElemByNodesType; // TODO resize for polyhedrons
+
+class SMDS_Downward
+{
+  friend class SMDS_UnstructuredGrid;
+  friend class SMDS_Down2D;
+  friend class SMDS_Down3D;
+public:
+  virtual int getNumberOfDownCells(int cellId);
+  virtual const int* getDownCells(int cellId);
+  virtual const unsigned char* getDownTypes(int cellId);
+  virtual int getNumberOfUpCells(int cellId) = 0;
+  virtual const int* getUpCells(int cellId) = 0;
+  virtual const unsigned char* getUpTypes(int cellId) = 0;
+  int getVtkCellId(int cellId)
+  {
+    return _vtkCellIds[cellId];
+  }
+  int getMaxId()
+  {
+    return _maxId;
+  }
+  static int getCellDimension(unsigned char cellType);
+protected:
+  SMDS_Downward(SMDS_UnstructuredGrid *grid, int nbDownCells);
+  ~SMDS_Downward();
+  int addCell(int vtkId = -1);
+  virtual void initCell(int cellId);
+  virtual void allocate(int nbElems) = 0;
+  virtual void compactStorage() = 0;
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's
+  virtual void addUpCell(int cellId, int upCellId, unsigned char aType); //!< Id's are downward connectivity id's
+  virtual int getNodeSet(int cellId, int* nodeSet);
+
+  SMDS_UnstructuredGrid* _grid;
+  int _maxId;
+  int _nbDownCells; //!< the same number for all cells of a derived class
+  std::vector<int> _cellIds; //!< growing size: all the down cell id's, size = _maxId * _nbDownCells
+  std::vector<int> _vtkCellIds; //!< growing size: size = _maxId, either vtkId or -1
+  std::vector<unsigned char> _cellTypes; //!< fixed size: the same vector for all cells of a derived class
+
+  static std::vector<int> _cellDimension; //!< conversion table: type --> dimension
+};
+
+class SMDS_Down1D: public SMDS_Downward
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+  virtual int getNumberOfUpCells(int cellId);
+  virtual const int* getUpCells(int cellId);
+  virtual const unsigned char* getUpTypes(int cellId);
+protected:
+  SMDS_Down1D(SMDS_UnstructuredGrid *grid, int nbDownCells);
+  ~SMDS_Down1D();
+  virtual void initCell(int cellId);
+  virtual void allocate(int nbElems);
+  virtual void compactStorage();
+  virtual void addUpCell(int cellId, int upCellId, unsigned char aType); //!< Id's are downward connectivity id's
+  virtual int getNodeSet(int cellId, int* nodeSet);
+  void setNodes(int cellId, int vtkId);
+  void setNodes(int cellId, const int* nodeIds);
+  int computeVtkCells(int cellId, std::vector<int>& vtkIds);
+  int computeVtkCells(int* pts, std::vector<int>& vtkIds);
+  int computeFaces(int cellId, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes);
+  int computeFaces(int* pts, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes);
+
+  std::vector<std::vector<int> > _upCellIdsVector; //!< the number of faces sharing an edge is not known
+  std::vector<std::vector<unsigned char> > _upCellTypesVector; //!< the number of faces sharing an edge is not known
+  std::vector<int> _upCellIds; //!< compacted storage after connectivity calculation
+  std::vector<unsigned char> _upCellTypes; //!< compacted storage after connectivity calculation
+  std::vector<int> _upCellIndex; //!< compacted storage after connectivity calculation
+};
+
+class SMDS_Down2D: public SMDS_Downward
+{
+  friend class SMDS_UnstructuredGrid;
+  friend class SMDS_Down1D;
+public:
+  virtual int getNumberOfUpCells(int cellId);
+  virtual const int* getUpCells(int cellId);
+  virtual const unsigned char* getUpTypes(int cellId);
+protected:
+  SMDS_Down2D(SMDS_UnstructuredGrid *grid, int nbDownCells);
+  ~SMDS_Down2D();
+  virtual void allocate(int nbElems);
+  virtual void compactStorage();
+  virtual void addUpCell(int cellId, int upCellId, unsigned char aType);
+  virtual void computeEdgesWithNodes(int cellId, ListElemByNodesType& facesWithNodes) = 0;
+  virtual int getNodeSet(int cellId, int* nodeSet);
+  int computeVolumeIds(int cellId, int* ids);
+  int computeVolumeIds(ElemByNodesType& faceByNodes, int* ids);
+  int computeVolumeIdsFromNodesFace(int* nodes, int nbNodes, int* ids);
+  void setTempNodes(int cellId, int vtkId);
+  void setTempNodes(int cellId, ElemByNodesType& faceByNodes);
+  bool isInFace(int cellId, int *pts, int npts);
+  int FindEdgeByNodes(int cellId, ElemByNodesType& edgeByNodes);
+
+  std::vector<int> _upCellIds; //!< 2 volumes max. per face
+  std::vector<unsigned char> _upCellTypes; //!< 2 volume types per face
+  std::vector<int> _tempNodes; //!< temporary storage of nodes, until downward connectivity completion
+  int _nbNodes; //!< number of nodes in a face
+};
+
+class SMDS_Down3D: public SMDS_Downward
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+  virtual int getNumberOfUpCells(int cellId);
+  virtual const int* getUpCells(int cellId);
+  virtual const unsigned char* getUpTypes(int cellId);
+protected:
+  SMDS_Down3D(SMDS_UnstructuredGrid *grid, int nbDownCells);
+  ~SMDS_Down3D();
+  virtual void allocate(int nbElems);
+  virtual void compactStorage();
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes) = 0;
+  int FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes);
+};
+
+class SMDS_DownEdge: public SMDS_Down1D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownEdge(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownEdge();
+};
+
+class SMDS_DownQuadEdge: public SMDS_Down1D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadEdge(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadEdge();
+};
+
+class SMDS_DownTriangle: public SMDS_Down2D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownTriangle(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownTriangle();
+  virtual void computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes);
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's
+};
+
+class SMDS_DownQuadTriangle: public SMDS_Down2D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadTriangle(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadTriangle();
+  virtual void computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes);
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's
+};
+
+class SMDS_DownQuadrangle: public SMDS_Down2D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadrangle(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadrangle();
+  virtual void computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes);
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's
+};
+
+class SMDS_DownQuadQuadrangle: public SMDS_Down2D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadQuadrangle(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadQuadrangle();
+  virtual void computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes);
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's
+};
+
+//class SMDS_DownPolygon: public SMDS_Down2D
+//{
+//public:
+//  SMDS_DownPolygon(SMDS_UnstructuredGrid *grid);
+//  ~SMDS_DownPolygon();
+//protected:
+//};
+
+//class SMDS_DownQuadPolygon: public SMDS_Down2D
+//{
+//public:
+//  SMDS_DownQuadPolygon(SMDS_UnstructuredGrid *grid);
+//  ~SMDS_DownQuadPolygon();
+//protected:
+//};
+
+class SMDS_DownTetra: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownTetra(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownTetra();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownQuadTetra: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadTetra();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownPyramid: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownPyramid(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownPyramid();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownQuadPyramid: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadPyramid();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownPenta: public SMDS_Down3D
+{
+public:
+  SMDS_DownPenta(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownPenta();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+protected:
+};
+
+class SMDS_DownQuadPenta: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadPenta(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadPenta();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownHexa: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownHexa(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownHexa();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+class SMDS_DownQuadHexa: public SMDS_Down3D
+{
+  friend class SMDS_UnstructuredGrid;
+public:
+protected:
+  SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid);
+  ~SMDS_DownQuadHexa();
+  virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
+  virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
+};
+
+//class SMDS_DownPolyhedra: public SMDS_Down3D
+//{
+//public:
+//  SMDS_DownPolyhedra(SMDS_UnstructuredGrid *grid);
+//  ~SMDS_DownPolyhedra();
+//protected:
+//};
+
+//class SMDS_DownQuadPolyhedra: public SMDS_Down3D
+//{
+//public:
+//  SMDS_DownQuadPolyhedra(SMDS_UnstructuredGrid *grid);
+//  ~SMDS_DownQuadPolyhedra();
+//protected:
+//};
+
+#endif /* SMDS_DOWNWARD_HXX_ */
index 017f74cfaaf2f47a1236b5dbf842462a6a388081..21d7d84b01f5008601788ecb1b57e14c45ec2122 100644 (file)
@@ -41,11 +41,11 @@ using namespace std;
 //=======================================================================
 
 SMDS_LinearEdge::SMDS_LinearEdge(const SMDS_MeshNode * node1,
-                             const SMDS_MeshNode * node2)
-{      
-    //MESSAGE("SMDS_LinearEdge " << GetID());
-       myNodes[0]=node1;
-       myNodes[1]=node2;
+                                 const SMDS_MeshNode * node2)
+{
+  //MESSAGE("SMDS_LinearEdge " << GetID());
+  myNodes[0] = node1;
+  myNodes[1] = node2;
 }
 
 //=======================================================================
@@ -55,80 +55,88 @@ SMDS_LinearEdge::SMDS_LinearEdge(const SMDS_MeshNode * node1,
 
 void SMDS_LinearEdge::Print(ostream & OS) const
 {
-       OS << "edge <" << GetID() << "> : (" << myNodes[0] << " , " << myNodes[1] <<
-               ") " << endl;
+  OS << "edge <" << GetID() << "> : (" << myNodes[0] << " , " << myNodes[1]
+      << ") " << endl;
 }
 
 int SMDS_LinearEdge::NbNodes() const
 {
-       return 2;
+  return 2;
 }
 
 int SMDS_LinearEdge::NbEdges() const
 {
-       return 1;
+  return 1;
 }
 
-class SMDS_LinearEdge_MyNodeIterator:public SMDS_ElemIterator
+class SMDS_LinearEdge_MyNodeIterator: public SMDS_ElemIterator
 {
-  const SMDS_MeshNode *const* myNodes;
+  const SMDS_MeshNode * const * myNodes;
   int myIndex;
- public:
-  SMDS_LinearEdge_MyNodeIterator(const SMDS_MeshNode * const* nodes):
-    myNodes(nodes),myIndex(0) {}
+public:
+  SMDS_LinearEdge_MyNodeIterator(const SMDS_MeshNode * const * nodes) :
+    myNodes(nodes), myIndex(0)
+  {
+  }
 
   bool more()
   {
-    return myIndex<2;
+    return myIndex < 2;
   }
 
   const SMDS_MeshElement* next()
   {
     myIndex++;
-    return myNodes[myIndex-1];
+    return myNodes[myIndex - 1];
   }
 };
 
-SMDS_ElemIteratorPtr SMDS_LinearEdge::
-       elementsIterator(SMDSAbs_ElementType type) const
+SMDS_ElemIteratorPtr SMDS_LinearEdge::elementsIterator(SMDSAbs_ElementType type) const
 {
-  switch(type)
+  switch (type)
   {
-  case SMDSAbs_Edge:
-    return SMDS_MeshElement::elementsIterator(SMDSAbs_Edge); 
-  case SMDSAbs_Node:
-    return SMDS_ElemIteratorPtr(new SMDS_LinearEdge_MyNodeIterator(myNodes));
-  default:
-    return SMDS_ElemIteratorPtr
-      (new SMDS_IteratorOfElements
-       (this,type, SMDS_ElemIteratorPtr(new SMDS_LinearEdge_MyNodeIterator(myNodes))));
+    case SMDSAbs_Edge:
+      return SMDS_MeshElement::elementsIterator(SMDSAbs_Edge);
+    case SMDSAbs_Node:
+      return SMDS_ElemIteratorPtr(new SMDS_LinearEdge_MyNodeIterator(myNodes));
+    default:
+      return SMDS_ElemIteratorPtr(
+                                  new SMDS_IteratorOfElements(
+                                                              this,
+                                                              type,
+                                                              SMDS_ElemIteratorPtr(
+                                                                                   new SMDS_LinearEdge_MyNodeIterator(
+                                                                                                                      myNodes))));
   }
 }
 
 bool operator<(const SMDS_LinearEdge & e1, const SMDS_LinearEdge & e2)
 {
-       int id11=e1.myNodes[0]->GetID();
-       int id21=e2.myNodes[0]->GetID();
-       int id12=e1.myNodes[1]->GetID();
-       int id22=e2.myNodes[1]->GetID();
-       int tmp;
-
-       if(id11>=id12) 
-       {
-               tmp=id11;
-               id11=id12;
-               id12=tmp;       
-       }
-       if(id21>=id22) 
-       {
-               tmp=id21;
-               id21=id22;
-               id22=tmp;       
-       }
-
-       if(id11<id21) return true;
-       else if(id11==id21) return (id21<id22);
-       else return false;
+  int id11 = e1.myNodes[0]->GetID();
+  int id21 = e2.myNodes[0]->GetID();
+  int id12 = e1.myNodes[1]->GetID();
+  int id22 = e2.myNodes[1]->GetID();
+  int tmp;
+
+  if (id11 >= id12)
+    {
+      tmp = id11;
+      id11 = id12;
+      id12 = tmp;
+    }
+  if (id21 >= id22)
+    {
+      tmp = id21;
+      id21 = id22;
+      id22 = tmp;
+    }
+
+  if (id11 < id21)
+    return true;
+  else if (id11 == id21)
+    return (id21 < id22);
+  else
+    return false;
 }
 
 /*!
@@ -138,7 +146,7 @@ bool operator<(const SMDS_LinearEdge & e1, const SMDS_LinearEdge & e2)
  */
 const SMDS_MeshNode* SMDS_LinearEdge::GetNode(const int ind) const
 {
-  return myNodes[ ind ];
+  return myNodes[ind];
 }
 
 //=======================================================================
@@ -147,9 +155,9 @@ const SMDS_MeshNode* SMDS_LinearEdge::GetNode(const int ind) const
 //=======================================================================
 
 bool SMDS_LinearEdge::ChangeNodes(const SMDS_MeshNode * node1,
-                                const SMDS_MeshNode * node2)
+                                  const SMDS_MeshNode * node2)
 {
-  myNodes[0]=node1;
-  myNodes[1]=node2;
+  myNodes[0] = node1;
+  myNodes[1] = node2;
   return true;
 }
index a9f89c9c9cfbae8439e0eb63722c66c9b23e6f3c..f8c7025066f5b41cfdb67defce91595b477291ac 100644 (file)
 #include "SMDS_MeshEdge.hxx"
 #include <iostream>
 
-class SMDS_EXPORT SMDS_LinearEdge:public SMDS_MeshEdge
+class SMDS_EXPORT SMDS_LinearEdge: public SMDS_MeshEdge
 {
 
-  public:
-       SMDS_LinearEdge(const SMDS_MeshNode * node1,
-                      const SMDS_MeshNode * node2);
-        bool ChangeNodes(const SMDS_MeshNode * node1,
-                         const SMDS_MeshNode * node2);
-       void Print(std::ostream & OS) const;
+public:
+  SMDS_LinearEdge(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
+  bool ChangeNodes(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
+  void Print(std::ostream & OS) const;
 
-       virtual SMDSAbs_EntityType GetEntityType() const { return SMDSEntity_Edge; }
-       int NbNodes() const;
-       int NbEdges() const;
-       friend bool operator<(const SMDS_LinearEdge& e1, const SMDS_LinearEdge& e2);
+  virtual SMDSAbs_EntityType GetEntityType() const
+  {
+    return SMDSEntity_Edge;
+  }
+  int NbNodes() const;
+  int NbEdges() const;
+  friend bool operator<(const SMDS_LinearEdge& e1, const SMDS_LinearEdge& e2);
 
   /*!
    * \brief Return node by its index
-    * \param ind - node index
-    * \retval const SMDS_MeshNode* - the node
+   * \param ind - node index
+   * \retval const SMDS_MeshNode* - the node
    */
   virtual const SMDS_MeshNode* GetNode(const int ind) const;
 
-  protected:
-       SMDS_ElemIteratorPtr
-               elementsIterator(SMDSAbs_ElementType type) const;
+protected:
+  SMDS_ElemIteratorPtr
+  elementsIterator(SMDSAbs_ElementType type) const;
 
-  protected:
-       const SMDS_MeshNode* myNodes[3];
+protected:
+  const SMDS_MeshNode* myNodes[3];
 
 };
 #endif
index bb53cb6b6b2902169f99d0dd8e8d1afba96b9751..2c2aa6ed627323d979e1df6ed7a1d3b19f9e0e63 100644 (file)
@@ -148,6 +148,7 @@ SMDS_Mesh::SMDS_Mesh()
   myIDElements.clear();
   myVtkIndex.clear();
   myGrid = SMDS_UnstructuredGrid::New();
+  myGrid->setSMDS_mesh(this);
   myGrid->Initialize();
   myGrid->Allocate();
   vtkPoints* points = vtkPoints::New();
index 2feea3d182446e17c458db127bf91020e0f27c00..4cfd2a0a7a44f0bab22436cd9f5c94b17caae8e2 100644 (file)
@@ -1,4 +1,3 @@
-
 #include "SMDS_MeshCell.hxx"
 #include "utilities.h"
 
@@ -6,12 +5,12 @@ using namespace std;
 
 int SMDS_MeshCell::nbCells = 0;
 
-
-SMDS_MeshCell::SMDS_MeshCell() : SMDS_MeshElement(-1)
+SMDS_MeshCell::SMDS_MeshCell() :
+  SMDS_MeshElement(-1)
 {
   nbCells++;
   myVtkID = -1;
-};
+}
 
 SMDS_MeshCell::~SMDS_MeshCell()
 {
index fb291d1eed7478ad9e525ef3451c12ff14abcb24..96108c0950178d23df47bd2f555de3730e5857f8 100644 (file)
@@ -7,13 +7,21 @@
  * \brief Base class for all cells
  */
 
-class SMDS_EXPORT SMDS_MeshCell:public SMDS_MeshElement
+class SMDS_EXPORT SMDS_MeshCell: public SMDS_MeshElement
 {
 public:
   SMDS_MeshCell();
   virtual ~SMDS_MeshCell();
-  inline void setVtkId(int vtkId) { myVtkID = vtkId; };
-  inline int getVtkId() const {return myVtkID; };
+  inline void setVtkId(int vtkId)
+  {
+    myVtkID = vtkId;
+  }
+
+  inline int getVtkId() const
+  {
+    return myVtkID;
+  }
+
   static int nbCells;
 protected:
   int myVtkID;
index 5eb2d6a86758c8ae6d7aecf90f82761177ed982b..34259a2e29df9ed7ef1f6497c976039f89a23e79 100644 (file)
@@ -41,9 +41,8 @@ using namespace std;
 //function : SMDS_MeshNodeIDFactory
 //purpose  : 
 //=======================================================================
-SMDS_MeshNodeIDFactory::SMDS_MeshNodeIDFactory():
-  SMDS_MeshIDFactory(),
-  myMin(0), myMax(0)
+SMDS_MeshNodeIDFactory::SMDS_MeshNodeIDFactory() :
+  SMDS_MeshIDFactory(), myMin(0), myMax(0)
 {
 }
 
@@ -53,7 +52,7 @@ SMDS_MeshNodeIDFactory::SMDS_MeshNodeIDFactory():
 //=======================================================================
 bool SMDS_MeshNodeIDFactory::BindID(int ID, SMDS_MeshElement * elem)
 {
-  updateMinMax (ID);
+  updateMinMax(ID);
   return true;
 }
 
@@ -63,10 +62,10 @@ bool SMDS_MeshNodeIDFactory::BindID(int ID, SMDS_MeshElement * elem)
 //=======================================================================
 SMDS_MeshElement* SMDS_MeshNodeIDFactory::MeshElement(int ID)
 {
-  if ((ID<0) || (ID>myMax))
+  if ((ID < 0) || (ID > myMax))
     return NULL;
   const SMDS_MeshElement* elem = GetMesh()->FindNode(ID);
-  return (SMDS_MeshElement*)(elem);
+  return (SMDS_MeshElement*) (elem);
 }
 
 //=======================================================================
@@ -77,9 +76,9 @@ void SMDS_MeshNodeIDFactory::ReleaseID(const int ID)
 {
   SMDS_MeshIDFactory::ReleaseID(ID);
   if (ID == myMax)
-    myMax = 0;     // --- force updateMinMax
+    myMax = 0; // --- force updateMinMax
   if (ID == myMin)
-    myMax = 0;     // --- force updateMinMax
+    myMax = 0; // --- force updateMinMax
 }
 
 //=======================================================================
@@ -120,7 +119,7 @@ void SMDS_MeshNodeIDFactory::updateMinMax() const
 
 SMDS_ElemIteratorPtr SMDS_MeshNodeIDFactory::elementsIterator() const
 {
-    return myMesh->elementsIterator(SMDSAbs_Node);
+  return myMesh->elementsIterator(SMDSAbs_Node);
 }
 
 void SMDS_MeshNodeIDFactory::Clear()
index 941ce66d005dc58d8adc8bd3c91f21e980a62bca..4caadf4651b5ecebddc2a137f521d9647d7c6fff 100644 (file)
@@ -35,7 +35,7 @@
 
 class SMDS_MeshElement;
 
-class SMDS_EXPORT SMDS_MeshNodeIDFactory:public SMDS_MeshIDFactory
+class SMDS_EXPORT SMDS_MeshNodeIDFactory: public SMDS_MeshIDFactory
 {
 public:
   SMDS_MeshNodeIDFactory();
@@ -51,8 +51,10 @@ protected:
   void updateMinMax() const;
   void updateMinMax(int id) const
   {
-    if (id > myMax) myMax = id;
-    if (id < myMin) myMin = id;
+    if (id > myMax)
+      myMax = id;
+    if (id < myMin)
+      myMin = id;
   }
 
   mutable int myMin, myMax;
index eef9665933c150880a77549238e1e016d0f0a763..4713a19a8fd9ca4ea584939858182f261139630b 100644 (file)
@@ -1,6 +1,9 @@
-
-
+#define CHRONODEF
 #include "SMDS_UnstructuredGrid.hxx"
+#include "SMDS_Mesh.hxx"
+#include "SMDS_MeshInfo.hxx"
+#include "SMDS_Downward.hxx"
+
 #include "utilities.h"
 
 #include <vtkCellArray.h>
@@ -14,261 +17,651 @@ using namespace std;
 
 SMDS_UnstructuredGrid* SMDS_UnstructuredGrid::New()
 {
-       MESSAGE("SMDS_UnstructuredGrid::New");
-       return new SMDS_UnstructuredGrid();
+  MESSAGE("SMDS_UnstructuredGrid::New");
+  return new SMDS_UnstructuredGrid();
 }
 
-SMDS_UnstructuredGrid::SMDS_UnstructuredGrid() : vtkUnstructuredGrid()
+SMDS_UnstructuredGrid::SMDS_UnstructuredGrid() :
+  vtkUnstructuredGrid()
 {
+  _cellIdToDownId.clear();
+  _downTypes.clear();
+  _downArray.clear();
+  _mesh = 0;
+  _counters = new counters(100);
 }
 
 SMDS_UnstructuredGrid::~SMDS_UnstructuredGrid()
 {
 }
 
-
 unsigned long SMDS_UnstructuredGrid::GetMTime()
 {
-       unsigned long mtime = vtkUnstructuredGrid::GetMTime();
-       MESSAGE("vtkUnstructuredGrid::GetMTime: " << mtime);
-       return mtime;
+  unsigned long mtime = vtkUnstructuredGrid::GetMTime();
+  MESSAGE("vtkUnstructuredGrid::GetMTime: " << mtime);
+  return mtime;
 }
 
 void SMDS_UnstructuredGrid::Update()
 {
-       MESSAGE("SMDS_UnstructuredGrid::Update");
-       return vtkUnstructuredGrid::Update();
+  MESSAGE("SMDS_UnstructuredGrid::Update");
+  return vtkUnstructuredGrid::Update();
 }
 
 void SMDS_UnstructuredGrid::UpdateInformation()
 {
-       MESSAGE("SMDS_UnstructuredGrid::UpdateInformation");
-       return vtkUnstructuredGrid::UpdateInformation();
+  MESSAGE("SMDS_UnstructuredGrid::UpdateInformation");
+  return vtkUnstructuredGrid::UpdateInformation();
+}
+
+void SMDS_UnstructuredGrid::setSMDS_mesh(SMDS_Mesh *mesh)
+{
+  _mesh = mesh;
 }
 
 void SMDS_UnstructuredGrid::compactGrid(std::vector<int>& idNodesOldToNew, int newNodeSize,
-                                                                               std::vector<int>& idCellsOldToNew, int newCellSize)
+                                        std::vector<int>& idCellsOldToNew, int newCellSize)
 {
-       MESSAGE("------------------------- SMDS_UnstructuredGrid::compactGrid " << newNodeSize << " " << newCellSize);
-
-       int startHole = 0;
-       int endHole = 0;
-       int startBloc = 0;
-       int endBloc = 0;
-       int alreadyCopied = 0;
-       int holes = 0;
-
-       typedef enum {lookHoleStart, lookHoleEnd, lookBlocEnd} enumState;
-       enumState compactState = lookHoleStart;
-
-//     if (this->Links)
-//     {
-//             this->Links->UnRegister(this);
-//             this->Links = 0;
-//     }
-
-       // --- if newNodeSize, create a new compacted vtkPoints
-
-       vtkPoints *newPoints = 0;
-       if (newNodeSize)
-       {
-               MESSAGE("-------------- compactGrid, newNodeSize " << newNodeSize);
-               newPoints = vtkPoints::New();
-               newPoints->Initialize();
-               newPoints->Allocate(newNodeSize);
-               newPoints->SetNumberOfPoints(newNodeSize);
-               int oldNodeSize = idNodesOldToNew.size();
-
-               for (int i=0; i< oldNodeSize; i++)
-               {
-                       switch(compactState)
-                       {
-                       case lookHoleStart:
-                               if (idNodesOldToNew[i] < 0)
-                               {
-                                       MESSAGE("-------------- newNodeSize, startHole " << i <<  " " << oldNodeSize);
-                                       startHole = i;
-                                       if (!alreadyCopied) // copy the first bloc
-                                       {
-                                               MESSAGE("--------- copy first nodes before hole " << i << " " << oldNodeSize);
-                                               copyNodes(newPoints, idNodesOldToNew, alreadyCopied, 0, startHole);
-                                       }
-                                       compactState = lookHoleEnd;
-                               }
-                               break;
-                       case lookHoleEnd:
-                               if (idNodesOldToNew[i] >= 0)
-                               {
-                                       MESSAGE("-------------- newNodeSize, endHole " << i <<  " " << oldNodeSize);
-                                       endHole = i;
-                                       startBloc = i;
-                                       compactState = lookBlocEnd;
-                               }
-                               break;
-                       case lookBlocEnd:
-                               if (idNodesOldToNew[i] < 0) endBloc = i; // see nbPoints below
-                               else if (i == (oldNodeSize-1)) endBloc = i+1;
-                               if (endBloc)
-                               {
-                                       MESSAGE("-------------- newNodeSize, endbloc " << endBloc <<  " " << oldNodeSize);
-                                       copyNodes(newPoints, idNodesOldToNew, alreadyCopied, startBloc, endBloc);
-                                       compactState = lookHoleStart;
-                                       startHole = i;
-                                       endHole = 0;
-                                       startBloc = 0;
-                                       endBloc = 0;
-                               }
-                               break;
-                       }
-               }
-               if (!alreadyCopied) // no hole, but shorter, no need to modify idNodesOldToNew
-               {
-                       MESSAGE("------------- newNodeSize, shorter " << oldNodeSize);
-                       copyNodes(newPoints, idNodesOldToNew, alreadyCopied, 0, newNodeSize);
-               }
-               newPoints->Squeeze();
-       }
-
-       // --- create new compacted Connectivity, Locations and Types
-
-    int oldCellSize = this->Types->GetNumberOfTuples();
-
-       vtkCellArray *newConnectivity = vtkCellArray::New();
-       newConnectivity->Initialize();
-       int oldCellDataSize = this->Connectivity->GetData()->GetSize();
-       newConnectivity->Allocate(oldCellDataSize);
-       MESSAGE("oldCellSize="<< oldCellSize << " oldCellDataSize=" << oldCellDataSize);
-
-       vtkUnsignedCharArray *newTypes = vtkUnsignedCharArray::New();
-       newTypes->Initialize();
-       //newTypes->Allocate(oldCellSize);
-       newTypes->SetNumberOfValues(newCellSize);
-
-       vtkIdTypeArray *newLocations = vtkIdTypeArray::New();
-       newLocations->Initialize();
-       //newLocations->Allocate(oldCellSize);
-       newLocations->SetNumberOfValues(newCellSize);
-
-       startHole = 0;
-       endHole = 0;
-       startBloc = 0;
-       endBloc = 0;
-       alreadyCopied = 0;
-       holes = 0;
-       compactState = lookHoleStart;
-
-       vtkIdType tmpid[50];
-       vtkIdType *pointsCell =&tmpid[0]; // --- points id to fill a new cell
-
-    for (int i=0; i<oldCellSize; i++)
+  MESSAGE("------------------------- SMDS_UnstructuredGrid::compactGrid " << newNodeSize << " " << newCellSize);CHRONO(1);
+  int startHole = 0;
+  int endHole = 0;
+  int startBloc = 0;
+  int endBloc = 0;
+  int alreadyCopied = 0;
+  int holes = 0;
+
+  typedef enum
+  {
+    lookHoleStart, lookHoleEnd, lookBlocEnd
+  } enumState;
+  enumState compactState = lookHoleStart;
+
+  //   if (this->Links)
+  //   {
+  //           this->Links->UnRegister(this);
+  //           this->Links = 0;
+  //   }
+
+  // --- if newNodeSize, create a new compacted vtkPoints
+
+  vtkPoints *newPoints = 0;
+  if (newNodeSize)
+    {
+      MESSAGE("-------------- compactGrid, newNodeSize " << newNodeSize);
+      newPoints = vtkPoints::New();
+      newPoints->Initialize();
+      newPoints->Allocate(newNodeSize);
+      newPoints->SetNumberOfPoints(newNodeSize);
+      int oldNodeSize = idNodesOldToNew.size();
+
+      for (int i = 0; i < oldNodeSize; i++)
+        {
+          switch (compactState)
+          {
+            case lookHoleStart:
+              if (idNodesOldToNew[i] < 0)
+                {
+                  MESSAGE("-------------- newNodeSize, startHole " << i << " " << oldNodeSize);
+                  startHole = i;
+                  if (!alreadyCopied) // copy the first bloc
+                    {
+                      MESSAGE("--------- copy first nodes before hole " << i << " " << oldNodeSize);
+                      copyNodes(newPoints, idNodesOldToNew, alreadyCopied, 0, startHole);
+                    }
+                  compactState = lookHoleEnd;
+                }
+              break;
+            case lookHoleEnd:
+              if (idNodesOldToNew[i] >= 0)
+                {
+                  MESSAGE("-------------- newNodeSize, endHole " << i << " " << oldNodeSize);
+                  endHole = i;
+                  startBloc = i;
+                  compactState = lookBlocEnd;
+                }
+              break;
+            case lookBlocEnd:
+              if (idNodesOldToNew[i] < 0)
+                endBloc = i; // see nbPoints below
+              else if (i == (oldNodeSize - 1))
+                endBloc = i + 1;
+              if (endBloc)
+                {
+                  MESSAGE("-------------- newNodeSize, endbloc " << endBloc << " " << oldNodeSize);
+                  copyNodes(newPoints, idNodesOldToNew, alreadyCopied, startBloc, endBloc);
+                  compactState = lookHoleStart;
+                  startHole = i;
+                  endHole = 0;
+                  startBloc = 0;
+                  endBloc = 0;
+                }
+              break;
+          }
+        }
+      if (!alreadyCopied) // no hole, but shorter, no need to modify idNodesOldToNew
+        {
+          MESSAGE("------------- newNodeSize, shorter " << oldNodeSize);
+          copyNodes(newPoints, idNodesOldToNew, alreadyCopied, 0, newNodeSize);
+        }
+      newPoints->Squeeze();
+    }
+
+  // --- create new compacted Connectivity, Locations and Types
+
+  int oldCellSize = this->Types->GetNumberOfTuples();
+
+  vtkCellArray *newConnectivity = vtkCellArray::New();
+  newConnectivity->Initialize();
+  int oldCellDataSize = this->Connectivity->GetData()->GetSize();
+  newConnectivity->Allocate(oldCellDataSize);
+  MESSAGE("oldCellSize="<< oldCellSize << " oldCellDataSize=" << oldCellDataSize);
+
+  vtkUnsignedCharArray *newTypes = vtkUnsignedCharArray::New();
+  newTypes->Initialize();
+  //newTypes->Allocate(oldCellSize);
+  newTypes->SetNumberOfValues(newCellSize);
+
+  vtkIdTypeArray *newLocations = vtkIdTypeArray::New();
+  newLocations->Initialize();
+  //newLocations->Allocate(oldCellSize);
+  newLocations->SetNumberOfValues(newCellSize);
+
+  startHole = 0;
+  endHole = 0;
+  startBloc = 0;
+  endBloc = 0;
+  alreadyCopied = 0;
+  holes = 0;
+  compactState = lookHoleStart;
+
+  vtkIdType tmpid[50];
+  vtkIdType *pointsCell = &tmpid[0]; // --- points id to fill a new cell
+
+  for (int i = 0; i < oldCellSize; i++)
+    {
+      switch (compactState)
+      {
+        case lookHoleStart:
+          if (this->Types->GetValue(i) == VTK_EMPTY_CELL)
+            {
+              MESSAGE(" -------- newCellSize, startHole " << i << " " << oldCellSize);
+              startHole = i;
+              compactState = lookHoleEnd;
+              if (!alreadyCopied) // copy the first bloc
+                {
+                  MESSAGE("--------- copy first bloc before hole " << i << " " << oldCellSize);
+                  copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell,
+                           alreadyCopied, 0, startHole);
+                }
+            }
+          break;
+        case lookHoleEnd:
+          if (this->Types->GetValue(i) != VTK_EMPTY_CELL)
+            {
+              MESSAGE(" -------- newCellSize, EndHole " << i << " " << oldCellSize);
+              endHole = i;
+              startBloc = i;
+              compactState = lookBlocEnd;
+              holes += endHole - startHole;
+              //alreadyCopied = startBloc -holes;
+            }
+          break;
+        case lookBlocEnd:
+          endBloc = 0;
+          if (this->Types->GetValue(i) == VTK_EMPTY_CELL)
+            endBloc = i;
+          else if (i == (oldCellSize - 1))
+            endBloc = i + 1;
+          if (endBloc)
+            {
+              MESSAGE(" -------- newCellSize, endBloc " << endBloc << " " << oldCellSize);
+              copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell,
+                       alreadyCopied, startBloc, endBloc);
+              compactState = lookHoleStart;
+            }
+          break;
+      }
+    }
+  if (!alreadyCopied) // no hole, but shorter
     {
-               switch(compactState)
-               {
-               case lookHoleStart:
-                       if (this->Types->GetValue(i) == VTK_EMPTY_CELL)
-                       {
-                   MESSAGE(" -------- newCellSize, startHole " << i << " " << oldCellSize);
-                               startHole = i;
-                               compactState = lookHoleEnd;
-                               if (!alreadyCopied) // copy the first bloc
-                               {
-                                       MESSAGE("--------- copy first bloc before hole " << i << " " << oldCellSize);
-                                       copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell, alreadyCopied, 0, startHole);
-                               }
-                       }
-                       break;
-               case lookHoleEnd:
-                       if (this->Types->GetValue(i) != VTK_EMPTY_CELL)
-                       {
-                   MESSAGE(" -------- newCellSize, EndHole " << i << " " << oldCellSize);
-                               endHole = i;
-                               startBloc = i;
-                               compactState = lookBlocEnd;
-                               holes += endHole - startHole;
-                               //alreadyCopied = startBloc -holes;
-                       }
-                       break;
-               case lookBlocEnd:
-                       endBloc =0;
-                       if (this->Types->GetValue(i) == VTK_EMPTY_CELL) endBloc =i;
-                       else if (i == (oldCellSize-1)) endBloc = i+1;
-                       if (endBloc)
-                       {
-                       MESSAGE(" -------- newCellSize, endBloc " << endBloc << " " << oldCellSize);
-                       copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell, alreadyCopied, startBloc, endBloc);
-                       compactState = lookHoleStart;
-                       }
-                       break;
-               }
+      MESSAGE(" -------- newCellSize, shorter " << oldCellSize);
+      copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell, alreadyCopied, 0,
+               oldCellSize);
     }
-    if (!alreadyCopied) // no hole, but shorter
+
+  newConnectivity->Squeeze();
+  //newTypes->Squeeze();
+  //newLocations->Squeeze();
+
+  if (newNodeSize)
     {
-       MESSAGE(" -------- newCellSize, shorter " << oldCellSize);
-       copyBloc(newTypes, idCellsOldToNew, idNodesOldToNew, newConnectivity, newLocations, pointsCell, alreadyCopied, 0, oldCellSize);
+      MESSAGE("------- newNodeSize, setPoints");
+      this->SetPoints(newPoints);
+      MESSAGE("NumberOfPoints: " << this->GetNumberOfPoints());
     }
+  this->SetCells(newTypes, newLocations, newConnectivity);
+  this->BuildLinks();
+}
 
-    newConnectivity->Squeeze();
-    //newTypes->Squeeze();
-    //newLocations->Squeeze();
+void SMDS_UnstructuredGrid::copyNodes(vtkPoints *newPoints, std::vector<int>& idNodesOldToNew, int& alreadyCopied,
+                                      int start, int end)
+{
+  MESSAGE("copyNodes " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start);
+  void *target = newPoints->GetVoidPointer(3 * alreadyCopied);
+  void *source = this->Points->GetVoidPointer(3 * start);
+  int nbPoints = end - start;
+  if (nbPoints > 0)
+    {
+      memcpy(target, source, 3 * sizeof(float) * nbPoints);
+      for (int j = start; j < end; j++)
+        idNodesOldToNew[j] = alreadyCopied++;
+    }
+}
 
-    if (newNodeSize)
+void SMDS_UnstructuredGrid::copyBloc(vtkUnsignedCharArray *newTypes, std::vector<int>& idCellsOldToNew,
+                                     std::vector<int>& idNodesOldToNew, vtkCellArray* newConnectivity,
+                                     vtkIdTypeArray* newLocations, vtkIdType* pointsCell, int& alreadyCopied,
+                                     int start, int end)
+{
+  MESSAGE("copyBloc " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start);
+  for (int j = start; j < end; j++)
     {
-       MESSAGE("------- newNodeSize, setPoints");
-       this->SetPoints(newPoints);
-       MESSAGE("NumberOfPoints: " << this->GetNumberOfPoints());
+      newTypes->SetValue(alreadyCopied, this->Types->GetValue(j));
+      idCellsOldToNew[j] = alreadyCopied;
+      vtkIdType oldLoc = this->Locations->GetValue(j);
+      vtkIdType nbpts;
+      vtkIdType *oldPtsCell = 0;
+      this->Connectivity->GetCell(oldLoc, nbpts, oldPtsCell);
+      //MESSAGE(j << " " << alreadyCopied << " " << (int)this->Types->GetValue(j) << " " << oldLoc << " " << nbpts );
+      for (int l = 0; l < nbpts; l++)
+        {
+          int oldval = oldPtsCell[l];
+          pointsCell[l] = idNodesOldToNew[oldval];
+          //MESSAGE("   " << oldval << " " << pointsCell[l]);
+        }
+      int newcnt = newConnectivity->InsertNextCell(nbpts, pointsCell);
+      int newLoc = newConnectivity->GetInsertLocation(nbpts);
+      //MESSAGE(newcnt << " " << newLoc);
+      newLocations->SetValue(alreadyCopied, newLoc);
+      alreadyCopied++;
     }
-    this->SetCells(newTypes, newLocations, newConnectivity);
-    this->BuildLinks();
 }
 
-void SMDS_UnstructuredGrid::copyNodes(vtkPoints *newPoints,
-               std::vector<int>& idNodesOldToNew,
-               int& alreadyCopied,
-               int start,
-               int end)
+int SMDS_UnstructuredGrid::CellIdToDownId(int vtkCellId)
+{
+  // ASSERT((vtkCellId >= 0) && (vtkCellId < _cellIdToDownId.size()));
+  return _cellIdToDownId[vtkCellId];
+}
+
+void SMDS_UnstructuredGrid::setCellIdToDownId(int vtkCellId, int downId)
 {
-       MESSAGE("copyNodes " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start);
-       void *target = newPoints->GetVoidPointer(3*alreadyCopied);
-       void *source = this->Points->GetVoidPointer(3*start);
-       int nbPoints = end - start;
-       if (nbPoints >0)
-       {
-               memcpy(target, source, 3*sizeof(float)*nbPoints);
-               for (int j=start; j<end; j++)
-                       idNodesOldToNew[j] = alreadyCopied++;
-       }
+  // ASSERT((vtkCellId >= 0) && (vtkCellId < _cellIdToDownId.size()));
+  _cellIdToDownId[vtkCellId] = downId;
 }
 
-void SMDS_UnstructuredGrid::copyBloc(vtkUnsignedCharArray *newTypes,
-               std::vector<int>& idCellsOldToNew,
-               std::vector<int>& idNodesOldToNew,
-               vtkCellArray* newConnectivity,
-               vtkIdTypeArray* newLocations,
-               vtkIdType* pointsCell,
-               int& alreadyCopied,
-               int start,
-               int end)
+/*! Build downward connectivity: to do only when needed because heavy memory load.
+ *  Downward connectivity is no more valid if vtkUnstructuredGrid is modified.
+ *
+ */
+void SMDS_UnstructuredGrid::BuildDownwardConnectivity()
 {
-       MESSAGE("copyBloc " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start);
-       for (int j=start; j<end; j++)
-       {
-               newTypes->SetValue(alreadyCopied, this->Types->GetValue(j));
-               idCellsOldToNew[j] = alreadyCopied;
-               vtkIdType oldLoc = this->Locations->GetValue(j);
-               vtkIdType nbpts;
-               vtkIdType *oldPtsCell = 0;
-               this->Connectivity->GetCell(oldLoc, nbpts, oldPtsCell);
-               //MESSAGE(j << " " << alreadyCopied << " " << (int)this->Types->GetValue(j) << " " << oldLoc << " " << nbpts );
-               for (int l=0; l<nbpts; l++)
-               {
-                       int oldval = oldPtsCell[l];
-                       pointsCell[l] = idNodesOldToNew[oldval];
-                       //MESSAGE("   " << oldval << " " << pointsCell[l]);
-               }
-               int newcnt = newConnectivity->InsertNextCell(nbpts, pointsCell);
-               int newLoc = newConnectivity->GetInsertLocation(nbpts);
-               //MESSAGE(newcnt << " " << newLoc);
-               newLocations->SetValue(alreadyCopied, newLoc);
-               alreadyCopied++;
-       }
+  MESSAGE("SMDS_UnstructuredGrid::BuildDownwardConnectivity");CHRONO(2);
+
+  // --- erase previous data if any
+
+  for (int i = 0; i < _downArray.size(); i++)
+    {
+      if (_downArray[i])
+        delete _downArray[i];
+      _downArray[i] = 0;
+    }
+  _cellIdToDownId.clear();
+
+  // --- create SMDS_Downward structures (in _downArray vector[vtkCellType])
+
+  _downArray.resize(VTK_QUADRATIC_PYRAMID + 1, 0); // --- max. type value = VTK_QUADRATIC_PYRAMID
+
+  _downArray[VTK_LINE] = new SMDS_DownEdge(this);
+  _downArray[VTK_QUADRATIC_EDGE] = new SMDS_DownQuadEdge(this);
+  _downArray[VTK_TRIANGLE] = new SMDS_DownTriangle(this);
+  _downArray[VTK_QUADRATIC_TRIANGLE] = new SMDS_DownQuadTriangle(this);
+  _downArray[VTK_QUAD] = new SMDS_DownQuadrangle(this);
+  _downArray[VTK_QUADRATIC_QUAD] = new SMDS_DownQuadQuadrangle(this);
+  _downArray[VTK_TETRA] = new SMDS_DownTetra(this);
+  _downArray[VTK_QUADRATIC_TETRA] = new SMDS_DownQuadTetra(this);
+  _downArray[VTK_PYRAMID] = new SMDS_DownPyramid(this);
+  _downArray[VTK_QUADRATIC_PYRAMID] = new SMDS_DownQuadPyramid(this);
+  _downArray[VTK_WEDGE] = new SMDS_DownPenta(this);
+  _downArray[VTK_QUADRATIC_WEDGE] = new SMDS_DownQuadPenta(this);
+  _downArray[VTK_HEXAHEDRON] = new SMDS_DownHexa(this);
+  _downArray[VTK_QUADRATIC_HEXAHEDRON] = new SMDS_DownQuadHexa(this);
+
+  // --- get detailed info of number of cells of each type, allocate SMDS_downward structures
+
+  const SMDS_MeshInfo &meshInfo = _mesh->GetMeshInfo();
+
+  int nbLinTetra = meshInfo.NbTetras(ORDER_LINEAR);
+  int nbQuadTetra = meshInfo.NbTetras(ORDER_QUADRATIC);
+  int nbLinPyra = meshInfo.NbPyramids(ORDER_LINEAR);
+  int nbQuadPyra = meshInfo.NbPyramids(ORDER_QUADRATIC);
+  int nbLinPrism = meshInfo.NbPrisms(ORDER_LINEAR);
+  int nbQuadPrism = meshInfo.NbPrisms(ORDER_QUADRATIC);
+  int nbLinHexa = meshInfo.NbHexas(ORDER_LINEAR);
+  int nbQuadHexa = meshInfo.NbHexas(ORDER_QUADRATIC);
+
+  int nbLineGuess = int((4.0 / 3.0) * nbLinTetra + 2 * nbLinPrism + 2.5 * nbLinPyra + 3 * nbLinHexa);
+  int nbQuadEdgeGuess = int((4.0 / 3.0) * nbQuadTetra + 2 * nbQuadPrism + 2.5 * nbQuadPyra + 3 * nbQuadHexa);
+  int nbLinTriaGuess = 2 * nbLinTetra + nbLinPrism + 2 * nbLinPyra;
+  int nbQuadTriaGuess = 2 * nbQuadTetra + nbQuadPrism + 2 * nbQuadPyra;
+  int nbLinQuadGuess = int((2.0 / 3.0) * nbLinPrism + (1.0 / 2.0) * nbLinPyra + 3 * nbLinHexa);
+  int nbQuadQuadGuess = int((2.0 / 3.0) * nbQuadPrism + (1.0 / 2.0) * nbQuadPyra + 3 * nbQuadHexa);
+
+  int GuessSize[VTK_QUADRATIC_TETRA];
+  GuessSize[VTK_LINE] = nbLineGuess;
+  GuessSize[VTK_QUADRATIC_EDGE] = nbQuadEdgeGuess;
+  GuessSize[VTK_TRIANGLE] = nbLinTriaGuess;
+  GuessSize[VTK_QUADRATIC_TRIANGLE] = nbQuadTriaGuess;
+  GuessSize[VTK_QUAD] = nbLinQuadGuess;
+  GuessSize[VTK_QUADRATIC_QUAD] = nbQuadQuadGuess;
+  GuessSize[VTK_TETRA] = nbLinTetra;
+  GuessSize[VTK_QUADRATIC_TETRA] = nbQuadTetra;
+  GuessSize[VTK_PYRAMID] = nbLinPyra;
+  GuessSize[VTK_QUADRATIC_PYRAMID] = nbQuadPyra;
+  GuessSize[VTK_WEDGE] = nbLinPrism;
+  GuessSize[VTK_QUADRATIC_WEDGE] = nbQuadPrism;
+  GuessSize[VTK_HEXAHEDRON] = nbLinHexa;
+  GuessSize[VTK_QUADRATIC_HEXAHEDRON] = nbQuadHexa;
+
+  _downArray[VTK_LINE]->allocate(nbLineGuess);
+  _downArray[VTK_QUADRATIC_EDGE]->allocate(nbQuadEdgeGuess);
+  _downArray[VTK_TRIANGLE]->allocate(nbLinTriaGuess);
+  _downArray[VTK_QUADRATIC_TRIANGLE]->allocate(nbQuadTriaGuess);
+  _downArray[VTK_QUAD]->allocate(nbLinQuadGuess);
+  _downArray[VTK_QUADRATIC_QUAD]->allocate(nbQuadQuadGuess);
+  _downArray[VTK_TETRA]->allocate(nbLinTetra);
+  _downArray[VTK_QUADRATIC_TETRA]->allocate(nbQuadTetra);
+  _downArray[VTK_PYRAMID]->allocate(nbLinPyra);
+  _downArray[VTK_QUADRATIC_PYRAMID]->allocate(nbQuadPyra);
+  _downArray[VTK_WEDGE]->allocate(nbLinPrism);
+  _downArray[VTK_QUADRATIC_WEDGE]->allocate(nbQuadPrism);
+  _downArray[VTK_HEXAHEDRON]->allocate(nbLinHexa);
+  _downArray[VTK_QUADRATIC_HEXAHEDRON]->allocate(nbQuadHexa);
+
+  // --- iteration on vtkUnstructuredGrid cells, only faces
+  //     for each vtk face:
+  //       create a downward face entry with its downward id.
+  //       compute vtk volumes, create downward volumes entry.
+  //       mark face in downward volumes
+  //       mark volumes in downward face
+
+  MESSAGE("--- iteration on vtkUnstructuredGrid cells, only faces");CHRONO(20);
+  int cellSize = this->Types->GetNumberOfTuples();
+  _cellIdToDownId.resize(cellSize, -1);
+
+  for (int i = 0; i < cellSize; i++)
+    {
+      int vtkFaceType = this->GetCellType(i);
+      if (SMDS_Downward::getCellDimension(vtkFaceType) == 2)
+        {
+          int vtkFaceId = i;
+          //ASSERT(_downArray[vtkFaceType]);
+          int connFaceId = _downArray[vtkFaceType]->addCell(vtkFaceId);
+          SMDS_Down2D* downFace = static_cast<SMDS_Down2D*> (_downArray[vtkFaceType]);
+          downFace->setTempNodes(connFaceId, vtkFaceId);
+          int vols[2] = { -1, -1 };
+          int nbVolumes = downFace->computeVolumeIds(vtkFaceId, vols);
+          //MESSAGE("nbVolumes="<< nbVolumes);
+          for (int ivol = 0; ivol < nbVolumes; ivol++)
+            {
+              int vtkVolId = vols[ivol];
+              int vtkVolType = this->GetCellType(vtkVolId);
+              //ASSERT(_downArray[vtkVolType]);
+              int connVolId = _downArray[vtkVolType]->addCell(vtkVolId);
+              _downArray[vtkVolType]->addDownCell(connVolId, connFaceId, vtkFaceType);
+              _downArray[vtkFaceType]->addUpCell(connFaceId, connVolId, vtkVolType);
+              // MESSAGE("Face " << vtkFaceId << " belongs to volume " << vtkVolId);
+            }
+        }
+    }
+
+  // --- iteration on vtkUnstructuredGrid cells, only volumes
+  //     for each vtk volume:
+  //       create downward volumes entry if not already done
+  //       build a temporary list of faces described with their nodes
+  //       for each face
+  //         compute the vtk volumes containing this face
+  //         check if the face is already listed in the volumes (comparison of ordered list of nodes)
+  //         if not, create a downward face entry (resizing of structure required)
+  //         (the downward faces store a temporary list of nodes to ease the comparison)
+  //         create downward volumes entry if not already done
+  //         mark volumes in downward face
+  //         mark face in downward volumes
+
+  CHRONOSTOP(20);
+  MESSAGE("--- iteration on vtkUnstructuredGrid cells, only volumes");CHRONO(21);
+
+  for (int i = 0; i < cellSize; i++)
+    {
+      int vtkType = this->GetCellType(i);
+      if (SMDS_Downward::getCellDimension(vtkType) == 3)
+        {
+          //CHRONO(31);
+          int vtkVolId = i;
+          // MESSAGE("vtk volume " << vtkVolId);
+          //ASSERT(_downArray[vtkType]);
+          int connVolId = _downArray[vtkType]->addCell(vtkVolId);
+
+          // --- find all the faces of the volume, describe the faces by their nodes
+
+          SMDS_Down3D* downVol = static_cast<SMDS_Down3D*> (_downArray[vtkType]);
+          ListElemByNodesType facesWithNodes;
+          downVol->computeFacesWithNodes(vtkVolId, facesWithNodes);
+          // MESSAGE("vtk volume " << vtkVolId << " contains " << facesWithNodes.nbElems << " faces");
+          //CHRONOSTOP(31);
+          for (int iface = 0; iface < facesWithNodes.nbElems; iface++)
+            {
+              // --- find the volumes containing the face
+
+              //CHRONO(32);
+              int vtkFaceType = facesWithNodes.elems[iface].vtkType;
+              SMDS_Down2D* downFace = static_cast<SMDS_Down2D*> (_downArray[vtkFaceType]);
+              int vols[2] = { -1, -1 };
+              int *nodes = &facesWithNodes.elems[iface].nodeIds[0];
+              int lg = facesWithNodes.elems[iface].nbNodes;
+              int nbVolumes = downFace->computeVolumeIdsFromNodesFace(nodes, lg, vols);
+              // MESSAGE("vtk volume " << vtkVolId << " face " << iface << " belongs to " << nbVolumes << " volumes");
+
+              // --- check if face is registered in the volumes
+              //CHRONOSTOP(32);
+
+              //CHRONO(33);
+              int connFaceId = -1;
+              for (int ivol = 0; ivol < nbVolumes; ivol++)
+                {
+                  int vtkVolId2 = vols[ivol];
+                  int vtkVolType = this->GetCellType(vtkVolId2);
+                  //ASSERT(_downArray[vtkVolType]);
+                  int connVolId2 = _downArray[vtkVolType]->addCell(vtkVolId2);
+                  SMDS_Down3D* downVol2 = static_cast<SMDS_Down3D*> (_downArray[vtkVolType]);
+                  connFaceId = downVol2->FindFaceByNodes(connVolId2, facesWithNodes.elems[iface]);
+                  if (connFaceId >= 0)
+                    break; // --- face already created
+                }//CHRONOSTOP(33);
+
+              // --- if face is not registered in the volumes, create face
+
+              //CHRONO(34);
+              if (connFaceId < 0)
+                {
+                  connFaceId = _downArray[vtkFaceType]->addCell();
+                  downFace->setTempNodes(connFaceId, facesWithNodes.elems[iface]);
+                }//CHRONOSTOP(34);
+
+              // --- mark volumes in downward face and mark face in downward volumes
+
+              //CHRONO(35);
+              for (int ivol = 0; ivol < nbVolumes; ivol++)
+                {
+                  int vtkVolId2 = vols[ivol];
+                  int vtkVolType = this->GetCellType(vtkVolId2);
+                  //ASSERT(_downArray[vtkVolType]);
+                  int connVolId2 = _downArray[vtkVolType]->addCell(vtkVolId2);
+                  _downArray[vtkVolType]->addDownCell(connVolId2, connFaceId, vtkFaceType);
+                  _downArray[vtkFaceType]->addUpCell(connFaceId, connVolId2, vtkVolType);
+                  // MESSAGE(" From volume " << vtkVolId << " face " << connFaceId << " belongs to volume " << vtkVolId2);
+                }//CHRONOSTOP(35);
+            }
+        }
+    }
+
+  // --- iteration on vtkUnstructuredGrid cells, only edges
+  //     for each vtk edge:
+  //       create downward edge entry
+  //       store the nodes id's in downward edge (redundant with vtkUnstructuredGrid)
+  //       find downward faces
+  //       (from vtk faces or volumes, get downward faces, they have a temporary list of nodes)
+  //       mark edge in downward faces
+  //       mark faces in downward edge
+
+  CHRONOSTOP(21);
+  MESSAGE("--- iteration on vtkUnstructuredGrid cells, only edges");CHRONO(22);
+
+  for (int i = 0; i < cellSize; i++)
+    {
+      int vtkEdgeType = this->GetCellType(i);
+      if (SMDS_Downward::getCellDimension(vtkEdgeType) == 1)
+        {
+          int vtkEdgeId = i;
+          //ASSERT(_downArray[vtkEdgeType]);
+          int connEdgeId = _downArray[vtkEdgeType]->addCell(vtkEdgeId);
+          SMDS_Down1D* downEdge = static_cast<SMDS_Down1D*> (_downArray[vtkEdgeType]);
+          downEdge->setNodes(connEdgeId, vtkEdgeId);
+          vector<int> vtkIds;
+          int nbVtkCells = downEdge->computeVtkCells(connEdgeId, vtkIds);
+          int downFaces[100];
+          unsigned char downTypes[100];
+          int nbDownFaces = downEdge->computeFaces(connEdgeId, &vtkIds[0], nbVtkCells, downFaces, downTypes);
+          for (int n = 0; n < nbDownFaces; n++)
+            {
+              _downArray[downTypes[n]]->addDownCell(downFaces[n], connEdgeId, vtkEdgeType);
+              _downArray[vtkEdgeType]->addUpCell(connEdgeId, downFaces[n], downTypes[n]);
+            }
+        }
+    }
+
+  // --- iteration on downward faces (they are all listed now)
+  //     for each downward face:
+  //       build a temporary list of edges with their ordered list of nodes
+  //       for each edge:
+  //         find all the vtk cells containing this edge
+  //         then identify all the downward faces containing the edge, from the vtk cells
+  //         check if the edge is already listed in the faces (comparison of ordered list of nodes)
+  //         if not, create a downward edge entry with the node id's
+  //         mark edge in downward faces
+  //         mark downward faces in edge (size of list unknown, to be allocated)
+
+  CHRONOSTOP(22);CHRONO(23);
+
+  for (int vtkFaceType = 0; vtkFaceType < VTK_QUADRATIC_PYRAMID; vtkFaceType++)
+    {
+      if (SMDS_Downward::getCellDimension(vtkFaceType) != 2)
+        continue;
+
+      // --- find all the edges of the face, describe the edges by their nodes
+
+      SMDS_Down2D* downFace = static_cast<SMDS_Down2D*> (_downArray[vtkFaceType]);
+      int maxId = downFace->getMaxId();
+      for (int faceId = 0; faceId < maxId; faceId++)
+        {
+          //CHRONO(40);
+          ListElemByNodesType edgesWithNodes;
+          downFace->computeEdgesWithNodes(faceId, edgesWithNodes);
+          // MESSAGE("downward face type " << vtkFaceType << " num " << faceId << " contains " << edgesWithNodes.nbElems << " edges");
+
+          //CHRONOSTOP(40);
+          for (int iedge = 0; iedge < edgesWithNodes.nbElems; iedge++)
+            {
+
+              // --- check if the edge is already registered by exploration of the faces
+
+              //CHRONO(41);
+              vector<int> vtkIds;
+              unsigned char vtkEdgeType = edgesWithNodes.elems[iedge].vtkType;
+              int *pts = &edgesWithNodes.elems[iedge].nodeIds[0];
+              SMDS_Down1D* downEdge = static_cast<SMDS_Down1D*> (_downArray[vtkEdgeType]);
+              int nbVtkCells = downEdge->computeVtkCells(pts, vtkIds);
+              //CHRONOSTOP(41);CHRONO(42);
+              int downFaces[100];
+              unsigned char downTypes[100];
+              int nbDownFaces = downEdge->computeFaces(pts, &vtkIds[0], nbVtkCells, downFaces, downTypes);
+              //CHRONOSTOP(42);
+
+              //CHRONO(43);
+              int connEdgeId = -1;
+              for (int idf = 0; idf < nbDownFaces; idf++)
+                {
+                  int faceId2 = downFaces[idf];
+                  int faceType = downTypes[idf];
+                  //ASSERT(_downArray[faceType]);
+                  SMDS_Down2D* downFace2 = static_cast<SMDS_Down2D*> (_downArray[faceType]);
+                  connEdgeId = downFace2->FindEdgeByNodes(faceId2, edgesWithNodes.elems[iedge]);
+                  if (connEdgeId >= 0)
+                    break; // --- edge already created
+                }//CHRONOSTOP(43);
+
+              // --- if edge is not registered in the faces, create edge
+
+              if (connEdgeId < 0)
+                {
+                  //CHRONO(44);
+                  connEdgeId = _downArray[vtkEdgeType]->addCell();
+                  downEdge->setNodes(connEdgeId, edgesWithNodes.elems[iedge].nodeIds);
+                  //CHRONOSTOP(44);
+                }
+
+              // --- mark faces in downward edge and mark edge in downward faces
+
+              //CHRONO(45);
+              for (int idf = 0; idf < nbDownFaces; idf++)
+                {
+                  int faceId2 = downFaces[idf];
+                  int faceType = downTypes[idf];
+                  //ASSERT(_downArray[faceType]);
+                  SMDS_Down2D* downFace2 = static_cast<SMDS_Down2D*> (_downArray[faceType]);
+                  _downArray[vtkEdgeType]->addUpCell(connEdgeId, faceId2, faceType);
+                  _downArray[faceType]->addDownCell(faceId2, connEdgeId, vtkEdgeType);
+                  // MESSAGE(" From face t:" << vtkFaceType << " " << faceId <<
+                  //  " edge " << connEdgeId << " belongs to face t:" << faceType << " " << faceId2);
+                }//CHRONOSTOP(45);
+            }
+        }
+    }
+
+  CHRONOSTOP(23);CHRONO(24);
+
+  // compact downward connectivity structure: adjust downward arrays size, replace vector<vector int>> by a single vector<int>
+  // 3D first then 2D and last 1D to release memory before edge upCells reorganization, (temporary memory use)
+
+  for (int vtkType = VTK_QUADRATIC_PYRAMID; vtkType >= 0; vtkType--)
+    {
+      if (SMDS_Downward *down = _downArray[vtkType])
+        {
+          down->compactStorage();
+        }
+    }
+
+  // --- Statistics
+
+  for (int vtkType = 0; vtkType <= VTK_QUADRATIC_PYRAMID; vtkType++)
+    {
+      if (SMDS_Downward *down = _downArray[vtkType])
+        {
+          if (down->getMaxId())
+            {
+              MESSAGE("Cells of Type " << vtkType << " : number of entities, est: "
+                  << GuessSize[vtkType] << " real: " << down->getMaxId());
+            }
+        }
+    }CHRONOSTOP(24);CHRONOSTOP(2);
+  _counters->stats();
 }
index 87ae00eb75e4d6693fb2c81c5824ab25d7e3280f..30a0747537d8db88ac7e2e53e09231bcbe4c6dd4 100644 (file)
 #include <vector>
 
 #include <vtkUnstructuredGrid.h>
+#include "chrono.hxx"
+
+class SMDS_Downward;
+class SMDS_Mesh;
 
 class SMDS_UnstructuredGrid: public vtkUnstructuredGrid
 {
 public:
-       void compactGrid(std::vector<int>& idNodesOldToNew, int newNodeSize,
-                                        std::vector<int>& idCellsOldToNew, int newCellSize);
-
-       virtual unsigned long GetMTime();
-       virtual void Update();
-       virtual void UpdateInformation();
-
-    static SMDS_UnstructuredGrid* New();
+  void setSMDS_mesh(SMDS_Mesh *mesh);
+  void compactGrid(std::vector<int>& idNodesOldToNew, int newNodeSize, std::vector<int>& idCellsOldToNew,
+                   int newCellSize);
+
+  virtual unsigned long GetMTime();
+  virtual void Update();
+  virtual void UpdateInformation();
+
+  int CellIdToDownId(int vtkCellId);
+  void setCellIdToDownId(int vtkCellId, int downId);
+  void BuildDownwardConnectivity();
+  vtkCellLinks* GetLinks()
+  {
+    return Links;
+  }
+  SMDS_Downward* getDownArray(unsigned char vtkType)
+  {
+    return _downArray[vtkType];
+  }
+  static SMDS_UnstructuredGrid* New();
 protected:
-    SMDS_UnstructuredGrid();
-    ~SMDS_UnstructuredGrid();
-    void copyNodes(vtkPoints *newPoints,
-               std::vector<int>& idNodesOldToNew,
-               int& alreadyCopied,
-               int start,
-               int end);
-       void copyBloc(vtkUnsignedCharArray *newTypes,
-                       std::vector<int>& idCellsOldToNew,
-                       std::vector<int>& idNodesOldToNew,
-                       vtkCellArray* newConnectivity,
-                       vtkIdTypeArray* newLocations,
-                       vtkIdType* pointsCell,
-                       int& alreadyCopied,
-                       int start,
-                       int end);
-
+  SMDS_UnstructuredGrid();
+  ~SMDS_UnstructuredGrid();
+  void copyNodes(vtkPoints *newPoints, std::vector<int>& idNodesOldToNew, int& alreadyCopied, int start, int end);
+  void copyBloc(vtkUnsignedCharArray *newTypes, std::vector<int>& idCellsOldToNew, std::vector<int>& idNodesOldToNew,
+                vtkCellArray* newConnectivity, vtkIdTypeArray* newLocations, vtkIdType* pointsCell, int& alreadyCopied,
+                int start, int end);
+
+  SMDS_Mesh *_mesh;
+  std::vector<int> _cellIdToDownId; //!< convert vtk Id to downward[vtkType] id, initialized with -1
+  std::vector<unsigned char> _downTypes;
+  std::vector<SMDS_Downward*> _downArray;
+  counters *_counters;
 };
 
 #endif /* _SMDS_UNSTRUCTUREDGRID_HXX */
index 1d0138f1be067e767fd7c908a3b2061ce38e50df..d888a58bae699268ba3523c8a69c6e99678514df 100644 (file)
@@ -1,6 +1,7 @@
 #include "SMDS_VtkCellIterator.hxx"
 
-SMDS_VtkCellIterator::SMDS_VtkCellIterator(SMDS_Mesh* mesh, int vtkCellId, SMDSAbs_EntityType aType) :
+SMDS_VtkCellIterator::SMDS_VtkCellIterator(SMDS_Mesh* mesh, int vtkCellId,
+                                           SMDSAbs_EntityType aType) :
   _mesh(mesh), _cellId(vtkCellId), _index(0), _type(aType)
 {
   vtkUnstructuredGrid* grid = _mesh->getGrid();
@@ -11,62 +12,62 @@ SMDS_VtkCellIterator::SMDS_VtkCellIterator(SMDS_Mesh* mesh, int vtkCellId, SMDSA
   switch (_type)
   {
     case SMDSEntity_Tetra:
-    {
-      this->exchange(1, 2);
-      break;
-    }
+      {
+        this->exchange(1, 2);
+        break;
+      }
     case SMDSEntity_Pyramid:
-    {
-      this->exchange(1, 3);
-      break;
-    }
+      {
+        this->exchange(1, 3);
+        break;
+      }
     case SMDSEntity_Penta:
-    {
-      //this->exchange(1, 2);
-      //this->exchange(4, 5);
-      break;
-    }
+      {
+        //this->exchange(1, 2);
+        //this->exchange(4, 5);
+        break;
+      }
     case SMDSEntity_Hexa:
-    {
-      this->exchange(1, 3);
-      this->exchange(5, 7);
-      break;
-    }
+      {
+        this->exchange(1, 3);
+        this->exchange(5, 7);
+        break;
+      }
     case SMDSEntity_Quad_Tetra:
-    {
-      this->exchange(1, 2);
-      this->exchange(4, 6);
-      this->exchange(8, 9);
-      break;
-    }
+      {
+        this->exchange(1, 2);
+        this->exchange(4, 6);
+        this->exchange(8, 9);
+        break;
+      }
     case SMDSEntity_Quad_Pyramid:
-    {
-      this->exchange(1, 3);
-      this->exchange(5, 8);
-      this->exchange(6, 7);
-      this->exchange(10, 12);
-      break;
-    }
+      {
+        this->exchange(1, 3);
+        this->exchange(5, 8);
+        this->exchange(6, 7);
+        this->exchange(10, 12);
+        break;
+      }
     case SMDSEntity_Quad_Penta:
-    {
-      //this->exchange(1, 2);
-      //this->exchange(4, 5);
-      //this->exchange(6, 8);
-      //this->exchange(9, 11);
-      //this->exchange(13, 14);
-      break;
-    }
+      {
+        //this->exchange(1, 2);
+        //this->exchange(4, 5);
+        //this->exchange(6, 8);
+        //this->exchange(9, 11);
+        //this->exchange(13, 14);
+        break;
+      }
     case SMDSEntity_Quad_Hexa:
-    {
-      this->exchange(1, 3);
-      this->exchange(5, 7);
-      this->exchange(8, 11);
-      this->exchange(9, 10);
-      this->exchange(12, 15);
-      this->exchange(13, 14);
-      this->exchange(17, 19);
-      break;
-    }
+      {
+        this->exchange(1, 3);
+        this->exchange(5, 7);
+        this->exchange(8, 11);
+        this->exchange(9, 10);
+        this->exchange(12, 15);
+        this->exchange(13, 14);
+        this->exchange(17, 19);
+        break;
+      }
     default:
       break;
   }
index 3a98cfac9d8defe6ee0e3708650f8bcd78fc12be..537c76d2c841fbfa77212007a219f070a4ed0d82 100644 (file)
@@ -8,16 +8,21 @@
 #include <vtkCell.h>
 #include <vtkIdList.h>
 
-class SMDS_VtkCellIterator : public SMDS_ElemIterator
+class SMDS_VtkCellIterator: public SMDS_ElemIterator
 {
 public:
-  SMDS_VtkCellIterator(SMDS_Mesh* mesh, int vtkCellId, SMDSAbs_EntityType aType);
+      SMDS_VtkCellIterator(SMDS_Mesh* mesh, int vtkCellId,
+                           SMDSAbs_EntityType aType);
   virtual ~SMDS_VtkCellIterator();
   virtual bool more();
   virtual const SMDS_MeshElement* next();
-  inline void exchange(vtkIdType a, vtkIdType b) { vtkIdType t = _vtkIdList->GetId(a);
-                                                                                                  _vtkIdList->SetId(a, _vtkIdList->GetId(b));
-                                                   _vtkIdList->SetId(b, t); };
+  inline void exchange(vtkIdType a, vtkIdType b)
+  {
+    vtkIdType t = _vtkIdList->GetId(a);
+    _vtkIdList->SetId(a, _vtkIdList->GetId(b));
+    _vtkIdList->SetId(b, t);
+  }
+
 protected:
   SMDS_Mesh* _mesh;
   int _cellId;
index 3b3e25882f96487de422da2bb89f9e345795111e..34745b44f81c3b2914cc5be365f4ccfe0cf96347 100644 (file)
@@ -16,7 +16,7 @@ SMDS_VtkEdge::SMDS_VtkEdge()
 
 SMDS_VtkEdge::SMDS_VtkEdge(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 {
-       init(nodeIds, mesh);
+  init(nodeIds, mesh);
 }
 
 SMDS_VtkEdge::~SMDS_VtkEdge()
@@ -25,53 +25,53 @@ SMDS_VtkEdge::~SMDS_VtkEdge()
 
 void SMDS_VtkEdge::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 {
-       vtkUnstructuredGrid* grid = mesh->getGrid();
-       myIdInShape = -1;
-       myMeshId = mesh->getMeshId();
-       vtkIdType aType = VTK_LINE;
-       if (nodeIds.size() == 3)
-      aType = VTK_QUADRATIC_EDGE;
-       myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
+  vtkUnstructuredGrid* grid = mesh->getGrid();
+  myIdInShape = -1;
+  myMeshId = mesh->getMeshId();
+  vtkIdType aType = VTK_LINE;
+  if (nodeIds.size() == 3)
+    aType = VTK_QUADRATIC_EDGE;
+  myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
 }
 
 bool SMDS_VtkEdge::ChangeNodes(const SMDS_MeshNode * node1,
-               const SMDS_MeshNode * node2)
+                               const SMDS_MeshNode * node2)
 {
-       return true;
+  return true;
 }
 
 void SMDS_VtkEdge::Print(std::ostream & OS) const
 {
-       OS << "edge <" << GetID() << "> : ";
+  OS << "edge <" << GetID() << "> : ";
 }
 
 int SMDS_VtkEdge::NbNodes() const
 {
-       vtkUnstructuredGrid* grid =SMDS_Mesh::_meshList[myMeshId]->getGrid();
-       int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
-       assert(nbPoints >=2);
-       return nbPoints;
+  vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
+  int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
+  assert(nbPoints >= 2);
+  return nbPoints;
 }
 
 int SMDS_VtkEdge::NbEdges() const
 {
-       return 1;
+  return 1;
 }
 
 SMDSAbs_EntityType SMDS_VtkEdge::GetEntityType() const
 {
-       if (NbNodes() == 2)
-         return SMDSEntity_Edge;
-       else
-         return SMDSEntity_Quad_Edge;
+  if (NbNodes() == 2)
+    return SMDSEntity_Edge;
+  else
+    return SMDSEntity_Quad_Edge;
 }
 
 vtkIdType SMDS_VtkEdge::GetVtkType() const
 {
-       if (NbNodes() == 2)
-               return VTK_LINE;
-       else
-               return VTK_QUADRATIC_EDGE;
+  if (NbNodes() == 2)
+    return VTK_LINE;
+  else
+    return VTK_QUADRATIC_EDGE;
 
 }
 
@@ -89,20 +89,24 @@ SMDS_VtkEdge::GetNode(const int ind) const
 bool SMDS_VtkEdge::IsQuadratic() const
 {
   if (this->NbNodes() > 2)
-       return true;
+    return true;
   else
-       return false;
+    return false;
 }
 
 SMDS_ElemIteratorPtr SMDS_VtkEdge::elementsIterator(SMDSAbs_ElementType type) const
 {
-       switch (type)
-       {
-       case SMDSAbs_Node:
-               return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(
-                               SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
-       default:
-               MESSAGE("ERROR : Iterator not implemented");
-               return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
-       }
+  switch (type)
+  {
+    case SMDSAbs_Node:
+      return SMDS_ElemIteratorPtr(
+                                  new SMDS_VtkCellIterator(
+                                                           SMDS_Mesh::_meshList[myMeshId],
+                                                           myVtkID,
+                                                           GetEntityType()));
+    default:
+      MESSAGE("ERROR : Iterator not implemented")
+      ;
+      return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
+  }
 }
index ad53647cc5512bf63cf61c851bb84ab0c0d34ab9..ade2f5ce02a6699cb51db329e94390d0c419a445 100644 (file)
@@ -15,7 +15,7 @@ SMDS_VtkFace::SMDS_VtkFace()
 
 SMDS_VtkFace::SMDS_VtkFace(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 {
-       init(nodeIds, mesh);
+  init(nodeIds, mesh);
 }
 
 SMDS_VtkFace::~SMDS_VtkFace()
@@ -24,54 +24,68 @@ SMDS_VtkFace::~SMDS_VtkFace()
 
 void SMDS_VtkFace::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 {
-       vtkUnstructuredGrid* grid = mesh->getGrid();
-       myIdInShape = -1;
-       myMeshId = mesh->getMeshId();
-       vtkIdType aType = VTK_TRIANGLE;
-       switch(nodeIds.size())
-         {
-         case  3: aType = VTK_TRIANGLE;           break;
-         case  4: aType = VTK_QUAD;               break;
-         case  6: aType = VTK_QUADRATIC_TRIANGLE; break;
-         case  8: aType = VTK_QUADRATIC_QUAD;     break;
-         default: aType = VTK_TRIANGLE; break;
-         }
-       myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
+  vtkUnstructuredGrid* grid = mesh->getGrid();
+  myIdInShape = -1;
+  myMeshId = mesh->getMeshId();
+  vtkIdType aType = VTK_TRIANGLE;
+  switch (nodeIds.size())
+  {
+    case 3:
+      aType = VTK_TRIANGLE;
+      break;
+    case 4:
+      aType = VTK_QUAD;
+      break;
+    case 6:
+      aType = VTK_QUADRATIC_TRIANGLE;
+      break;
+    case 8:
+      aType = VTK_QUADRATIC_QUAD;
+      break;
+    default:
+      aType = VTK_TRIANGLE;
+      break;
+  }
+  myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
 }
 
 bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
 {
-       return true;
+  return true;
 }
 
 void SMDS_VtkFace::Print(std::ostream & OS) const
 {
-       OS << "edge <" << GetID() << "> : ";
+  OS << "edge <" << GetID() << "> : ";
 }
 
 int SMDS_VtkFace::NbEdges() const
 {
-   switch(NbNodes())
-        {
-        case 3:
-        case 6: return 3;
-        case 4:
-        case 8: return 4;
-        default: MESSAGE("invalid number of nodes");
-        }
-   return 0;
+  switch (NbNodes())
+  {
+    case 3:
+    case 6:
+      return 3;
+    case 4:
+    case 8:
+      return 4;
+    default:
+      MESSAGE("invalid number of nodes")
+      ;
+  }
+  return 0;
 }
 
 int SMDS_VtkFace::NbFaces() const
 {
-       return 1;
+  return 1;
 }
 
 int SMDS_VtkFace::NbNodes() const
 {
-       vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
-       int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
-       return nbPoints;
+  vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
+  int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
+  return nbPoints;
 }
 
 /*!
@@ -88,44 +102,57 @@ SMDS_VtkFace::GetNode(const int ind) const
 bool SMDS_VtkFace::IsQuadratic() const
 {
   if (this->NbNodes() > 5)
-       return true;
+    return true;
   else
-       return false;
+    return false;
 }
 
 SMDSAbs_EntityType SMDS_VtkFace::GetEntityType() const
 {
-       SMDSAbs_EntityType aType = SMDSEntity_Triangle;
-       switch(NbNodes())
-         {
-         case  3:
-         case  6: aType = SMDSEntity_Triangle;   break;
-         case  4:
-         case  8: aType = SMDSEntity_Quadrangle; break;
-         }
-       return aType;
+  SMDSAbs_EntityType aType = SMDSEntity_Triangle;
+  switch (NbNodes())
+  {
+    case 3:
+    case 6:
+      aType = SMDSEntity_Triangle;
+      break;
+    case 4:
+    case 8:
+      aType = SMDSEntity_Quadrangle;
+      break;
+  }
+  return aType;
 }
 
 vtkIdType SMDS_VtkFace::GetVtkType() const
 {
-       switch(NbNodes())
-         {
-         case  3: return VTK_TRIANGLE;
-         case  6: return VTK_QUADRATIC_TRIANGLE;
-         case  4: return VTK_QUAD;
-         case  8: return VTK_QUADRATIC_QUAD;
-         }
+  switch (NbNodes())
+  {
+    case 3:
+      return VTK_TRIANGLE;
+    case 6:
+      return VTK_QUADRATIC_TRIANGLE;
+    case 4:
+      return VTK_QUAD;
+    case 8:
+      return VTK_QUADRATIC_QUAD;
+  }
 }
 
 SMDS_ElemIteratorPtr SMDS_VtkFace::elementsIterator(SMDSAbs_ElementType type) const
 {
-       switch (type)
-       {
-       case SMDSAbs_Node:
-               return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
-       default:
-               MESSAGE("ERROR : Iterator not implemented");
-               return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
-       }
+  switch (type)
+  {
+    case SMDSAbs_Node:
+      return SMDS_ElemIteratorPtr(
+                                  new SMDS_VtkCellIterator(
+                                                           SMDS_Mesh::_meshList[myMeshId],
+                                                           myVtkID,
+                                                           GetEntityType()));
+    default:
+      MESSAGE("ERROR : Iterator not implemented")
+      ;
+      return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
+  }
 }
 
index ebcc20851af4fe585504a0b7a2ce9b557b5d66d5..c8865d6ba589371f03791e364d4a439fa077ba94 100644 (file)
@@ -1,4 +1,3 @@
-
 #include "SMDS_VtkVolume.hxx"
 #include "SMDS_MeshNode.hxx"
 #include "SMDS_Mesh.hxx"
@@ -8,7 +7,6 @@
 
 #include <vector>
 
-
 SMDS_VtkVolume::SMDS_VtkVolume()
 {
 }
@@ -27,23 +25,41 @@ void SMDS_VtkVolume::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
   myIdInShape = -1;
   myMeshId = mesh->getMeshId();
   vtkIdType aType = VTK_TETRA;
-  switch(nodeIds.size())
-    {
-    case  4: aType = VTK_TETRA;                break;
-    case  5: aType = VTK_PYRAMID;              break;
-    case  6: aType = VTK_WEDGE;                break;
-    case  8: aType = VTK_HEXAHEDRON;           break;
-    case 10: aType = VTK_QUADRATIC_TETRA;      break;
-    case 13: aType = VTK_QUADRATIC_PYRAMID;    break;
-    case 15: aType = VTK_QUADRATIC_WEDGE;      break;
-    case 20: aType = VTK_QUADRATIC_HEXAHEDRON; break;
-    default: aType = VTK_HEXAHEDRON; break;
-    }
+  switch (nodeIds.size())
+  {
+    case 4:
+      aType = VTK_TETRA;
+      break;
+    case 5:
+      aType = VTK_PYRAMID;
+      break;
+    case 6:
+      aType = VTK_WEDGE;
+      break;
+    case 8:
+      aType = VTK_HEXAHEDRON;
+      break;
+    case 10:
+      aType = VTK_QUADRATIC_TETRA;
+      break;
+    case 13:
+      aType = VTK_QUADRATIC_PYRAMID;
+      break;
+    case 15:
+      aType = VTK_QUADRATIC_WEDGE;
+      break;
+    case 20:
+      aType = VTK_QUADRATIC_HEXAHEDRON;
+      break;
+    default:
+      aType = VTK_HEXAHEDRON;
+      break;
+  }
   myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
 }
 
 bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[],
-                                 const int            nbNodes)
+                                 const int nbNodes)
 {
   // utilise dans SMDS_Mesh
   return true;
@@ -60,55 +76,72 @@ void SMDS_VtkVolume::Print(ostream & OS) const
 
 int SMDS_VtkVolume::NbFaces() const
 {
-  switch(NbNodes())
-    {
-    case  4:
-    case 10: return 4;
-    case  5:
-    case 13: return 5;
-    case  6:
-    case 15: return 5;
-    case  8:
-    case 20: return 6;
-    default: MESSAGE("invalid number of nodes");
-    }
+  switch (NbNodes())
+  {
+    case 4:
+    case 10:
+      return 4;
+    case 5:
+    case 13:
+      return 5;
+    case 6:
+    case 15:
+      return 5;
+    case 8:
+    case 20:
+      return 6;
+    default:
+      MESSAGE("invalid number of nodes")
+      ;
+  }
   return 0;
 }
 
 int SMDS_VtkVolume::NbNodes() const
 {
-  vtkUnstructuredGrid* grid =SMDS_Mesh::_meshList[myMeshId]->getGrid();
+  vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
   int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
   return nbPoints;
 }
 
 int SMDS_VtkVolume::NbEdges() const
 {
-  switch(NbNodes())
-    {
-    case  4:
-    case 10: return 6;
-    case  5:
-    case 13: return 8;
-    case  6:
-    case 15: return 9;
-    case  8:
-    case 20: return 12;
-    default: MESSAGE("invalid number of nodes");
-    }
+  switch (NbNodes())
+  {
+    case 4:
+    case 10:
+      return 6;
+    case 5:
+    case 13:
+      return 8;
+    case 6:
+    case 15:
+      return 9;
+    case 8:
+    case 20:
+      return 12;
+    default:
+      MESSAGE("invalid number of nodes")
+      ;
+  }
   return 0;
 }
 
 SMDS_ElemIteratorPtr SMDS_VtkVolume::elementsIterator(SMDSAbs_ElementType type) const
 {
-  switch(type)
-    {
+  switch (type)
+  {
     case SMDSAbs_Node:
-      return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
+      return SMDS_ElemIteratorPtr(
+                                  new SMDS_VtkCellIterator(
+                                                           SMDS_Mesh::_meshList[myMeshId],
+                                                           myVtkID,
+                                                           GetEntityType()));
     default:
-      MESSAGE("ERROR : Iterator not implemented");
-      return SMDS_ElemIteratorPtr((SMDS_ElemIterator*)NULL);
-    }
+      MESSAGE("ERROR : Iterator not implemented")
+      ;
+      return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
+  }
 }
 
 SMDSAbs_ElementType SMDS_VtkVolume::GetType() const
@@ -129,43 +162,79 @@ const SMDS_MeshNode* SMDS_VtkVolume::GetNode(const int ind) const
 bool SMDS_VtkVolume::IsQuadratic() const
 {
   if (this->NbNodes() > 9)
-       return true;
+    return true;
   else
-       return false;
+    return false;
 }
 
 SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
 {
   SMDSAbs_EntityType aType = SMDSEntity_Tetra;
-  switch(NbNodes())
-    {
-    case  4: aType = SMDSEntity_Tetra;        break;
-    case  5: aType = SMDSEntity_Pyramid;      break;
-    case  6: aType = SMDSEntity_Penta;        break;
-    case  8: aType = SMDSEntity_Hexa;         break;
-    case 10: aType = SMDSEntity_Quad_Tetra;   break;
-    case 13: aType = SMDSEntity_Quad_Pyramid; break;
-    case 15: aType = SMDSEntity_Quad_Penta;   break;
-    case 20: aType = SMDSEntity_Quad_Hexa;    break;
-    default: aType = SMDSEntity_Hexa;         break;
-    }
+  switch (NbNodes())
+  {
+    case 4:
+      aType = SMDSEntity_Tetra;
+      break;
+    case 5:
+      aType = SMDSEntity_Pyramid;
+      break;
+    case 6:
+      aType = SMDSEntity_Penta;
+      break;
+    case 8:
+      aType = SMDSEntity_Hexa;
+      break;
+    case 10:
+      aType = SMDSEntity_Quad_Tetra;
+      break;
+    case 13:
+      aType = SMDSEntity_Quad_Pyramid;
+      break;
+    case 15:
+      aType = SMDSEntity_Quad_Penta;
+      break;
+    case 20:
+      aType = SMDSEntity_Quad_Hexa;
+      break;
+    default:
+      aType = SMDSEntity_Hexa;
+      break;
+  }
   return aType;
 }
 
 vtkIdType SMDS_VtkVolume::GetVtkType() const
 {
   vtkIdType aType = VTK_TETRA;
-  switch(NbNodes())
-    {
-    case  4: aType = VTK_TETRA;                break;
-    case  5: aType = VTK_PYRAMID;              break;
-    case  6: aType = VTK_WEDGE;                break;
-    case  8: aType = VTK_HEXAHEDRON;           break;
-    case 10: aType = VTK_QUADRATIC_TETRA;      break;
-    case 13: aType = VTK_QUADRATIC_PYRAMID;    break;
-    case 15: aType = VTK_QUADRATIC_WEDGE;      break;
-    case 20: aType = VTK_QUADRATIC_HEXAHEDRON; break;
-    default: aType = VTK_HEXAHEDRON;           break;
-    }
- return aType;
+  switch (NbNodes())
+  {
+    case 4:
+      aType = VTK_TETRA;
+      break;
+    case 5:
+      aType = VTK_PYRAMID;
+      break;
+    case 6:
+      aType = VTK_WEDGE;
+      break;
+    case 8:
+      aType = VTK_HEXAHEDRON;
+      break;
+    case 10:
+      aType = VTK_QUADRATIC_TETRA;
+      break;
+    case 13:
+      aType = VTK_QUADRATIC_PYRAMID;
+      break;
+    case 15:
+      aType = VTK_QUADRATIC_WEDGE;
+      break;
+    case 20:
+      aType = VTK_QUADRATIC_HEXAHEDRON;
+      break;
+    default:
+      aType = VTK_HEXAHEDRON;
+      break;
+  }
+  return aType;
 }
index 078533ba69cac31eb8b264c3e20f65d118253a24..9ee9f81dfb1165c83dc1f6a82a54b4239d63d7b3 100644 (file)
@@ -7,15 +7,14 @@
 #include <vtkUnstructuredGrid.h>
 #include <vector>
 
-class SMDS_EXPORT SMDS_VtkVolume:public SMDS_MeshVolume
+class SMDS_EXPORT SMDS_VtkVolume: public SMDS_MeshVolume
 {
 public:
   SMDS_VtkVolume();
   SMDS_VtkVolume(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh);
   ~SMDS_VtkVolume();
   void init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh);
-  bool ChangeNodes(const SMDS_MeshNode* nodes[],
-                   const int            nbNodes);
+  bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
 
   void Print(std::ostream & OS) const;
   int NbFaces() const;
diff --git a/src/SMDS/chrono.cxx b/src/SMDS/chrono.cxx
new file mode 100644 (file)
index 0000000..d33856a
--- /dev/null
@@ -0,0 +1,85 @@
+//  Copyright (C) 2006-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "chrono.hxx"
+#include "utilities.h"
+
+using namespace std;
+
+cntStruct* counters::_ctrs = 0;
+  
+counters::counters(int nb)
+{
+  MESSAGE("counters::counters(int nb)");
+  _nbChrono = nb;
+  _ctrs = new cntStruct[_nbChrono];
+
+  for (int i=0; i< _nbChrono; i++)
+    {
+      _ctrs[i]._ctrNames = 0;
+      _ctrs[i]._ctrLines = 0;
+      _ctrs[i]._ctrOccur = 0;
+      _ctrs[i]._ctrCumul = 0;
+    }
+
+  MESSAGE("counters::counters()");
+}
+
+counters::~counters()
+{
+  stats();
+}
+
+void counters::stats()
+{
+  MESSAGE("counters::stats()");
+  for (int i=0; i < _nbChrono; i++)
+    if (_ctrs[i]._ctrOccur)
+      {
+        MESSAGE("Compteur[" << i << "]: "<< _ctrs[i]._ctrNames << "[" << _ctrs[i]._ctrLines << "]");
+        MESSAGE("  " << _ctrs[i]._ctrOccur);
+        MESSAGE("  " << _ctrs[i]._ctrCumul);
+      }
+}
+
+
+
+chrono::chrono(int i) : _ctr(i), _run(true)
+{
+  //MESSAGE("chrono::chrono " << _ctr << " " << _run);
+  _start = clock();    
+}
+
+chrono::~chrono()
+{
+  if (_run) stop();
+}
+
+void chrono::stop()
+{
+  //MESSAGE("chrono::stop " << _ctr << " " << _run);
+  if (_run)
+    {
+      _run = false;
+      _end = clock();
+      double elapse = double(_end - _start)/double(CLOCKS_PER_SEC);
+      counters::_ctrs[_ctr]._ctrOccur++;
+      counters::_ctrs[_ctr]._ctrCumul += elapse;
+    }
+}
diff --git a/src/SMDS/chrono.hxx b/src/SMDS/chrono.hxx
new file mode 100644 (file)
index 0000000..c48ec85
--- /dev/null
@@ -0,0 +1,73 @@
+//  Copyright (C) 2006-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef _CHRONO_HXX_
+#define _CHRONO_HXX_
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <ctime>
+
+typedef struct acnt
+{
+  char*  _ctrNames;
+  int    _ctrLines;
+  int    _ctrOccur;
+  double _ctrCumul;
+} cntStruct;
+
+class counters
+{
+public:
+  static cntStruct *_ctrs;
+  counters(int nb);
+  ~counters();
+  void stats();
+protected:
+  int _nbChrono;
+};
+
+class chrono
+{
+public:
+  chrono(int i);
+  ~chrono();
+  void stop();
+protected:
+  bool _run;
+  int _ctr;
+  clock_t _start, _end;
+};
+
+#ifdef CHRONODEF
+#define CHRONO(i) counters::_ctrs[i]._ctrNames = (char *)__FILE__; \
+  counters::_ctrs[i]._ctrLines = __LINE__; \
+  chrono aChrono##i(i);
+
+#define CHRONOSTOP(i) aChrono##i.stop();
+
+#else  // CHRONODEF
+
+#define CHRONO(i)
+#define CHRONOSTOP(i)
+
+#endif // CHRONODEF
+
+#endif // _CHRONO_HXX_
index 2754222f1bf5f85721bb52bab1b6a7e34aaec1f4..f9323bc0e29e4582c9c11593b98136e028209ca9 100644 (file)
@@ -1,19 +1,18 @@
-
 #ifndef _MEMOIRE_H_
 #define _MEMOIRE_H_
 
 #include <malloc.h>
 #include <iostream>
 
-void memostat( const char* f, int l);
+void memostat(const char* f, int l);
 
-void memostat( const char* f, int l)
+void memostat(const char* f, int l)
 {
-/*  struct mallinfo mem = mallinfo(); */
-/*  std::cerr << f << ":"<< l << " " << mem.arena << " " << mem.ordblks << " " << mem.hblks << " " << mem.hblkhd << " "  << mem.uordblks << " "  << mem.fordblks << " " << mem.keepcost << std::endl; */
-std::cerr << f << ":"<< l << " --------------------------"<< std::endl;
- malloc_stats();
-std::cerr << f << ":"<< l << " --------------------------"<< std::endl;
+  /*  struct mallinfo mem = mallinfo(); */
+  /*  std::cerr << f << ":"<< l << " " << mem.arena << " " << mem.ordblks << " " << mem.hblks << " " << mem.hblkhd << " "  << mem.uordblks << " "  << mem.fordblks << " " << mem.keepcost << std::endl; */
+  std::cerr << f << ":" << l << " --------------------------" << std::endl;
 malloc_stats();
+  std::cerr << f << ":" << l << " --------------------------" << std::endl;
 }
 
 #define MEMOSTAT memostat( __FILE__, __LINE__ )
index bb77e3bbd541b9735b629b1acf732d41fbda14dd..a7afa4c9f033987a64faea65138636793a1d95dd 100644 (file)
@@ -1914,7 +1914,7 @@ void SMESHDS_Mesh::compactMesh()
        myVtkIndex.swap(newVtkToSmds);
        MESSAGE("myCells.size()=" << myCells.size() << " myIDElements.size()=" << myIDElements.size() << " myVtkIndex.size()=" << myVtkIndex.size() );
 
-
+       myGrid->BuildDownwardConnectivity();
 
        // ---TODO: myNodes, myElements in submeshes