Nektar++
InterfaceMapDG.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File InterfaceMapDG.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: MPI communication for interfaces
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include "InterfaceMapDG.h"
36
37namespace Nektar
38{
39namespace MultiRegions
40{
41
43 const ExpListSharedPtr &trace,
44 const SpatialDomains::InterfaceShPtr &interfaceShPtr)
45 : m_trace(trace), m_interface(interfaceShPtr)
46{
47}
48
49// Creates the objects that communicates trace values across the interface in
50// serial and parallel. Does this by checking all interfaces to see if they
51// are contained locally (on the current rank), and checks all other ranks for
52// the same interface ID and if contains the opposite interface side i.e.
53// 'left' or 'right'
56 const ExpListSharedPtr &trace)
57 : m_graph(meshGraph), m_movement(meshGraph->GetMovement()), m_trace(trace)
58{
59 auto comm = m_trace->GetComm()->GetSpaceComm();
60 auto interfaceCollection = m_movement->GetInterfaces();
61
62 // myIndxLR contains the info about what interface edges are present on
63 // current rank with each interface no, i, consisting of:
64 // [i] = indx
65 // [i + 1] = 0 (non), = 1 (left only), = 2 (right only), = 3 (both)
66 std::map<int, int> myIndxLRMap;
67
68 // localInterfaces contains a map of interface ID to a pair of interface
69 // traces, this pair is 'left' and 'right' interface and is used to
70 // construct and store the traces for interfaces present on the current rank
71 std::map<int, std::pair<InterfaceTraceSharedPtr, InterfaceTraceSharedPtr>>
72 localInterfaces;
73
74 // Map of m_localInterfaces vector to interface ID
75 Array<OneD, int> indxToInterfaceID(interfaceCollection.size());
76
77 // Loops over all interfaces and check if either side, 'left' or 'right'
78 // are empty on the current rank, if not empty then populate the local
79 // interface data structures and keep track using myIndxLRMap
80 size_t cnt = 0;
81 for (const auto &interface : interfaceCollection)
82 {
83 indxToInterfaceID[cnt] = interface.first.first;
84 myIndxLRMap[interface.first.first] = 0;
85
86 if (!interface.second->GetLeftInterface()->IsEmpty())
87 {
88 myIndxLRMap[interface.first.first] += 1;
89
90 localInterfaces[interface.first.first].first =
92 trace, interface.second->GetLeftInterface());
93 m_localInterfaces.emplace_back(
94 localInterfaces[interface.first.first].first);
95 }
96
97 if (!interface.second->GetRightInterface()->IsEmpty())
98 {
99 myIndxLRMap[interface.first.first] += 2;
100
101 localInterfaces[interface.first.first].second =
103 trace, interface.second->GetRightInterface());
104 m_localInterfaces.emplace_back(
105 localInterfaces[interface.first.first].second);
106 }
107
108 cnt++;
109 }
110
111 // Send num of interfaces size so all partitions can prepare buffers
112 int nRanks = comm->GetSize();
113
114 // Send all interface edges present to all partitions
115 Array<OneD, int> interfaceEdges(myIndxLRMap.size());
116 cnt = 0;
117 for (auto pres : myIndxLRMap)
118 {
119 interfaceEdges[cnt++] = pres.second;
120 }
121 Array<OneD, int> rankLocalInterfaceIds(myIndxLRMap.size() * nRanks, 0);
122 comm->AllGather(interfaceEdges, rankLocalInterfaceIds);
123
124 // Map of rank to vector of interface traces
125 std::map<int, std::vector<InterfaceTraceSharedPtr>> oppRankSharedInterface;
126
127 // Find what interface Ids match with other ranks, then check if opposite
128 // edge
129 size_t myRank = comm->GetRank();
130 size_t numInterfaces = interfaceCollection.size();
131 for (int i = 0; i < nRanks; ++i)
132 {
133 for (size_t j = 0; j < numInterfaces; ++j)
134 {
135 int otherId = indxToInterfaceID[j];
136
137 // otherCode represents for a specific interface ID what sides are
138 // present on rank i, 0=non, 1=left, 2=right, 3=both
139 int otherCode = rankLocalInterfaceIds[i * numInterfaces + j];
140
141 // myCode represents for a specific interface ID what sides are
142 // present on this rank/process 0=non, 1=left, 2=right, 3=both
143 int myCode = myIndxLRMap[otherId];
144
145 // Special case if checking current rank (this process)
146 if (i == myRank)
147 {
148 // If contains both edges locally then set check local to true
149 if (myCode == 3)
150 {
151 localInterfaces[otherId].first->SetCheckLocal(true);
152 localInterfaces[otherId].second->SetCheckLocal(true);
153 }
154
155 continue;
156 }
157
158 // Checks if this ranks 'left' matches any 'right' on other rank
159 if ((myCode == 1 && otherCode == 2) ||
160 (myCode == 1 && otherCode == 3) ||
161 (myCode == 3 && otherCode == 2))
162 {
163 oppRankSharedInterface[i].emplace_back(
164 localInterfaces[otherId].first);
165 }
166 // Checks if this ranks 'right' matches any 'left' on other rank
167 else if ((myCode == 2 && otherCode == 1) ||
168 (myCode == 2 && otherCode == 3) ||
169 (myCode == 3 && otherCode == 1))
170 {
171 oppRankSharedInterface[i].emplace_back(
172 localInterfaces[otherId].second);
173 }
174 // Checks if this ranks 'both' matches any 'both' on other rank
175 else if (myCode == 3 && otherCode == 3)
176 {
177 oppRankSharedInterface[i].emplace_back(
178 localInterfaces[otherId].first);
179 oppRankSharedInterface[i].emplace_back(
180 localInterfaces[otherId].second);
181 }
182 }
183 }
184
185 // Create individual interface exchange objects (each object is rank ->
186 // rank) and contains a vector of interfaceTrace objects
187 for (auto &rank : oppRankSharedInterface)
188 {
189 m_exchange.emplace_back(
191 m_movement, m_trace, comm, rank));
192 }
193
194 // Find missing coordinates on interface from other side
196}
197
199{
200 auto comm = m_trace->GetComm()->GetSpaceComm();
201 auto zones = m_movement->GetZones();
202
203 for (auto &interfaceTrace : m_localInterfaces)
204 {
205 interfaceTrace->CalcLocalMissing();
206 }
207
208 // If parallel communication is needed
209 if (!m_exchange.empty())
210 {
211 auto requestSend = comm->CreateRequest(m_exchange.size());
212 auto requestRecv = comm->CreateRequest(m_exchange.size());
213
214 for (int i = 0; i < m_exchange.size(); ++i)
215 {
216 m_exchange[i]->RankFillSizes(requestSend, requestRecv, i);
217 }
218 comm->WaitAll(requestSend);
219 comm->WaitAll(requestRecv);
220
221 for (int i = 0; i < m_exchange.size(); ++i)
222 {
223 m_exchange[i]->SendMissing(requestSend, requestRecv, i);
224 }
225 comm->WaitAll(requestSend);
226 comm->WaitAll(requestRecv);
227
228 for (auto &i : m_exchange)
229 {
230 i->CalcRankDistances();
231 }
232 }
233}
234
235/**
236 * Calculates what coordinates on the interface are missing; i.e. aren't located
237 * in an edge from the other side of the interface on this partition. These are
238 * stored in the vector #m_missingCoords, and another vector of the same index
239 * layout contains the location of that coordinate in the trace i.e. the
240 * 'offset + i' value. It checks first if the interface is flagged local, which
241 * denotes whether the opposite side is also present on this rank, if not then
242 * all coordinates are missing. If local then the same structure as
243 * CalcRankDistances is used to minimise computational cost.
244 */
246{
247 auto childEdge = m_interface->GetEdge();
248 // If not flagged 'check local' then all points are missing
249 if (!m_checkLocal)
250 {
251 int cnt = 0;
252 for (auto &childId : childEdge)
253 {
254 auto childElmt = m_trace->GetExpFromGeomId(childId.first);
255 size_t nq = childElmt->GetTotPoints();
256 Array<OneD, NekDouble> xc(nq, 0.0), yc(nq, 0.0), zc(nq, 0.0);
257 childElmt->GetCoords(xc, yc, zc);
258 int offset =
259 m_trace->GetPhys_Offset(m_trace->GetElmtToExpId(childId.first));
260
261 for (int i = 0; i < nq; ++i, ++cnt)
262 {
264 xs[0] = xc[i];
265 xs[1] = yc[i];
266 xs[2] = zc[i];
267
268 m_missingCoords.emplace_back(xs);
269 m_mapMissingCoordToTrace.emplace_back(offset + i);
270 }
271 }
272 }
273 // Otherwise we need to check to see what points the other side of the
274 // interface on this rank contains. This is done by looping over each
275 // quadrature point in all the edges on this side of the interface, then
276 // check if this quadrature point is also in any edges on the other side
277 // of the interface. First use MinMaxCheck as a cheap method to eliminate
278 // far away edges. If it passes MinMaxCheck perform the FindDistance search
279 // which numerically searches for the closest local coordinate on the other
280 // interface side edge and returns the cartesian distance from the search
281 // coordinate to the found local coordinate. If determined to be close
282 // enough then add to found local coordinates.
283 else
284 {
285 for (auto &childId : childEdge)
286 {
287 auto childElmt = m_trace->GetExpFromGeomId(childId.first);
288 size_t nq = childElmt->GetTotPoints();
289 Array<OneD, NekDouble> xc(nq, 0.0), yc(nq, 0.0), zc(nq, 0.0);
290 childElmt->GetCoords(xc, yc, zc);
291 int offset =
292 m_trace->GetPhys_Offset(m_trace->GetElmtToExpId(childId.first));
293
294 for (int i = 0; i < nq; ++i)
295 {
296 bool found = false;
297 Array<OneD, NekDouble> foundLocCoord;
299 xs[0] = xc[i];
300 xs[1] = yc[i];
301 xs[2] = zc[i];
302
303 auto parentEdge = m_interface->GetOppInterface()->GetEdge();
304 for (auto &edge : parentEdge)
305 {
306 // First check if inside the edge bounding box
307 if (!edge.second->MinMaxCheck(xs))
308 {
309 continue;
310 }
311
312 NekDouble dist =
313 edge.second->FindDistance(xs, foundLocCoord);
315 {
316 found = true;
317 m_foundLocalCoords[offset + i] = std::make_pair(
318 edge.second->GetGlobalID(), foundLocCoord);
319 break;
320 }
321 }
322
323 if (!found)
324 {
325 m_missingCoords.emplace_back(xs);
326 m_mapMissingCoordToTrace.emplace_back(offset + i);
327 }
328 }
329 }
330 }
331
332 // If running in serial there shouldn't be any missing coordinates.
333 if (m_trace->GetComm()->IsSerial())
334 {
336 "Missing " + std::to_string(m_missingCoords.size()) +
337 " coordinates on interface ID " +
338 std::to_string(m_interface->GetId()) +
339 " linked to interface ID " +
340 std::to_string(m_interface->GetOppInterface()->GetId()) +
341 ". Check both sides of the interface line up.");
342 }
343}
344
345// This fills m_sendSize and m_recvSize with the correct sizes for the
346// communication lengths for each rank when communicating the traces. I.e.
347// however many quadrature points on the opposite side of the interface to
348// send, and however many on this side to receive.
351 LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum)
352{
353
354 // Recalc size is the number of interfaces missing points that need to be
355 // communicated.
356 int recalcSize = 0;
357 for (auto &localInterface : m_interfaceTraces)
358 {
359 recalcSize +=
360 m_zones[localInterface->GetInterface()->GetId()]->GetMoved();
361 }
362
363 m_sendSize[m_rank] = Array<OneD, int>(recalcSize);
364 m_recvSize[m_rank] = Array<OneD, int>(recalcSize);
365
366 int cnt = 0;
367 for (auto &interface : m_interfaceTraces)
368 {
369 if (m_zones[interface->GetInterface()->GetId()]->GetMoved())
370 {
371 // Calculates the number of missing coordinates to be communicated
372 // This size is 3 times the number of missing coordinates to allow
373 // for 3D points
374 m_sendSize[m_rank][cnt++] =
375 interface->GetMissingCoords().size() * 3;
376 }
377 }
378
379 // Uses non-blocking send/recvs to send communication sizes to other ranks
381 requestSend, requestNum);
383 requestRecv, requestNum);
384}
385
386// Uses the calculated send/recv sizes to send all missing coordinates to
387// other ranks.
390 LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum)
391{
392 m_totSendSize[m_rank] = std::accumulate(m_sendSize[m_rank].begin(),
393 m_sendSize[m_rank].end(), 0);
394 m_totRecvSize[m_rank] = std::accumulate(m_recvSize[m_rank].begin(),
395 m_recvSize[m_rank].end(), 0);
396
399
400 int cnt = 0;
401 for (auto &interface : m_interfaceTraces)
402 {
403 if (m_zones[interface->GetInterface()->GetId()]->GetMoved())
404 {
405 auto missing = interface->GetMissingCoords();
406 for (auto coord : missing)
407 {
408 // Points are organised in blocks of three
409 // x coord, then y coord, then z coord.
410 for (int k = 0; k < 3; ++k, ++cnt)
411 {
412 m_send[cnt] = coord[k];
413 }
414 }
415 }
416 }
417
418 // Uses non-blocking send/recvs to send missing points to other ranks
419 m_comm->Isend(m_rank, m_send, m_totSendSize[m_rank], requestSend,
420 requestNum);
421 m_comm->Irecv(m_rank, m_recv, m_totRecvSize[m_rank], requestRecv,
422 requestNum);
423}
424
425/**
426 * Performs the trace exchange across interfaces
427 * 1) Calculate and send the Fwd trace to other ranks with pairwise comms
428 * 2) While waiting for the send/recv to complete we fill the local interfaces
429 * Bwd trace
430 * 3) Fill the remaining Bwd trace with the received trace data from other ranks
431 */
434{
435 auto comm = m_trace->GetComm()->GetSpaceComm();
436
437 // If no parallel exchange needed we only fill the local traces
438 if (m_exchange.empty())
439 {
440 // Fill local interface traces
441 for (auto &m_localInterface : m_localInterfaces)
442 {
443 m_localInterface->FillLocalBwdTrace(Fwd, Bwd);
444 }
445 }
446 else
447 {
448 auto requestSend = comm->CreateRequest(m_exchange.size());
449 auto requestRecv = comm->CreateRequest(m_exchange.size());
450 for (int i = 0; i < m_exchange.size(); ++i)
451 {
452 m_exchange[i]->SendFwdTrace(requestSend, requestRecv, i, Fwd);
453 }
454
455 // Fill local interface traces
456 for (auto &m_localInterface : m_localInterfaces)
457 {
458 m_localInterface->FillLocalBwdTrace(Fwd, Bwd);
459 }
460
461 comm->WaitAll(requestSend);
462 comm->WaitAll(requestRecv);
463
464 // Fill communicated interface traces
465 for (auto &i : m_exchange)
466 {
467 i->FillRankBwdTraceExchange(Bwd);
468 }
469 }
470}
471
474{
475 // If flagged then fill trace from local coords
476 if (m_checkLocal)
477 {
478 for (auto &foundLocCoord : m_foundLocalCoords)
479 {
480 int traceId = m_trace->GetElmtToExpId(foundLocCoord.second.first);
481 Array<OneD, NekDouble> locCoord = foundLocCoord.second.second;
482
483 Array<OneD, NekDouble> edgePhys =
484 Fwd + m_trace->GetPhys_Offset(traceId);
485
486 Bwd[foundLocCoord.first] =
487 m_trace->GetExp(traceId)->StdPhysEvaluate(locCoord, edgePhys);
488 }
489 }
490}
491
493{
494 int cnt = 0;
495 for (int i = 0; i < m_interfaceTraces.size(); ++i)
496 {
497 Array<OneD, NekDouble> traceTmp(m_sendSize[m_rank][i] / 3, 0.0);
498 for (int j = 0; j < m_sendSize[m_rank][i] / 3; ++j, ++cnt)
499 {
500 traceTmp[j] = m_recvTrace[cnt];
501 }
502
503 m_interfaceTraces[i]->FillRankBwdTrace(traceTmp, Bwd);
504 }
505}
506
509{
510 for (int i = 0; i < m_mapMissingCoordToTrace.size(); ++i)
511 {
512 if (!std::isnan(trace[i]))
513 {
514 Bwd[m_mapMissingCoordToTrace[i]] = trace[i];
515 }
516 }
517}
518
521 LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum,
523{
525 Array<OneD, NekDouble>(m_totSendSize[m_rank] / 3, std::nan(""));
527 Array<OneD, NekDouble>(m_totRecvSize[m_rank] / 3, std::nan(""));
528
529 for (auto &i : m_foundRankCoords[m_rank])
530 {
531 int traceId = m_trace->GetElmtToExpId(i.second.first);
532 Array<OneD, NekDouble> locCoord = i.second.second;
533
534 Array<OneD, NekDouble> edgePhys =
535 Fwd + m_trace->GetPhys_Offset(traceId);
536
537 m_sendTrace[i.first] =
538 m_trace->GetExp(traceId)->StdPhysEvaluate(locCoord, edgePhys);
539 }
540
541 m_comm->Isend(m_rank, m_sendTrace, m_sendTrace.size(), requestSend,
542 requestNum);
543 m_comm->Irecv(m_rank, m_recvTrace, m_recvTrace.size(), requestRecv,
544 requestNum);
545}
546
547/**
548 * Check coords in m_recv from other rank to see if present on this rank, and
549 * then populates m_foundRankCoords if found.
550 * - Loops over all interface traces present in the exchange, i.e. every
551 * interface needed on this rank-to-rank communication object
552 * - Then loops over all the quadrature points missing from the other side in
553 * that interface using global coordinates
554 * - Loop over each local edge and use MinMaxCheck on the point as a fast
555 * comparison on whether the point lies on the edge
556 * - If true then use the more expensive FindDistance function to find the
557 * closest local coordinate of the global 'missing' point on the local edge
558 * and the distance from the edge that corresponds to
559 * - If distance is less than 5e-5 save found coordinate in m_foundRankCoords
560 */
561
563{
564 Array<OneD, int> disp(m_recvSize[m_rank].size() + 1, 0.0);
565 std::partial_sum(m_recvSize[m_rank].begin(), m_recvSize[m_rank].end(),
566 &disp[1]);
567
568 for (int i = 0; i < m_interfaceTraces.size(); ++i)
569 {
570 auto localEdge = m_interfaceTraces[i]->GetInterface()->GetEdge();
571
572 for (int j = disp[i]; j < disp[i + 1]; j += 3)
573 {
574 Array<OneD, NekDouble> foundLocCoord;
576 xs[0] = m_recv[j];
577 xs[1] = m_recv[j + 1];
578 xs[2] = m_recv[j + 2];
579
580 for (auto &edge : localEdge)
581 {
582 // First check if inside the edge bounding box
583 if (!edge.second->MinMaxCheck(xs))
584 {
585 continue;
586 }
587
588 NekDouble dist = edge.second->FindDistance(xs, foundLocCoord);
589
591 {
592 m_foundRankCoords[m_rank][j / 3] = std::make_pair(
593 edge.second->GetGlobalID(), foundLocCoord);
594 break;
595 }
596 }
597 }
598 }
599}
600
601} // namespace MultiRegions
602} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::map< int, Array< OneD, int > > m_sendSize
Map of rank to array of size of send buffer for each interface.
void RankFillSizes(LibUtilities::CommRequestSharedPtr &requestSend, LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum)
std::map< int, SpatialDomains::ZoneBaseShPtr > m_zones
Map of zone IDs to zone bases.
const ExpListSharedPtr m_trace
Trace expansion list.
void FillRankBwdTraceExchange(Array< OneD, NekDouble > &Bwd)
const std::vector< InterfaceTraceSharedPtr > m_interfaceTraces
Vector of interface traces i.e. every interface side present on m_rank.
const LibUtilities::CommSharedPtr m_comm
Communicator.
void SendFwdTrace(LibUtilities::CommRequestSharedPtr &requestSend, LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum, Array< OneD, NekDouble > &Fwd)
Array< OneD, NekDouble > m_send
Send buffer for coord exchange.
std::map< int, std::map< int, std::pair< int, Array< OneD, NekDouble > > > > m_foundRankCoords
std::map< int, int > m_totSendSize
Map of rank to total size of send buffer for all interfaces.
void CalcRankDistances()
Populates m_foundRankCoords using the FindDistance function.
std::map< int, int > m_totRecvSize
Map of rank to total size of receive buffer for all interfaces.
std::map< int, Array< OneD, int > > m_recvSize
Map of rank to array of size of receive buffer for each interface.
Array< OneD, NekDouble > m_recv
Receive buffer for coord exchange.
void SendMissing(LibUtilities::CommRequestSharedPtr &requestSend, LibUtilities::CommRequestSharedPtr &requestRecv, int requestNum)
Array< OneD, NekDouble > m_recvTrace
Receive buffer for trace exchange.
Array< OneD, NekDouble > m_sendTrace
Send buffer for trace exchange.
const ExpListSharedPtr m_trace
Trace expansion list.
void ExchangeTrace(Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
Perform the trace exchange between processors, given the forwards and backwards spaces.
std::vector< InterfaceExchangeSharedPtr > m_exchange
Vector of interface exchanges, i.e. every rank-to-rank comm needed.
void ExchangeCoords()
Perform the coordinate exchange between processors. This is where the missing coordinates on the inte...
SpatialDomains::MovementSharedPtr m_movement
Movement object associated with the non-conformal interfaces.
InterfaceMapDG(const SpatialDomains::MeshGraphSharedPtr &graph, const ExpListSharedPtr &trace)
std::vector< InterfaceTraceSharedPtr > m_localInterfaces
Interface sides present on current process.
ExpListSharedPtr m_trace
Trace expansion list.
std::map< int, std::pair< int, Array< OneD, NekDouble > > > m_foundLocalCoords
Map of found coordinates present locally.
std::vector< int > m_mapMissingCoordToTrace
Vector of indices corresponding to m_missingCoord locations in trace.
SpatialDomains::InterfaceShPtr m_interface
Local interface object.
std::vector< Array< OneD, NekDouble > > m_missingCoords
Vector of coordinates on interface missing from the other side locally.
InterfaceTrace(const ExpListSharedPtr &trace, const SpatialDomains::InterfaceShPtr &interfaceShPtr)
Constructor.
void FillRankBwdTrace(Array< OneD, NekDouble > &trace, Array< OneD, NekDouble > &Bwd)
Fills the Bwd trace from partitioned trace.
void CalcLocalMissing()
Calculates what coordinates on the interface are missing locally.
void FillLocalBwdTrace(Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
Fills the Bwd trace by interpolating from the Fwd for local interfaces.
bool m_checkLocal
Flag whether the opposite side of the interface is present locally.
std::shared_ptr< CommRequest > CommRequestSharedPtr
Definition: Comm.h:86
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static const NekDouble kFindDistanceMin
std::shared_ptr< Interface > InterfaceShPtr
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble