Salome HOME
Update copyrights
[tools/medcoupling.git] / src / INTERP_KERNEL / PolyhedronIntersectorP1P1.txx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20 #ifndef __PolyhedronIntersectorP1P1_TXX__
21 #define __PolyhedronIntersectorP1P1_TXX__
22
23 #include "PolyhedronIntersectorP1P1.hxx"
24 #include "Intersector3DP1P1.txx"
25 #include "MeshUtils.hxx"
26
27 #include "SplitterTetra.txx"
28
29 namespace INTERP_KERNEL
30 {
31
32   /**
33    * Constructor creating object from target cell global number 
34    * 
35    * @param targetMesh  mesh containing the target elements
36    * @param srcMesh     mesh containing the source elements
37    * @param policy      splitting policy to be used
38    */
39   template<class MyMeshType, class MyMatrix>
40   PolyhedronIntersectorP1P1<MyMeshType,MyMatrix>::PolyhedronIntersectorP1P1(const MyMeshType& targetMesh, const MyMeshType& srcMesh, SplittingPolicy policy):Intersector3DP1P1<MyMeshType,MyMatrix>(targetMesh,srcMesh)
41   {
42     // SPEC:
43     // "Limitation. Concerning P1P1 3D improvement only tetrahedron will be supported.
44     // If another type than tetrahedron is detected an INTERP_KERNEL::Exception should be thrown"
45
46     // Check types of elements here rather than in intersectCells() since a wrong type can be
47     // found late after a long time of calculation.
48
49     const unsigned long numSrcElems = srcMesh.getNumberOfElements();
50     for(unsigned long i = 0 ; i < numSrcElems ; ++i)
51       if ( srcMesh.getTypeOfElement( OTT<ConnType,numPol>::indFC( i )) != NORM_TETRA4 )
52         throw INTERP_KERNEL::Exception("P1P1 3D algorithm works only with tetrahedral meshes");
53
54     const unsigned long numTgtElems = targetMesh.getNumberOfElements();
55     for(unsigned long i = 0 ; i < numTgtElems ; ++i)
56       if ( targetMesh.getTypeOfElement( OTT<ConnType,numPol>::indFC( i )) != NORM_TETRA4 )
57         throw INTERP_KERNEL::Exception("P1P1 3D algorithm works only with tetrahedral meshes");
58   }
59
60   /**
61    * Destructor.
62    */
63   template<class MyMeshType, class MyMatrix>
64   PolyhedronIntersectorP1P1<MyMeshType,MyMatrix>::~PolyhedronIntersectorP1P1()
65   {
66   }
67
68   /**
69    * Calculates the volume of intersection of an element in the source mesh and the target element
70    * represented by the object.
71    * 
72    * @param targetCell in C mode.
73    * @param srcCells in C mode.
74    */
75   template<class MyMeshType, class MyMatrix>
76   void PolyhedronIntersectorP1P1<MyMeshType,MyMatrix>::intersectCells(ConnType targetCell, const std::vector<ConnType>& srcCells, MyMatrix& res)
77   {
78 #ifdef _DEBUG_
79     UnitTetraIntersectionBary b; b.init();
80 #endif
81     // split the targetCell into dual cells
82     std::pair< int, std::vector<double> > subTetraNodes[24]; // a node of sub tetra and its coordinates
83     const double* nodes[4]; int conn[4];
84     for(int node = 0; node < 4 ; ++node)
85       nodes[node]=getCoordsOfNode2(node, OTT<ConnType,numPol>::indFC(targetCell),
86                                    Intersector3D<MyMeshType,MyMatrix>::_target_mesh,conn[node]);
87     SplitterTetra<MyMeshType> tgtTetra(Intersector3D<MyMeshType,MyMatrix>::_src_mesh, nodes, conn);
88     for (int i=0; i<24; i++)
89       {
90         subTetraNodes[i].second.resize(12);
91         tgtTetra.splitMySelfForDual(&subTetraNodes[i].second[0],i,subTetraNodes[i].first);
92       }
93     // intersect each source tetrahedron with each of target dual cells
94     SplitterTetra<MyMeshType>* subTetrasS[24];
95     for(typename std::vector<ConnType>::const_iterator iterCellS=srcCells.begin();iterCellS!=srcCells.end();iterCellS++)
96       {
97         // split a source cell into dual cells
98         for(int node = 0; node < 4 ; ++node)
99           nodes[node]=getCoordsOfNode2(node, OTT<ConnType,numPol>::indFC(*iterCellS),
100                                        Intersector3D<MyMeshType,MyMatrix>::_src_mesh,conn[node]);
101
102         SplitterTetra<MyMeshType> srcTetra(Intersector3D<MyMeshType,MyMatrix>::_target_mesh, nodes, conn);
103         srcTetra.splitIntoDualCells(subTetrasS);
104
105         // intersect each target subTetra with each source one
106         for(int i=0;i<24;i++)
107           {
108             SplitterTetra<MyMeshType> *tmp=subTetrasS[i];
109             ConnType sourceNode=OTT<ConnType,numPol>::indFC(tmp->getId(0));
110             for(int j=0;j<24;j++)
111               {
112                 const double* tetraNodes12 = &subTetraNodes[j].second[0];
113                 const double* tetraNodesT[4]={ tetraNodes12, tetraNodes12+3, tetraNodes12+6, tetraNodes12+9 };
114                 double volume = tmp->intersectTetra( tetraNodesT );
115                 if(volume!=0.)
116                   {
117                     ConnType tgtNode=subTetraNodes[j].first;
118                     typename MyMatrix::value_type& resRow = res[tgtNode];
119                     typename MyMatrix::value_type::const_iterator iterRes=resRow.find( sourceNode );
120                     if(iterRes!=resRow.end())
121                       {
122                         volume += (*iterRes).second;
123                         resRow.erase(sourceNode);
124                       }
125                     resRow.insert(std::make_pair(sourceNode,volume));
126                   }
127               }
128             delete tmp;
129           }
130       }
131   }
132 }
133
134 #endif