+ return nbOfTurnLoop;
+ }
+
+ unsigned CellModel::fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const
+ {
+ typeOfSon=getSonType2(sonId);
+ if(!isDynamic())
+ return fillSonCellNodalConnectivity(sonId,nodalConn,sonNodalConn);
+ else
+ {
+ if(_dim==2)//polygon
+ {
+ if(_type==NORM_POLYGON)
+ {
+ sonNodalConn[0]=nodalConn[sonId];
+ sonNodalConn[1]=nodalConn[(sonId+1)%lgth];
+ return 2;
+ }
+ else
+ {
+ sonNodalConn[0]=nodalConn[sonId];
+ sonNodalConn[1]=nodalConn[(sonId+1)%(lgth/2)];
+ sonNodalConn[2]=nodalConn[sonId+(lgth/2)];
+ return 3;
+ }
+ }
+ else if(_dim==3)
+ {//polyedron
+ const int *where=nodalConn;
+ for(int i=0;i<sonId;i++)
+ {
+ where=std::find(where,nodalConn+lgth,-1);
+ where++;
+ }
+ const int *where2=std::find(where,nodalConn+lgth,-1);
+ std::copy(where,where2,sonNodalConn);
+ return where2-where;
+ }
+ else
+ throw INTERP_KERNEL::Exception("CellModel::fillSonCellNodalConnectivity2 : no sons on NORM_POLYL !");
+ }
+ }
+
+ /*!
+ * Equivalent to CellModel::fillSonCellNodalConnectivity2 except for HEXA8 where the order of sub faces is not has MED file numbering for transformation HEXA8->HEXA27
+ */
+ unsigned CellModel::fillSonCellNodalConnectivity4(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const
+ {
+ if(_type==NORM_HEXA8)
+ {
+ static const int permutation[6]={0,2,3,4,5,1};
+ return fillSonCellNodalConnectivity2(permutation[sonId],nodalConn,lgth,sonNodalConn,typeOfSon);
+ }
+ else
+ return fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon);
+ }
+
+ unsigned CellModel::fillSonEdgesNodalConnectivity3D(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const
+ {
+ if(!isDynamic())
+ {
+ if(!isQuadratic())
+ {
+ typeOfSon=NORM_SEG2;
+ sonNodalConn[0]=nodalConn[_little_sons_con[sonId][0]];
+ sonNodalConn[1]=nodalConn[_little_sons_con[sonId][1]];
+ return 2;
+ }
+ else
+ {
+ typeOfSon=NORM_SEG3;
+ sonNodalConn[0]=nodalConn[_little_sons_con[sonId][0]];
+ sonNodalConn[1]=nodalConn[_little_sons_con[sonId][1]];
+ sonNodalConn[2]=nodalConn[_little_sons_con[sonId][2]];
+ return 3;
+ }
+ }
+ else
+ throw INTERP_KERNEL::Exception("CellModel::fillSonEdgesNodalConnectivity3D : not implemented yet for NORM_POLYHED !");
+ }
+
+ /*!
+ * \sa getNumberOfMicroEdges
+ */
+ unsigned CellModel::fillMicroEdgeNodalConnectivity(int sonId, const int *nodalConn, int *sonNodalConn, NormalizedCellType& typeOfSon) const
+ {
+ if(isQuadratic())
+ {
+ int edgeId(sonId/2),subEdgeId(sonId%2);
+ typeOfSon=NORM_SEG2;
+ const unsigned *sonConn(0);
+ switch(getDimension())
+ {
+ case 2:
+ {
+ sonConn=_sons_con[edgeId];
+ break;
+ }
+ case 3:
+ {
+ sonConn=_little_sons_con[edgeId];
+ break;
+ }
+ default:
+ throw INTERP_KERNEL::Exception("CellModel::fillMicroEdgeNodalConnectivity : only 2D and 3D cells support this !");
+ }
+ const unsigned tmp[3]={sonConn[0],sonConn[2],sonConn[1]};
+ sonNodalConn[0]=nodalConn[tmp[subEdgeId]];
+ sonNodalConn[1]=nodalConn[tmp[subEdgeId+1]];
+ return 2;
+ }
+ else
+ {
+ switch(getDimension())
+ {
+ case 2:
+ return fillSonCellNodalConnectivity2(sonId,nodalConn,0,sonNodalConn,typeOfSon);
+ case 3:
+ return fillSonEdgesNodalConnectivity3D(sonId,nodalConn,0,sonNodalConn,typeOfSon);
+ default:
+ throw INTERP_KERNEL::Exception("CellModel::fillMicroEdgeNodalConnectivity : only 2D and 3D cells support this #2 !");
+ }
+ }
+ }
+
+ void CellModel::changeOrientationOf2D(int *nodalConn, unsigned int sz) const
+ {
+ if(sz<1)
+ return ;
+ if(!isQuadratic())
+ {
+ std::vector<int> tmp(sz-1);
+ std::copy(nodalConn+1,nodalConn+sz,tmp.rbegin());
+ std::copy(tmp.begin(),tmp.end(),nodalConn+1);
+ }
+ else
+ {
+ unsigned int sz2(sz/2);
+ std::vector<int> tmp0(sz2-1),tmp1(sz2);
+ std::copy(nodalConn+1,nodalConn+sz2,tmp0.rbegin());
+ std::copy(nodalConn+sz2,nodalConn+sz,tmp1.rbegin());
+ std::copy(tmp0.begin(),tmp0.end(),nodalConn+1);
+ std::copy(tmp1.begin(),tmp1.end(),nodalConn+sz2);
+ }
+ }
+
+ void CellModel::changeOrientationOf1D(int *nodalConn, unsigned int sz) const
+ {
+ if(!isDynamic())
+ {
+ if(sz==2 || sz==3)
+ {
+ std::swap(nodalConn[0],nodalConn[1]);
+ return ;
+ }
+ else if(sz==4)
+ {
+ std::swap(nodalConn[0],nodalConn[1]);
+ std::swap(nodalConn[2],nodalConn[3]);
+ }
+ else
+ throw Exception("CellModel::changeOrientationOf1D : unrecognized 1D cell type !");
+ }
+ else
+ {
+ std::vector<int> tmp(sz-1);
+ std::copy(nodalConn+1,nodalConn+sz,tmp.rbegin());
+ std::copy(tmp.begin(),tmp.end(),nodalConn+1);
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return number of nodes in sonId-th son of a Dynamic() cell
+ */
+ //================================================================================
+
+ unsigned CellModel::getNumberOfNodesConstituentTheSon2(unsigned sonId, const int *nodalConn, int lgth) const
+ {
+ if(!isDynamic())
+ return getNumberOfNodesConstituentTheSon(sonId);
+
+ if(_dim==2)//polygon
+ {
+ if(_type==NORM_POLYGON)
+ return 2;
+ else
+ return 3;
+ }
+ else if(_dim==3)
+ {//polyedron
+ const int *where=nodalConn;
+ for(unsigned int i=0;i<sonId;i++)
+ {
+ where=std::find(where,nodalConn+lgth,-1);
+ where++;
+ }
+ const int *where2=std::find(where,nodalConn+lgth,-1);
+ return where2-where;
+ }
+ else
+ throw INTERP_KERNEL::Exception("CellModel::getNumberOfNodesConstituentTheSon2 : no sons on NORM_POLYL !");
+ }
+
+ /*!
+ * This method retrieves if cell1 represented by 'conn1' and cell2 represented by 'conn2'
+ * are equivalent by a permutation or not. This method expects to work on 1D or 2D (only mesh dimension where it is possible to have a spaceDim) strictly higher than meshDim.
+ * If not an exception will be thrown.
+ * @return True if two cells have same orientation, false if not.
+ */
+ bool CellModel::getOrientationStatus(unsigned lgth, const int *conn1, const int *conn2) const
+ {
+ if(_dim!=1 && _dim!=2)
+ throw INTERP_KERNEL::Exception("CellModel::getOrientationStatus : invalid dimension ! Must be 1 or 2 !");
+ if(!_quadratic)
+ {
+ std::vector<int> tmp(2*lgth);
+ std::vector<int>::iterator it=std::copy(conn1,conn1+lgth,tmp.begin());
+ std::copy(conn1,conn1+lgth,it);
+ it=std::search(tmp.begin(),tmp.end(),conn2,conn2+lgth);
+ if(it==tmp.begin())
+ return true;
+ if(it!=tmp.end())
+ return _dim!=1;
+ std::vector<int>::reverse_iterator it2=std::search(tmp.rbegin(),tmp.rend(),conn2,conn2+lgth);
+ if(it2!=tmp.rend())
+ return false;
+ throw INTERP_KERNEL::Exception("CellModel::getOrientationStatus : Request of orientation status of non equal connectively cells !");
+ }
+ else
+ {
+ if(_dim!=1)
+ {
+ std::vector<int> tmp(lgth);
+ std::vector<int>::iterator it=std::copy(conn1,conn1+lgth/2,tmp.begin());
+ std::copy(conn1,conn1+lgth/2,it);
+ it=std::search(tmp.begin(),tmp.end(),conn2,conn2+lgth/2);
+ int d=std::distance(tmp.begin(),it);
+ if(it==tmp.end())
+ return false;
+ it=std::copy(conn1+lgth/2,conn1+lgth,tmp.begin());
+ std::copy(conn1+lgth/2,conn1+lgth,it);
+ it=std::search(tmp.begin(),tmp.end(),conn2,conn2+lgth);
+ if(it==tmp.end())
+ return false;
+ int d2=std::distance(tmp.begin(),it);
+ return d==d2;
+ }
+ else
+ {
+ int p=(lgth+1)/2;
+ std::vector<int> tmp(2*p);
+ std::vector<int>::iterator it=std::copy(conn1,conn1+p,tmp.begin());
+ std::copy(conn1,conn1+p,it);
+ it=std::search(tmp.begin(),tmp.end(),conn2,conn2+p);
+ int d=std::distance(tmp.begin(),it);
+ if(it==tmp.end())
+ return false;
+ tmp.resize(2*p-2);
+ it=std::copy(conn1+p,conn1+lgth,tmp.begin());
+ std::copy(conn1+p,conn1+lgth,it);
+ it=std::search(tmp.begin(),tmp.end(),conn2+p,conn2+lgth);
+ if(it==tmp.end())
+ return false;
+ int d2=std::distance(tmp.begin(),it);
+ return d==d2;
+ }
+ }
+ }
+
+ DiameterCalculator *CellModel::buildInstanceOfDiameterCalulator(int spaceDim) const
+ {
+ switch(_type)
+ {
+ case NORM_TRI3:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorTRI3S2;
+ case 3:
+ return new DiameterCalulatorTRI3S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For TRI3 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_QUAD4:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorQUAD4S2;
+ case 3:
+ return new DiameterCalulatorQUAD4S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For QUAD4 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_TRI6:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorTRI6S2;
+ case 3:
+ return new DiameterCalulatorTRI6S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For TRI6 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_TRI7:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorTRI7S2;
+ case 3:
+ return new DiameterCalulatorTRI7S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For TRI7 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_QUAD8:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorQUAD8S2;
+ case 3:
+ return new DiameterCalulatorQUAD8S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For QUAD8 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_QUAD9:
+ {
+ switch(spaceDim)
+ {
+ case 2:
+ return new DiameterCalulatorQUAD9S2;
+ case 3:
+ return new DiameterCalulatorQUAD9S3;
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For QUAD9 only space dimension 2 and 3 implemented !");
+ }
+ break;
+ }
+ case NORM_TETRA4:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorTETRA4;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For TETRA4 space dimension 3 expected !");
+ }
+ case NORM_TETRA10:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorTETRA10;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For TETRA10 space dimension 3 expected !");
+ }
+ case NORM_HEXA8:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorHEXA8;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For HEXA8 space dimension 3 expected !");
+ }
+ case NORM_HEXA20:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorHEXA20;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For HEXA20 space dimension 3 expected !");
+ }
+ case NORM_HEXA27:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorHEXA27;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For HEXA27 space dimension 3 expected !");
+ }
+ case NORM_PENTA6:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorPENTA6;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For PENTA6 space dimension 3 expected !");
+ }
+ case NORM_PENTA15:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorPENTA15;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For PENTA15 space dimension 3 expected !");
+ }
+ case NORM_PYRA5:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorPYRA5;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For PYRA5 space dimension 3 expected !");
+ }
+ case NORM_PYRA13:
+ {
+ if(spaceDim==3)
+ return new DiameterCalulatorPYRA13;
+ else
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : For PYRA13 space dimension 3 expected !");
+ }
+ default:
+ throw Exception("CellModel::buildInstanceOfDiameterCalulator : implemented only for TRI3, QUAD4, TETRA4, HEXA8, PENTA6, PYRA5 !");
+ }
+ }
+
+ OrientationInverter *CellModel::buildOrientationInverter() const
+ {
+ switch(_type)
+ {
+ case NORM_SEG2:
+ return new OrientationInverterSEG2;
+ case NORM_SEG3:
+ return new OrientationInverterSEG3;
+ case NORM_TRI3:
+ case NORM_QUAD4:
+ return new OrientationInverter2DLinear(getNumberOfNodes());
+ case NORM_TRI6:
+ case NORM_QUAD8:
+ return new OrientationInverter2DQuadratic(getNumberOfNodes());
+ case NORM_POLYGON:
+ return new OrientationInverterPolygon;
+ case NORM_QPOLYG:
+ return new OrientationInverterQPolygon;
+ case NORM_TETRA4:
+ return new OrientationInverterTetra4;
+ case NORM_PYRA5:
+ return new OrientationInverterPyra5;
+ case NORM_TETRA10:
+ return new OrientationInverterTetra10;
+ case NORM_PYRA13:
+ return new OrientationInverterPyra13;
+ case NORM_PENTA6:
+ case NORM_HEXA8:
+ return new OrientationInverter3DExtrusionLinear(getNumberOfNodes());
+ case NORM_PENTA15:
+ case NORM_HEXA20:
+ return new OrientationInverter3DExtrusionQuadratic(getNumberOfNodes());
+ default:
+ {
+ std::ostringstream oss; oss << "CellModel::buildOrientationInverter : not managed geometric type " << getRepr() << " yet !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }