Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Directory_def.hpp
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TPETRA_DIRECTORY_HPP
11#define TPETRA_DIRECTORY_HPP
12
13#include "Tpetra_Distributor.hpp"
14#include "Tpetra_Map.hpp"
15#include "Tpetra_DirectoryImpl.hpp"
16#include "Tpetra_Directory_decl.hpp"
17
18namespace Tpetra {
19
20template <class LO, class GO, class NT>
23
24template <class LO, class GO, class NT>
26 if (impl_ != NULL) {
27 delete impl_;
28 impl_ = NULL;
29 }
30}
31
32template <class LO, class GO, class NT>
34 return impl_ != NULL;
35}
36
37template <class LO, class GO, class NT>
41 if (initialized()) {
43 impl_ == NULL, std::logic_error,
44 "Tpetra::Directory::initialize: "
45 "The Directory claims that it has been initialized, "
46 "but its implementation object has not yet been created. "
47 "Please report this bug to the Tpetra developers.");
48 } else {
49 TEUCHOS_TEST_FOR_EXCEPTION(
50 impl_ != NULL, std::logic_error,
51 "Tpetra::Directory::initialize: "
52 "Directory implementation has already been initialized, "
53 "but initialized() returns false. "
54 "Please report this bug to the Tpetra developers.");
55
56 // Create an implementation object of the appropriate type,
57 // depending on whether the Map is distributed or replicated,
58 // and contiguous or noncontiguous.
59 //
60 // mfh 06 Apr 2014: When a distributed noncontiguous Directory
61 // takes a TieBreak, all the entries (local indices and process
62 // ranks) owned by the Directory on the calling process pass
63 // through the TieBreak object. This may have side effects,
64 // such as the TieBreak object remembering whether there were
65 // any duplicates on the calling process. We want to extend use
66 // of a TieBreak object to other kinds of Directories. For a
67 // distributed contiguous Directory, the calling process owns
68 // all of the (PID,LID) pairs in the input Map. For a locally
69 // replicated contiguous Directory, Process 0 owns all of the
70 // (PID,LID) pairs in the input Map.
71 //
72 // It may seem silly to pass in a TieBreak when there are no
73 // ties to break. However, the TieBreak object gets to see all
74 // (PID,LID) pairs that the Directory owns on the calling
75 // process, and interface of TieBreak allows side effects.
76 // Users may wish to exploit them regardless of the kind of Map
77 // they pass in.
78 const ::Tpetra::Details::Directory<LO, GO, NT>* dir = NULL;
79 bool usedTieBreak = false;
80 if (map.isDistributed()) {
81 if (map.isUniform()) {
82 dir = new ::Tpetra::Details::ContiguousUniformDirectory<LO, GO, NT>(map);
83 } else if (map.isContiguous()) {
84 dir = new ::Tpetra::Details::DistributedContiguousDirectory<LO, GO, NT>(map);
85 } else {
86 dir = new ::Tpetra::Details::DistributedNoncontiguousDirectory<LO, GO, NT>(map, tieBreak);
87 usedTieBreak = true;
88 }
89 } else {
90 dir = new ::Tpetra::Details::ReplicatedDirectory<LO, GO, NT>(map);
91
92 if (tieBreak.mayHaveSideEffects() && map.getLocalNumElements() != 0) {
93 // We need the second clause in the above test because Map's
94 // interface provides an inclusive range of local indices.
95 const int myRank = map.getComm()->getRank();
96 // In a replicated Directory, Process 0 owns all the
97 // Directory's entries. This is an arbitrary assignment; any
98 // one process would do.
99 if (myRank == 0) {
100 std::vector<std::pair<int, LO> > pidLidList(1);
101 const LO minLocInd = map.getMinLocalIndex();
102 const LO maxLocInd = map.getMaxLocalIndex();
103 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) {
104 pidLidList[0] = std::make_pair(myRank, locInd);
105 const GO globInd = map.getGlobalElement(locInd);
106 // We don't care about the return value; we just want to
107 // invoke the side effects.
108 (void)tieBreak.selectedIndex(globInd, pidLidList);
109 }
110 }
111 }
112 usedTieBreak = true;
113 } // done with all different Map cases
114
115 // If we haven't already used the TieBreak object, use it now.
116 // This code appears twice because ReplicatedDirectory is a
117 // special case: we already know what gets replicated.
118 if (!usedTieBreak && tieBreak.mayHaveSideEffects() &&
119 map.getLocalNumElements() != 0) {
120 // We need the third clause in the above test because Map's
121 // interface provides an inclusive range of local indices.
122 std::vector<std::pair<int, LO> > pidLidList(1);
123 const LO minLocInd = map.getMinLocalIndex();
124 const LO maxLocInd = map.getMaxLocalIndex();
125 const int myRank = map.getComm()->getRank();
126 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) {
127 pidLidList[0] = std::make_pair(myRank, locInd);
128 const GO globInd = map.getGlobalElement(locInd);
129 // We don't care about the return value; we just want to
130 // invoke the side effects.
131 (void)tieBreak.selectedIndex(globInd, pidLidList);
132 }
133 }
134
135 impl_ = dir;
136 }
137}
138
139template <class LO, class GO, class NT>
140void Directory<LO, GO, NT>::initialize(const Map<LO, GO, NT>& map) {
141 if (initialized()) {
142 TEUCHOS_TEST_FOR_EXCEPTION(
143 impl_ == NULL, std::logic_error,
144 "Tpetra::Directory::initialize: "
145 "The Directory claims that it has been initialized, "
146 "but its implementation object has not yet been created. "
147 "Please report this bug to the Tpetra developers.");
148 } else {
149 TEUCHOS_TEST_FOR_EXCEPTION(
150 impl_ != NULL, std::logic_error,
151 "Tpetra::Directory::initialize: "
152 "Directory implementation has already been initialized, "
153 "but initialized() returns false. "
154 "Please report this bug to the Tpetra developers.");
155
156 // Create an implementation object of the appropriate type,
157 // depending on whether the Map is distributed or replicated,
158 // and contiguous or noncontiguous.
159 const ::Tpetra::Details::Directory<LO, GO, NT>* dir = NULL;
160 if (map.isDistributed()) {
161 if (map.isUniform()) {
162 dir = new ::Tpetra::Details::ContiguousUniformDirectory<LO, GO, NT>(map);
163 } else if (map.isContiguous()) {
164 dir = new ::Tpetra::Details::DistributedContiguousDirectory<LO, GO, NT>(map);
165 } else {
166 dir = new ::Tpetra::Details::DistributedNoncontiguousDirectory<LO, GO, NT>(map);
167 }
168 } else {
169 dir = new ::Tpetra::Details::ReplicatedDirectory<LO, GO, NT>(map);
170 }
171 TEUCHOS_TEST_FOR_EXCEPTION(
172 dir == NULL, std::logic_error,
173 "Tpetra::Directory::initialize: "
174 "Failed to create Directory implementation. "
175 "Please report this bug to the Tpetra developers.");
176 impl_ = dir;
177 }
178}
179
180template <class LO, class GO, class NT>
183 getDirectoryEntries(const Map<LO, GO, NT>& map,
184 const Teuchos::ArrayView<const GO>& globalIDs,
185 const Teuchos::ArrayView<int>& nodeIDs) const {
186 if (!initialized()) {
187 // This const_cast is super wrong, but "mutable" is also a lie,
188 // and Map's interface needs this method to be marked const for
189 // some reason.
190 const_cast<Directory<LO, GO, NT>*>(this)->initialize(map);
191 }
192 const bool computeLIDs = false;
193 return impl_->getEntries(map, globalIDs, nodeIDs, Teuchos::null, computeLIDs);
194}
195
196template <class LO, class GO, class NT>
199 getDirectoryEntries(const Map<LO, GO, NT>& map,
200 const Teuchos::ArrayView<const GO>& globalIDs,
201 const Teuchos::ArrayView<int>& nodeIDs,
202 const Teuchos::ArrayView<LO>& localIDs) const {
203 if (!initialized()) {
204 // This const_cast is super wrong, but "mutable" is also a lie,
205 // and Map's interface needs this method to be marked const for
206 // some reason.
207 const_cast<Directory<LO, GO, NT>*>(this)->initialize(map);
208 }
209 const bool computeLIDs = true;
210 return impl_->getEntries(map, globalIDs, nodeIDs, localIDs, computeLIDs);
211}
212
213template <class LO, class GO, class NT>
214bool Directory<LO, GO, NT>::isOneToOne(const Map<LO, GO, NT>& map) const {
215 if (!initialized()) {
216 // This const_cast is super wrong, but "mutable" is also a lie,
217 // and Map's interface needs this method to be marked const for
218 // some reason.
219 const_cast<Directory<LO, GO, NT>*>(this)->initialize(map);
220 }
221 return impl_->isOneToOne(*(map.getComm()));
222}
223
224template <class LO, class GO, class NT>
225std::string
227 using Teuchos::TypeNameTraits;
228
229 std::ostringstream os;
230 os << "Directory"
231 << "<" << TypeNameTraits<LO>::name()
232 << ", " << TypeNameTraits<GO>::name()
233 << ", " << TypeNameTraits<NT>::name() << ">";
234 return os.str();
235}
236
237} // namespace Tpetra
238
239//
240// Explicit instantiation macro
241//
242// Must be expanded from within the Tpetra namespace!
243//
244
245#define TPETRA_DIRECTORY_INSTANT(LO, GO, NODE) \
246 template class Directory<LO, GO, NODE>;
247
248#endif // TPETRA_DIRECTORY_HPP
Struct that holds views of the contents of a CrsMatrix.
Interface for breaking ties in ownership.
virtual bool mayHaveSideEffects() const
Whether selectedIndex() may have side effects.
virtual std::size_t selectedIndex(GlobalOrdinal GID, const std::vector< std::pair< int, LocalOrdinal > > &pid_and_lid) const =0
Break any ties in ownership of the given global index GID.
Implement mapping from global ID to process ID and local ID.
std::string description() const
A one-line human-readable description of this object.
bool isOneToOne(const map_type &map) const
Whether the Directory's input Map is (globally) one to one.
LookupStatus getDirectoryEntries(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs) const
Given a global ID list, return the list of their owning process IDs.
void initialize(const map_type &map)
Initialize the Directory with its Map.
bool initialized() const
Whether the Directory is initialized.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void initialize(int *argc, char ***argv)
Initialize Tpetra.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).