/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2021-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "multiWorldConnectionsObject.H" #include "Pstream.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(multiWorldConnections, 0); } // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // namespace Foam { // Combine world-to-world connections. // Forward connection = 1, Backward connection = 2, Both = 3 struct worldConnectBitOrEq { void operator()(EdgeMap& a, const EdgeMap& b) const { forAllConstIters(b, iter) { a(iter.key()) |= iter.val(); } } }; static void printDOT(Ostream& os, const EdgeMap& connections) { os << nl << "// Multiworld communication graph:" << nl; os.beginBlock("graph"); // Graph Nodes == worlds label worldi = 0; for (const word& worldName : UPstream::allWorlds()) { os.indent(); os << worldi << " [xlabel=" << worldi << ",label=\"" << worldName << "\"]" << nl; ++worldi; } os << nl; // Graph Edges == connections for (const edge& connect : connections.sortedToc()) { os.indent(); os << connect.first() << " -- " << connect.second(); // Mismatched forward/backward connections? if (connections.lookup(connect, 0u) != 3u) { os << " [style=dashed] // mismatched?"; } os << nl; } os.endBlock(); os << "// end graph" << nl; } } // End namespace Foam // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::edge Foam::multiWorldConnections::worldPair(const label otherWorld) { if (otherWorld < 0 || !Pstream::parRun()) { Perr<< "ignore: no world or non-parallel" << endl; return edge(-1, -1); } else if (UPstream::allWorlds().size() <= otherWorld) { Perr<< "ignore: invalid world: " << otherWorld << endl; return edge(-1, -1); } const label thisWorldID = UPstream::myWorldID(); // The worlds (sorted) return edge(thisWorldID, otherWorld, true); } Foam::edge Foam::multiWorldConnections::worldPair(const word& otherWorld) { if (otherWorld.empty() || !Pstream::parRun()) { Perr<< "ignore: no world or non-parallel" << endl; return edge(-1, -1); } const label thisWorldID = UPstream::myWorldID(); const label otherWorldID = UPstream::allWorlds().find(otherWorld); if (otherWorldID < 0) { FatalErrorInFunction << "Cannot find world " << otherWorld << " in set of worlds " << flatOutput(UPstream::allWorlds()) << exit(FatalError); } // The worlds (sorted) return edge(thisWorldID, otherWorldID, true); } Foam::label Foam::multiWorldConnections::createCommunicator(const edge& worlds) { // Fallback: do not create, just use local world label comm = UPstream::worldComm; if (!worlds.valid()) { return comm; } const labelList& worldIDs = UPstream::worldIDs(); DynamicList