------------------------------------------------------------------------------
| 486 | |
| 487 | //------------------------------------------------------------------------------ |
| 488 | bool vtkParticleTracerBase::SendReceiveParticles( |
| 489 | std::vector<vtkIdType>& newReceivedInjectedPointIds) |
| 490 | { |
| 491 | int numParticles = static_cast<int>(this->MPISendList.size()); |
| 492 | |
| 493 | std::vector<int> allNumParticles(this->Controller->GetNumberOfProcesses(), 0); |
| 494 | // Broadcast and receive size to/from all other processes. |
| 495 | this->Controller->AllGather(&numParticles, allNumParticles.data(), 1); |
| 496 | |
| 497 | // write the message |
| 498 | constexpr int typeSize = sizeof(ParticleInformation); |
| 499 | |
| 500 | vtkIdType messageSize = numParticles * typeSize; |
| 501 | std::vector<char> sendMessage(messageSize, 0); |
| 502 | for (int i = 0; i < numParticles; i++) |
| 503 | { |
| 504 | memcpy(&sendMessage[i * typeSize], &this->MPISendList[i], typeSize); |
| 505 | auto it = this->MPIRecvList.find(this->MPISendList[i].InjectedPointId); |
| 506 | if (it != this->MPIRecvList.end()) |
| 507 | { |
| 508 | this->MPIRecvList.erase(it); |
| 509 | } |
| 510 | } |
| 511 | |
| 512 | std::vector<vtkIdType> messageLength(this->Controller->GetNumberOfProcesses(), 0); |
| 513 | std::vector<vtkIdType> messageOffset(this->Controller->GetNumberOfProcesses() + 1, 0); |
| 514 | int allMessageSize(0); |
| 515 | int numAllParticles(0); |
| 516 | for (int i = 0; i < this->Controller->GetNumberOfProcesses(); ++i) |
| 517 | { |
| 518 | numAllParticles += allNumParticles[i]; |
| 519 | messageLength[i] = allNumParticles[i] * typeSize; |
| 520 | messageOffset[i] = allMessageSize; |
| 521 | allMessageSize += messageLength[i]; |
| 522 | } |
| 523 | messageOffset.back() = allMessageSize; |
| 524 | |
| 525 | // receive the message |
| 526 | std::vector<char> recvMessage(allMessageSize, 0); |
| 527 | this->Controller->AllGatherV(messageSize > 0 ? sendMessage.data() : nullptr, |
| 528 | allMessageSize > 0 ? recvMessage.data() : nullptr, messageSize, messageLength.data(), |
| 529 | messageOffset.data()); |
| 530 | |
| 531 | int myRank = this->Controller->GetLocalProcessId(); |
| 532 | |
| 533 | // owningProcess is used to make sure that particles that are sent aren't added |
| 534 | // on multiple processes |
| 535 | std::vector<vtkIdType> owningProcess(numAllParticles, -1); |
| 536 | // we automatically ignore particles that we sent |
| 537 | int ignoreBegin = messageOffset[myRank] / typeSize; |
| 538 | int ignoreEnd = ignoreBegin + messageLength[myRank] / typeSize; |
| 539 | for (int i = 0; i < numAllParticles; i++) |
| 540 | { |
| 541 | if (i < ignoreBegin || i >= ignoreEnd) |
| 542 | { |
| 543 | ParticleInformation tmpParticle; |
| 544 | memcpy(&tmpParticle, &recvMessage[i * typeSize], typeSize); |
| 545 | // since this is first test, avoid bad cache tests |
no test coverage detected