]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
WIP working version. Franck to test ...
authorabn <adrien.bruneton@cea.fr>
Thu, 7 Oct 2021 19:17:03 +0000 (21:17 +0200)
committerabn <adrien.bruneton@cea.fr>
Fri, 8 Oct 2021 12:11:57 +0000 (14:11 +0200)
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling_Swig/MEDCouplingCommon.i
src/MEDLoader/MEDFileMesh.cxx
src/MEDLoader/Swig/MEDLoaderTest3.py

index b31bb1634f00ac64133b7ee82d49940b23113611..3a63bc6d625c06907527423d820f7ae12fa923fd 100755 (executable)
@@ -2360,13 +2360,10 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
  *
  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
  *             parameter is altered during the call.
- * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
- * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
- * \param [out] cellIdsNotModified cell ids in \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
+ * \return node ids which need to be duplicated following the algorithm explained above.
  *
  */
-void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *& nodeIdsToDuplicate,
-                                            DataArrayIdType *& cellIdsNeededToBeRenum, DataArrayIdType *& cellIdsNotModified) const
+DataArrayIdType* MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords) const
 {
   using DAInt = MCAuto<DataArrayIdType>;
   using MCUMesh = MCAuto<MEDCouplingUMesh>;
@@ -2395,7 +2392,7 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On
   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
   dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New();
   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
-  dsi = rdit0->deltaShiftIndex();
+  dsi = rdit0->deltaShiftIndex();  rdit0=0;
   DAInt boundSegs = dsi->findIdsEqual(1);  dsi = 0; // boundary segs/faces of the M0 mesh
   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
@@ -2423,98 +2420,230 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On
           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
 
-          // Also, in this (segment) mesh, nodes connected to more than 3 segs should not be dup either (singular points - see testBuildInnerBoundary6())
-          dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New();
-          MCUMesh meshM2Desc = meshM2->buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;  // a mesh made of node cells
-          dsi = rdit0->deltaShiftIndex();
-          DAInt singPoints = dsi->findIdsNotInRange(-1,4);   // points connected to (strictly) more than 3 segments
-          const mcIdType *cc = meshM2Desc->getNodalConnectivity()->begin(), *ccI = meshM2Desc->getNodalConnectivityIndex()->begin();
-          mcIdType * singPointsP = singPoints->rwBegin();
-          for (mcIdType j=0; j < singPoints->getNumberOfTuples(); j++) // replace ids in singPoints by real coordinate index (was index of cells in notDuplSkin)
+          // Specific logic to handle singular points :
+          //   - take the sub-mesh of M1 (dim N-1) built keeping only elements touching the m1IntersecSkin
+          //   - build its spread zones
+          //   - a node common to two different spread zones actually connects two cells of M1 by just one point : this is a singular point
+          //   which should not be duplicated.
+          // This is a costly algorithm so only go into it if a simple (non sufficient) criteria is met: a node connected to more than 3 segs in meshM2:
+          dnu1=DataArrayIdType::New(), dnu2=DataArrayIdType::New(), dnu3=DataArrayIdType::New(), rdit0=DataArrayIdType::New();
+          MCUMesh meshM2Desc = meshM2->buildDescendingConnectivity(dnu1, dnu2, dnu3, rdit0);  // a mesh made of node cells
+          dnu1=0;dnu2=0;dnu3=0;
+          dsi = rdit0->deltaShiftIndex();  rdit0=0;
+          DAInt singPoints = dsi->findIdsNotInRange(-1,4) ;    dsi=0;// points connected to (strictly) more than 3 segments
+          if (singPoints->getNumberOfTuples())
             {
-              mcIdType nodeCellIdx = singPointsP[j];
-              singPointsP[j] = cc[ccI[nodeCellIdx]+1];  // +1 to skip type
+              DAInt boundNodes = m1IntersecSkin->computeFetchedNodeIds();
+              DAInt boundCells = otherDimM1OnSameCoords.getCellIdsLyingOnNodes(boundNodes->begin(), boundNodes->end(), false); // false= take cell in, even if not all nodes are in dupl
+              MCUMesh m1Bound = static_cast<MEDCouplingUMesh *>(otherDimM1OnSameCoords.buildPartOfMySelf(boundCells->begin(), boundCells->end(), true));
+              DAInt d=DataArrayIdType::New(), dI=DataArrayIdType::New(), revD=DataArrayIdType::New(), revDI=DataArrayIdType::New();
+              MCUMesh dnuM = m1Bound->buildDescendingConnectivity(d,dI,revD,revDI); dnuM = 0;
+              DataArrayIdType *tmp3=0, *tmp4=0;
+              MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(d,dI,revD,revDI, tmp3, tmp4 );
+              DAInt neighSing(tmp3), neighISing(tmp4);
+              mcIdType seed=0;
+              DAInt hitCells = DataArrayIdType::New(); hitCells->alloc(m1Bound->getNumberOfCells(),1); hitCells->fillWithValue(-1);
+              mcIdType nIter=0, nIterMax=m1Bound->getNumberOfCells()+1;
+              while (nIter < nIterMax)
+                {
+                  mcIdType dnuId;
+                  DAInt sprdZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1, neighSing,neighISing, -1, dnuId);
+                  const mcIdType * ptr = sprdZone->begin();
+                  for (mcIdType cnt = 0; cnt < sprdZone->getNumberOfTuples(); ptr++, cnt++)
+                    hitCells->setIJSilent(*ptr,0,nIter);
+                  nIter++;
+                  DAInt noHit = hitCells->findIdsEqual(-1);
+                  if (noHit->getNumberOfTuples())
+                    seed = noHit->getIJ(0,0);
+                  else
+                    break;
+                }
+              if (nIter >= nIterMax)
+                throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
+              DAInt uniq = hitCells->buildUniqueNotSorted();
+              if (uniq->getNumberOfTuples() > 1)
+                {
+                  // All points common to two (or more) different spread zones are singular:
+                  DAInt cc=DataArrayIdType::New(), ccI=DataArrayIdType::New();
+                  m1Bound->getReverseNodalConnectivity(cc, ccI);
+                  DAInt spreadCC = cc->deepCopy();
+                  spreadCC->transformWithIndArr(hitCells->begin(), hitCells->end());
+                  DAInt singPoints2 = DataArrayIdType::New(); singPoints2->alloc(0,1);
+                  const mcIdType* ccIP = ccI->begin();
+                  const mcIdType* spreadCCP = spreadCC->begin();
+                  for(mcIdType j=0; j < ccI->getNumberOfTuples()-1; j++, ccIP++)
+                    {
+                      mcIdType sz = *(ccIP+1)-*ccIP;
+                      if (sz == 0) continue;  // skip empty packs
+                      mcIdType val = spreadCCP[*ccIP];
+                      for (mcIdType k=1; k < sz; k++)
+                        if (val != spreadCCP[*ccIP + k])
+                          {
+                            singPoints2->pushBackSilent(j);
+                            break;
+                          }
+                    }
+                  fNodes1 = fNodes1->buildSubstraction(singPoints2);
+                }
             }
