Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Transfer/TransferDetails.cpp
4 : : \copyright 2020 Charmworks, Inc.
5 : : All rights reserved. See the LICENSE file for details.
6 : : \brief Chare class declaration for mesh transfer workers holding part of a
7 : : mesh
8 : : \details Chare class declaration for mesh transfer workers holding part of a
9 : : mesh.
10 : : */
11 : : // *****************************************************************************
12 : :
13 : : #include "TransferDetails.hpp"
14 : : #include "Reorder.hpp"
15 : : #include "DerivedData.hpp"
16 : : #include "M2MTransfer.hpp"
17 : :
18 : : #include "collidecharm.h"
19 : :
20 : : #if defined(__clang__)
21 : : #pragma clang diagnostic push
22 : : #pragma clang diagnostic ignored "-Wold-style-cast"
23 : : #endif
24 : :
25 : 0 : PUPbytes(Collision);
26 : :
27 : : #if defined(__clang__)
28 : : #pragma clang diagnostic pop
29 : : #endif
30 : :
31 : : namespace exam2m {
32 : : extern CollideHandle collideHandle;
33 : : extern CProxy_M2MTransfer m2mtransferProxy;
34 : : }
35 : :
36 : : using exam2m::TransferDetails;
37 : :
38 : 14 : TransferDetails::TransferDetails( CkArrayID p, MeshData d, CkCallback cb ) :
39 : 14 : m_firstchunk(d.m_firstchunk)
40 : : // *****************************************************************************
41 : : // Constructor
42 : : //! \param[in] firstchunk Chunk ID used for the collision detection library
43 : : //! \param[in] cb Callback to inform application that the library is ready
44 : : // *****************************************************************************
45 : : {
46 [ + - ]: 14 : CollideRegister(collideHandle, m_firstchunk + thisIndex);
47 [ + - ]: 14 : d.m_proxy = thisProxy;
48 [ + - ][ + - ]: 14 : m2mtransferProxy.ckLocalBranch()->setMesh( p, d );
[ + - ]
49 [ + - ]: 14 : contribute(cb);
50 : 14 : }
51 : :
52 : : void
53 : 1232 : TransferDetails::setSourceTets(
54 : : std::vector< std::size_t>* inpoel,
55 : : tk::UnsMesh::Coords* coords,
56 : : const tk::Fields& u )
57 : : // *****************************************************************************
58 : : // Set the data for the source tetrahedrons to be collided
59 : : //! \param[in] inpoel Pointer to the connectivity data for the source mesh
60 : : //! \param[in] coords Pointer to the coordinate data for the source mesh
61 : : //! \param[in] u Pointer to the solution data for the source mesh
62 : : // *****************************************************************************
63 : : {
64 : 1232 : m_coord = coords;
65 : 1232 : m_u = const_cast< tk::Fields* >( &u );
66 : 1232 : m_inpoel = inpoel;
67 : :
68 : : // Send tetrahedron data to the collision detection library
69 : 1232 : collideTets();
70 : 1232 : }
71 : :
72 : : void
73 : 1232 : TransferDetails::setDestPoints(
74 : : tk::UnsMesh::Coords* coords,
75 : : tk::Fields& u,
76 : : CkCallback cb )
77 : : // *****************************************************************************
78 : : // Set the data for the destination points to be collided
79 : : //! \param[in] coords Pointer to the coordinate data for the destination mesh
80 : : //! \param[in,out] u Pointer to the solution data for the destination mesh
81 : : //! \param[in] cb Callback to call once this chare received all solution data
82 : : // *****************************************************************************
83 : : {
84 : 1232 : m_coord = coords;
85 : 1232 : m_u = static_cast< tk::Fields* >( &u );
86 : 1232 : m_donecb = cb;
87 : :
88 : : // Initialize msg counters, callback, and background solution data
89 : 1232 : m_numsent = 0;
90 : 1232 : m_numreceived = 0;
91 : 1232 : background();
92 : :
93 : : // Send vertex data to the collision detection library
94 : 1232 : collideVertices();
95 : 1232 : }
96 : :
97 : : void
98 : 1232 : TransferDetails::background()
99 : : // *****************************************************************************
100 : : // Initialize dest mesh solution with background data
101 : : //! \details This is useful to see what points did not receive solution.
102 : : // *****************************************************************************
103 : : {
104 : 1232 : tk::Fields& u = *m_u;
105 [ + + ]: 976330 : for (std::size_t i = 0; i < u.nunk(); ++i) u(i,0) = -1.0;
106 : 1232 : }
107 : :
108 : : void
109 : 1232 : TransferDetails::collideVertices()
110 : : // *****************************************************************************
111 : : // Pass vertex information to the collision detection library
112 : : // *****************************************************************************
113 : : {
114 : 1232 : const tk::UnsMesh::Coords& coord = *m_coord;
115 : 1232 : auto nVertices = coord[0].size();
116 : 1232 : std::size_t nBoxes = 0;
117 [ + - ]: 2464 : std::vector< bbox3d > boxes( nVertices );
118 [ + - ]: 2464 : std::vector< int > prio( nVertices );
119 : 1232 : auto firstchunk = static_cast< int >( m_firstchunk );
120 [ + + ]: 976330 : for (std::size_t i=0; i<nVertices; ++i) {
121 [ + - ]: 975098 : boxes[nBoxes].empty();
122 [ + - ]: 975098 : boxes[nBoxes].add(CkVector3d(coord[0][i], coord[1][i], coord[2][i]));
123 : 975098 : prio[nBoxes] = firstchunk;
124 : 975098 : ++nBoxes;
125 : : }
126 [ + - ]: 1232 : CollideBoxesPrio( collideHandle, firstchunk + thisIndex,
127 : 1232 : static_cast<int>(nBoxes), boxes.data(), prio.data() );
128 : 1232 : }
129 : :
130 : : void
131 : 1232 : TransferDetails::collideTets() const
132 : : // *****************************************************************************
133 : : // Pass tet information to the collision detection library
134 : : // *****************************************************************************
135 : : {
136 : 1232 : const std::vector< std::size_t >& inpoel = *m_inpoel;
137 : 1232 : const tk::UnsMesh::Coords& coord = *m_coord;
138 : 1232 : auto nBoxes = inpoel.size() / 4;
139 [ + - ]: 2464 : std::vector< bbox3d > boxes( nBoxes );
140 [ + - ]: 2464 : std::vector< int > prio( nBoxes );
141 : 1232 : auto firstchunk = static_cast< int >( m_firstchunk );
142 [ + + ]: 4107957 : for (std::size_t i=0; i<nBoxes; ++i) {
143 [ + - ]: 4106725 : boxes[i].empty();
144 : 4106725 : prio[i] = firstchunk;
145 [ + + ]: 20533625 : for (std::size_t j=0; j<4; ++j) {
146 : : // Get index of the jth point of the ith tet
147 : 16426900 : auto p = inpoel[i * 4 + j];
148 : : // Add that point to the tets bounding box
149 [ + - ]: 16426900 : boxes[i].add(CkVector3d(coord[0][p], coord[1][p], coord[2][p]));
150 : : }
151 : : }
152 [ + - ]: 1232 : CollideBoxesPrio( collideHandle, firstchunk + thisIndex,
153 : 1232 : static_cast<int>(nBoxes), boxes.data(), prio.data() );
154 : 1232 : }
155 : :
156 : : void
157 : 1232 : TransferDetails::processCollisions(
158 : : CProxy_TransferDetails proxy,
159 : : int numchares,
160 : : int chunkoffset,
161 : : int nColl,
162 : : Collision* colls )
163 : : // *****************************************************************************
164 : : // Process potential collisions by sending my points to the source mesh chares
165 : : // that they potentially collide with.
166 : : //! \param[in] proxy Proxy for the source mesh chares
167 : : //! \param[in] numchares Number of chares in the source mesh chare array
168 : : //! \param[in] chunkoffset First chunk ID of the source mesh
169 : : //! \param[in] nColl Number of potential collisions to process
170 : : //! \param[in] colls List of potential collisions
171 : : // *****************************************************************************
172 : : {
173 : 1232 : const tk::UnsMesh::Coords& coord = *m_coord;
174 : 1232 : int mychunk = thisIndex + m_firstchunk;
175 : :
176 : : std::vector< std::vector< PotentialCollision > >
177 [ + - ]: 2464 : pColls( static_cast<std::size_t>(numchares) );
178 : :
179 : : // Separate potential collisions into lists based on the source mesh chare
180 : : // that is involved in the potential collision
181 [ + + ]: 3462254 : for (int i = 0; i < nColl; i++) {
182 : : int chareindex;
183 [ + - ]: 3461022 : PotentialCollision pColl;
184 [ + + ]: 3461022 : if (colls[i].A.chunk == mychunk) {
185 : 3181956 : chareindex = colls[i].B.chunk - chunkoffset;
186 : 3181956 : pColl.dest_index = static_cast<std::size_t>(colls[i].A.number);
187 : 3181956 : pColl.source_index = static_cast<std::size_t>(colls[i].B.number);
188 : : } else {
189 : 279066 : chareindex = colls[i].A.chunk - chunkoffset;
190 : 279066 : pColl.dest_index = static_cast<std::size_t>(colls[i].B.number);
191 : 279066 : pColl.source_index = static_cast<std::size_t>(colls[i].A.number);
192 : : }
193 : :
194 : : #if defined(STRICT_GNUC)
195 : : #pragma GCC diagnostic push
196 : : #pragma GCC diagnostic ignored "-Wdeprecated-copy"
197 : : #endif
198 : 6922044 : pColl.point = { coord[0][pColl.dest_index],
199 : 3461022 : coord[1][pColl.dest_index],
200 : 3461022 : coord[2][pColl.dest_index] };
201 : : #if defined(STRICT_GNUC)
202 : : #pragma GCC diagnostic pop
203 : : #endif
204 : :
205 [ + - ]: 3461022 : pColls[ static_cast<std::size_t>(chareindex) ].push_back( pColl );
206 : : }
207 : :
208 : : // Send out the lists of potential collisions to the source mesh chares
209 [ + + ]: 6136 : for (int i = 0; i < numchares; i++) {
210 : 4904 : auto I = static_cast< std::size_t >( i );
211 : 4904 : m_numsent++;
212 [ + - ]: 9808 : proxy[i].determineActualCollisions( thisProxy,
213 [ + - ]: 4904 : thisIndex,
214 : 4904 : static_cast<int>(pColls[I].size()),
215 : 4904 : pColls[I].data() );
216 : : }
217 : 1232 : }
218 : :
219 : : void
220 : 4904 : TransferDetails::determineActualCollisions(
221 : : CProxy_TransferDetails proxy,
222 : : int index,
223 : : int nColls,
224 : : PotentialCollision* colls ) const
225 : : // *****************************************************************************
226 : : // Identify actual collisions by calling intet on all possible collisions, and
227 : : // interpolate solution values to send back to the destination mesh.
228 : : //! \param[in] proxy The proxy of the destination mesh chare array
229 : : //! \param[in] index The index in proxy to return the solution data to
230 : : //! \param[in] nColls Number of collisions to be checked
231 : : //! \param[in] colls List of potential collisions
232 : : // *****************************************************************************
233 : : {
234 : 4904 : const std::vector< std::size_t >& inpoel = *m_inpoel;
235 : 4904 : tk::Fields& u = *m_u;
236 : : //CkPrintf("Source chare %i received data for %i potential collisions\n",
237 : : // thisIndex, nColls);
238 : :
239 : : std::array< real, 4 > N;
240 : 4904 : int numInTet = 0;
241 : 4904 : std::vector< SolutionData > return_data;
242 : :
243 : : // Iterate over my potential collisions and call intet() to determine
244 : : // if an actual collision occurred, and if so interpolate solution to dest
245 [ + + ]: 3465926 : for (int i = 0; i < nColls; i++) {
246 : : std::vector< tk::real > point
247 [ + - ]: 6922044 : {colls[i].point.x, colls[i].point.y, colls[i].point.z};
248 [ + - ][ + + ]: 3461022 : if (tk::intet(*m_coord, *m_inpoel, point, colls[i].source_index, N))
249 : : {
250 : 460097 : numInTet++;
251 : 920194 : SolutionData data;
252 : 460097 : data.dest_index = colls[i].dest_index;
253 : 460097 : auto e = colls[i].source_index;
254 : 460097 : const auto A = inpoel[e*4+0];
255 : 460097 : const auto B = inpoel[e*4+1];
256 : 460097 : const auto C = inpoel[e*4+2];
257 : 460097 : const auto D = inpoel[e*4+3];
258 [ + - ]: 460097 : data.solution.resize( u.nprop() );
259 [ + + ]: 3220679 : for (std::size_t c=0; c<u.nprop(); ++c) {
260 [ + - ][ + - ]: 2760582 : data.solution[c] = N[0]*u(A,c) + N[1]*u(B,c) + N[2]*u(C,c) + N[3]*u(D,c);
[ + - ][ + - ]
261 : : }
262 [ + - ]: 460097 : return_data.push_back(data);
263 : : }
264 : : }
265 : : //CkPrintf("Source chare %i found %i/%i actual collisions\n",
266 : : // thisIndex, numInTet, nColls);
267 : : // Send the solution data for the actual collisions back to the dest mesh
268 [ + - ][ + - ]: 4904 : proxy[index].transferSolution( return_data );
269 : 4904 : }
270 : :
271 : : void
272 : 4904 : TransferDetails::transferSolution( const std::vector< SolutionData >& soln )
273 : : // *****************************************************************************
274 : : // Receive the solution data for destination mesh points that collided with the
275 : : // source mesh tetrahedrons
276 : : //! \param[in] soln List of solutions
277 : : // *****************************************************************************
278 : : {
279 : 4904 : tk::Fields& u = *m_u;
280 : :
281 [ + + ]: 465001 : for (std::size_t i=0; i<soln.size(); ++i) {
282 [ + + ]: 3220679 : for (std::size_t c=0; c<u.nprop(); ++c) {
283 : 2760582 : u(soln[i].dest_index,c) = soln[i].solution[c];
284 : : }
285 : : }
286 : :
287 : : // Inform the caller if we've received all solution data
288 : 4904 : m_numreceived++;
289 [ + + ]: 4904 : if (m_numreceived == m_numsent) {
290 : 1232 : m_donecb.send();
291 : : }
292 : 4904 : }
293 : :
294 : : #include "NoWarning/transferdetails.def.h"
|