-          DAInt fNodes2 = fNodes1->buildSubstraction(singPoints);
           notDup = xtrem->buildSubstraction(fNodes1);
         }
-      else
+      else  // if (validIds-> ...)
         notDup = xtrem->buildSubstraction(fNodes);
     }
-  else
+  else  // if (3D ...)
     notDup = xtrem->buildSubstraction(fNodes);
 
   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
   DAInt dupl = m1Nodes->buildSubstraction(notDup);
-  DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in dupl
+  return dupl.retn();
+}
+
+
+/*!
+ * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
+ * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
+ * This method is part of the MEDFileUMesh::buildInnerBoundaryAlongM1Group() algorithm.
+ * Given a set of nodes to duplicate, this method identifies which cells should have their connectivity modified
+ * to produce the inner boundary. It is typically called after findNodesToDuplicate().
+ *
+ * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
+ *             parameter is altered during the call.
+ * \param [in] nodeIdsToDuplicateBg node ids needed to be duplicated, as returned by findNodesToDuplicate.
+ * \param [in] nodeIdsToDuplicateEnd node ids needed to be duplicated, as returned by findNodesToDuplicate.
+ * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
+ * \param [out] cellIdsNotModified cell ids in \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
+ *
+ */
+void MEDCouplingUMesh::findCellsToRenumber(const MEDCouplingUMesh& otherDimM1OnSameCoords, const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd,
+                                           DataArrayIdType *& cellIdsNeededToBeRenum, DataArrayIdType *& cellIdsNotModified) const
+{
+  using DAInt = MCAuto<DataArrayIdType>;
+  using MCUMesh = MCAuto<MEDCouplingUMesh>;
+
+  checkFullyDefined();
+  otherDimM1OnSameCoords.checkFullyDefined();
+  if(getCoords()!=otherDimM1OnSameCoords.getCoords())
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellsToRenumber: meshes do not share the same coords array !");
+  if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellsToRenumber: the mesh given in other parameter must have this->getMeshDimension()-1 !");
+
+  DAInt cellsAroundGroup = getCellIdsLyingOnNodes(nodeIdsToDuplicateBg, nodeIdsToDuplicateEnd, false);  // false= take cell in, even if not all nodes are in dupl
 
   //
   MCUMesh mAroundGrp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
-  mcIdType nCells2 = mAroundGrp->getNumberOfCells();
+  mcIdType nCells2 = mAroundGrp->getNumberOfCells();  
   DAInt desc00=DataArrayIdType::New(),descI00=DataArrayIdType::New(),revDesc00=DataArrayIdType::New(),revDescI00=DataArrayIdType::New();
   MCUMesh mArGrpDesc=mAroundGrp->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
 
-  // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
-  DataArrayIdType *tmp00=0,*tmp11=0;
-  MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
-  DAInt neighInit00(tmp00);
-  DAInt neighIInit00(tmp11);
+  // Identify cells of M1 group in sub-mesh mAroundGrp
+  DataArrayIdType *idsOfM1t;
+  mArGrpDesc->areCellsIncludedIn(&otherDimM1OnSameCoords,2, idsOfM1t);
+  DAInt idsOfM1(idsOfM1t);
+
+  // Build map giving for each cell ID in mAroundGrp the corresponding cell ID on the other side of the crack:
+  // Note that this does not cover all cells around the crack (a cell like a triangle might touche the crack only with its tip)
+  std::map<mcIdType, mcIdType> toOtherSide;
+  const mcIdType *revDP=revDesc00->begin(), *revDIP=revDescI00->begin(); 
+  for (const auto& v: *idsOfM1)
+    {
+      mcIdType idx0 = revDIP[v];
+      mcIdType c1=revDP[idx0], c2=revDP[idx0+1];
+      toOtherSide[c1] = c2;
+      toOtherSide[c2] = c1;
+    }
+
   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
-  DataArrayIdType *idsTmp=0;
-  mArGrpDesc->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
-  DAInt ids(idsTmp);
   //     In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
   //     of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
-  DataArrayIdType::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
-  DataArrayIdType *tmp0=0,*tmp1=0;
+  DataArrayIdType::RemoveIdsFromIndexedArrays(idsOfM1->begin(), idsOfM1->end(),desc00,descI00);
   //     Compute the neighbor of each cell in mAroundGrp, taking into account the broken link above. Two
   //     cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
-  ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
-  DAInt neigh00(tmp0);
-  DAInt neighI00(tmp1);
+  DataArrayIdType *neigh00t=0, *neighI00t=0;
+  MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, neigh00t, neighI00t);
+  DAInt neigh00(neigh00t), neighI00(neighI00t);
 
   // For each initial connex part of the M1 mesh (or said differently for each independent crack):
-  mcIdType seed = 0, nIter = 0;
+  mcIdType seed=0, nIter=0;
   mcIdType nIterMax = nCells2+1; // Safety net for the loop
-  DAInt hitCells = DataArrayIdType::New(); hitCells->alloc(nCells2);
-  hitCells->fillWithValue(-1);
-  DAInt cellsToModifyConn0_torenum = DataArrayIdType::New();
-  cellsToModifyConn0_torenum->alloc(0,1);
+  DAInt hitCells = DataArrayIdType::New(); hitCells->alloc(nCells2,1);
+  hitCells->fillWithValue(-1);  // -1 : not hit, 0: one side of the crack, 1: other side of the crack
+  mcIdType PING_FULL, PONG_FULL;
   while (nIter < nIterMax)
     {
       DAInt t = hitCells->findIdsEqual(-1);
-      if (!t->getNumberOfTuples())
+      if(!t->getNumberOfTuples())
         break;
-      // Connex zone without the crack (to compute the next seed really)
-      mcIdType dnu;
-      DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
-      mcIdType cnt(0);
-      for (mcIdType * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
-        hitCells->setIJ(*ptr,0,1);
-      // Connex zone WITH the crack (to identify cells lying on either part of the crack)
-      DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
-      cellsToModifyConn0_torenum = DataArrayIdType::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
-      // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
-      DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
+      mcIdType seed = t->getIJ(0,0);
+      bool done = false;
+      PING_FULL         =1;  PONG_FULL=2;
+      mcIdType PING_PART=11, PONG_PART=22;
+      // while the connex bits in correspondance on either side of the crack are not fully covered
+      while(!done && nIter < nIterMax)  // Start of the ping-pong
+        {
+          nIter++;
+          // Identify connex zone around the seed - this zone corresponds to some cells on the other side
+          // of the crack that might extend further away. So we will need to compute spread zone on the other side
+          // too ... and this process can repeat, hence the "ping-pong" logic.
+          mcIdType dnu;
+          DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
+          done = true;
+          mcIdType* hitCellsP = hitCells->rwBegin();
+          for(const mcIdType& s: *spreadZone)
+            {
+              hitCellsP[s] = PING_FULL;
+              const auto& it = toOtherSide.find(s);
+              if (it != toOtherSide.end())
+                {
+                  mcIdType other = it->second;
+                  if (hitCellsP[other] != PONG_FULL)
+                    {
+                      // On the other side of the crack we hit a cell which was not fully covered previously by the 
+                      // ComputeSpreadZone process, so we are not done yet, ComputeSreadZone will need to be applied there
+                      done = false;
+                      hitCellsP[other] = PONG_PART;
+                      //  Compute next seed, i.e. a cell on the other side of the crack
+                      seed = other;
+                    }
+                }
+            }
+          if (done)
+            {
+              // we might have several disjoint PONG parts in front of a single PING connex part:
+              DAInt idsPong = hitCells->findIdsEqual(PONG_PART);
+              if (idsPong->getNumberOfTuples())
+                {
+                  seed = idsPong->getIJ(0,0);
+                  done = false;
+                }
+              continue;  // continue without switching side (or break if 'done' remains false)
+            }
+          else
+            {
+              // Go to the other side
+              std::swap(PING_FULL, PONG_FULL);
+              std::swap(PING_PART, PONG_PART);
+            }
+        } // while (!done ...)
       DAInt nonHitCells = hitCells->findIdsEqual(-1);
-      DAInt intersec = nonHitCells->buildIntersection(comple);
-      if (intersec->getNumberOfTuples())
-        { seed = intersec->getIJ(0,0); }
+      if (nonHitCells->getNumberOfTuples())
+        seed = nonHitCells->getIJ(0,0);
       else
-        { break; }
-      nIter++;
-    }
+        break;
+    } // while (nIter < nIterMax ...
   if (nIter >= nIterMax)
-    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
-
-  DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
-  cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
-  cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellsToRenumber: Too many iterations - should not happen");
+
+  DAInt cellsRet1 = hitCells->findIdsEqual(PONG_FULL);
+  DAInt cellsRet2 = hitCells->findIdsEqual(PING_FULL);
+  if (cellsRet1->getNumberOfTuples() + cellsRet2->getNumberOfTuples() != cellsAroundGroup->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellsToRenumber: Some cells not hit - Internal error should not happen");
+  cellsRet1->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
+  cellsRet2->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
   //
-  cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
-  cellIdsNotModified=cellsToModifyConn1_torenum.retn();
-  nodeIdsToDuplicate=dupl.retn();
+  cellIdsNeededToBeRenum=cellsRet1.retn();
+  cellIdsNotModified=cellsRet2.retn();
 }
 
 /*!
index de9c4da21476441e9a363c41e60543af88472081..2d5f408d7a8818f38b1126f6938d67a11e1e0f64 100644 (file)
@@ -144,7 +144,8 @@ namespace MEDCoupling
     MEDCOUPLING_EXPORT DataArrayIdType *findCellIdsOnBoundary() const;
     MEDCOUPLING_EXPORT void findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *&cellIdsRk0, DataArrayIdType *&cellIdsRk1) const;
     MEDCOUPLING_EXPORT MEDCouplingUMesh *computeSkin() const;
-    MEDCOUPLING_EXPORT void findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *& nodeIdsToDuplicate,
+    MEDCOUPLING_EXPORT DataArrayIdType *findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords) const;
+    MEDCOUPLING_EXPORT void findCellsToRenumber(const MEDCouplingUMesh& otherDimM1OnSameCoords, const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd,
                                                  DataArrayIdType *& cellIdsNeededToBeRenum, DataArrayIdType *& cellIdsNotModified) const;
     MEDCOUPLING_EXPORT void duplicateNodes(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd);
     MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(mcIdType offset);
index 1639e0751e394a059ab6de26b5abeb3a058562e9..c2f9afff3003cc976e3f962ac1162ccf7bd5bf12 100644 (file)
@@ -365,6 +365,7 @@ typedef long int mcIdType;
 %newobject MEDCoupling::MEDCouplingUMesh::getRenumArrForMEDFileFrmt;
 %newobject MEDCoupling::MEDCouplingUMesh::convertCellArrayPerGeoType;
 %newobject MEDCoupling::MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec;
+%newobject MEDCoupling::MEDCouplingUMesh::findNodesToDuplicate;
 %newobject MEDCoupling::MEDCouplingUMesh::buildDirectionVectorField;
 %newobject MEDCoupling::MEDCouplingUMesh::convertLinearCellsToQuadratic;
 %newobject MEDCoupling::MEDCouplingUMesh::getEdgeRatioField;
@@ -2452,14 +2453,19 @@ namespace MEDCoupling
         return ret;
       }
 
-      PyObject *findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords) const
+      DataArrayIdType *findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords) const
       {
-        DataArrayIdType *tmp0=0,*tmp1=0,*tmp2=0;
-        self->findNodesToDuplicate(otherDimM1OnSameCoords,tmp0,tmp1,tmp2);
-        PyObject *ret=PyTuple_New(3);
+        DataArrayIdType *ret=self->findNodesToDuplicate(otherDimM1OnSameCoords);
+        return ret;
+      }
+
+      PyObject *findCellsToRenumber(const MEDCouplingUMesh& otherDimM1OnSameCoords, const DataArrayIdType *dupNodes) const
+      {
+        DataArrayIdType *tmp0=0,*tmp1=0;
+        self->findCellsToRenumber(otherDimM1OnSameCoords,dupNodes->begin(), dupNodes->end(), tmp0,tmp1);
+        PyObject *ret=PyTuple_New(2);
         PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(tmp0),SWIGTITraits<mcIdType>::TI, SWIG_POINTER_OWN | 0 ));
         PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(tmp1),SWIGTITraits<mcIdType>::TI, SWIG_POINTER_OWN | 0 ));
-        PyTuple_SetItem(ret,2,SWIG_NewPointerObj(SWIG_as_voidptr(tmp2),SWIGTITraits<mcIdType>::TI, SWIG_POINTER_OWN | 0 ));
         return ret;
       }
 
index 214d4434930d89eabd36a34dbc07766451d484c2..78460bf1c840659a64f23b54b658322c28d30c29 100644 (file)
@@ -4110,11 +4110,16 @@ void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1,
   MUMesh m1=getMeshAtLevel(-1);
   mcIdType nbNodes=m0->getNumberOfNodes();
   MUMesh m11=getGroup(-1,grpNameM1);
-  DataArrayIdType *tmp00=0,*tmp11=0,*tmp22=0;
-  m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);  // the core of the duplication logic is in this method
-  DAInt nodeIdsToDuplicate(tmp00);
+  DataArrayIdType *tmp00=0, *tmp11=0,*tmp22=0;
+
+  // !!! The core of the duplication logic is in these 2 methods:
+  // !!!
+  DAInt nodeIdsToDuplicate = m0->findNodesToDuplicate(*m11);  // identify nodes to duplicate
+  m0->findCellsToRenumber(*m11, nodeIdsToDuplicate->begin(), nodeIdsToDuplicate->end(), tmp11,tmp22);  // identify cells needing renumbering
   DAInt cellsToModifyConn0(tmp11);
   DAInt cellsToModifyConn1(tmp22);
+  // !!!!
+
   MUMesh tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
   DAInt descTmp0=DataArrayIdType::New(),descITmp0=DataArrayIdType::New(),revDescTmp0=DataArrayIdType::New(),revDescITmp0=DataArrayIdType::New();
index 92c906a1e857468b44afddaec8b275c43d731fd3..5960607e471c8c0fcae973e7c03185ebd9250061 100644 (file)
@@ -1665,8 +1665,8 @@ class MEDLoaderTest3(unittest.TestCase):
         self.assertEqual(m3_bis.getCoords()[nodesDup].getValues(), m3_bis.getCoords()[nNod:].getValues())
         self.assertEqual(set([4, 5, 6, 7, 20, 21, 22, 23, 32, 33, 34, 35]), set(cells1.getValues()))
         self.assertEqual(set([0, 1, 2, 3, 24, 25, 26, 27, 28, 29, 30, 31]), set(cells2.getValues()))
-        self.assertEqual([],mfu.getGroupArr(-1,"group").getValues())
-        self.assertEqual([],mfu.getGroupArr(-1,"group_dup").getValues())  # here only one cell has been duplicated
+        self.assertEqual([2, 7, 12, 17, 95, 99, 103, 107, 129, 133, 137, 141],mfu.getGroupArr(-1,"group").getValues())
+        self.assertEqual([151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162],mfu.getGroupArr(-1,"group_dup").getValues())  # here only one cell has been duplicated
         m_desc, _, _, _, _ = m3_bis.buildDescendingConnectivity()
         m_desc.checkDeepEquivalOnSameNodesWith(m2_bis, 2, 9.9999)
         pass