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
20 template<class LO, class GO, class NT>
22 impl_ (NULL)
23 {}
24
25 template<class LO, class GO, class NT>
27 if (impl_ != NULL) {
28 delete impl_;
29 impl_ = NULL;
30 }
31 }
32
33 template<class LO, class GO, class NT>
34 bool
36 return impl_ != NULL;
37 }
38
39
40 template<class LO, class GO, class NT>
41 void
45 {
46 if (initialized ()) {
47 TEUCHOS_TEST_FOR_EXCEPTION(
48 impl_ == NULL, std::logic_error, "Tpetra::Directory::initialize: "
49 "The Directory claims that it has been initialized, "
50 "but its implementation object has not yet been created. "
51 "Please report this bug to the Tpetra developers.");
52 }
53 else {
54 TEUCHOS_TEST_FOR_EXCEPTION(
55 impl_ != NULL, std::logic_error, "Tpetra::Directory::initialize: "
56 "Directory implementation has already been initialized, "
57 "but initialized() returns false. "
58 "Please report this bug to the Tpetra developers.");
59
60 // Create an implementation object of the appropriate type,
61 // depending on whether the Map is distributed or replicated,
62 // and contiguous or noncontiguous.
63 //
64 // mfh 06 Apr 2014: When a distributed noncontiguous Directory
65 // takes a TieBreak, all the entries (local indices and process
66 // ranks) owned by the Directory on the calling process pass
67 // through the TieBreak object. This may have side effects,
68 // such as the TieBreak object remembering whether there were
69 // any duplicates on the calling process. We want to extend use
70 // of a TieBreak object to other kinds of Directories. For a
71 // distributed contiguous Directory, the calling process owns
72 // all of the (PID,LID) pairs in the input Map. For a locally
73 // replicated contiguous Directory, Process 0 owns all of the
74 // (PID,LID) pairs in the input Map.
75 //
76 // It may seem silly to pass in a TieBreak when there are no
77 // ties to break. However, the TieBreak object gets to see all
78 // (PID,LID) pairs that the Directory owns on the calling
79 // process, and interface of TieBreak allows side effects.
80 // Users may wish to exploit them regardless of the kind of Map
81 // they pass in.
82 const ::Tpetra::Details::Directory<LO, GO, NT>* dir = NULL;
83 bool usedTieBreak = false;
84 if (map.isDistributed ()) {
85 if (map.isUniform ()) {
86 dir = new ::Tpetra::Details::ContiguousUniformDirectory<LO, GO, NT> (map);
87 }
88 else if (map.isContiguous ()) {
89 dir = new ::Tpetra::Details::DistributedContiguousDirectory<LO, GO, NT> (map);
90 }
91 else {
92 dir = new ::Tpetra::Details::DistributedNoncontiguousDirectory<LO, GO, NT> (map, tieBreak);
93 usedTieBreak = true;
94 }
95 }
96 else {
97 dir = new ::Tpetra::Details::ReplicatedDirectory<LO, GO, NT> (map);
98
99 if (tieBreak.mayHaveSideEffects () && map.getLocalNumElements () != 0) {
100 // We need the second clause in the above test because Map's
101 // interface provides an inclusive range of local indices.
102 const int myRank = map.getComm ()->getRank ();
103 // In a replicated Directory, Process 0 owns all the
104 // Directory's entries. This is an arbitrary assignment; any
105 // one process would do.
106 if (myRank == 0) {
107 std::vector<std::pair<int, LO> > pidLidList (1);
108 const LO minLocInd = map.getMinLocalIndex ();
109 const LO maxLocInd = map.getMaxLocalIndex ();
110 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) {
111 pidLidList[0] = std::make_pair (myRank, locInd);
112 const GO globInd = map.getGlobalElement (locInd);
113 // We don't care about the return value; we just want to
114 // invoke the side effects.
115 (void) tieBreak.selectedIndex (globInd, pidLidList);
116 }
117 }
118 }
119 usedTieBreak = true;
120 } // done with all different Map cases
121
122 // If we haven't already used the TieBreak object, use it now.
123 // This code appears twice because ReplicatedDirectory is a
124 // special case: we already know what gets replicated.
125 if (! usedTieBreak && tieBreak.mayHaveSideEffects () &&
126 map.getLocalNumElements () != 0) {
127 // We need the third clause in the above test because Map's
128 // interface provides an inclusive range of local indices.
129 std::vector<std::pair<int, LO> > pidLidList (1);
130 const LO minLocInd = map.getMinLocalIndex ();
131 const LO maxLocInd = map.getMaxLocalIndex ();
132 const int myRank = map.getComm ()->getRank ();
133 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) {
134 pidLidList[0] = std::make_pair (myRank, locInd);
135 const GO globInd = map.getGlobalElement (locInd);
136 // We don't care about the return value; we just want to
137 // invoke the side effects.
138 (void) tieBreak.selectedIndex (globInd, pidLidList);
139 }
140 }
141
142 impl_ = dir;
143 }
144 }
145
146 template<class LO, class GO, class NT>
147 void
149 {
150 if (initialized ()) {
151 TEUCHOS_TEST_FOR_EXCEPTION(
152 impl_ == NULL, std::logic_error, "Tpetra::Directory::initialize: "
153 "The Directory claims that it has been initialized, "
154 "but its implementation object has not yet been created. "
155 "Please report this bug to the Tpetra developers.");
156 }
157 else {
158 TEUCHOS_TEST_FOR_EXCEPTION(
159 impl_ != NULL, std::logic_error, "Tpetra::Directory::initialize: "
160 "Directory implementation has already been initialized, "
161 "but initialized() returns false. "
162 "Please report this bug to the Tpetra developers.");
163
164 // Create an implementation object of the appropriate type,
165 // depending on whether the Map is distributed or replicated,
166 // and contiguous or noncontiguous.
167 const ::Tpetra::Details::Directory<LO, GO, NT>* dir = NULL;
168 if (map.isDistributed ()) {
169 if (map.isUniform ()) {
170 dir = new ::Tpetra::Details::ContiguousUniformDirectory<LO, GO, NT> (map);
171 }
172 else if (map.isContiguous ()) {
173 dir = new ::Tpetra::Details::DistributedContiguousDirectory<LO, GO, NT> (map);
174 }
175 else {
176 dir = new ::Tpetra::Details::DistributedNoncontiguousDirectory<LO, GO, NT> (map);
177 }
178 }
179 else {
180 dir = new ::Tpetra::Details::ReplicatedDirectory<LO, GO, NT> (map);
181 }
182 TEUCHOS_TEST_FOR_EXCEPTION(
183 dir == NULL, std::logic_error, "Tpetra::Directory::initialize: "
184 "Failed to create Directory implementation. "
185 "Please report this bug to the Tpetra developers.");
186 impl_ = dir;
187 }
188 }
189
190 template<class LO, class GO, class NT>
194 const Teuchos::ArrayView<const GO>& globalIDs,
195 const Teuchos::ArrayView<int>& nodeIDs) const
196 {
197 if (! initialized ()) {
198 // This const_cast is super wrong, but "mutable" is also a lie,
199 // and Map's interface needs this method to be marked const for
200 // some reason.
201 const_cast<Directory<LO, GO, NT>* > (this)->initialize (map);
202 }
203 const bool computeLIDs = false;
204 return impl_->getEntries (map, globalIDs, nodeIDs, Teuchos::null, computeLIDs);
205 }
206
207 template<class LO, class GO, class NT>
211 const Teuchos::ArrayView<const GO>& globalIDs,
212 const Teuchos::ArrayView<int>& nodeIDs,
213 const Teuchos::ArrayView<LO>& localIDs) const
214 {
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 const bool computeLIDs = true;
222 return impl_->getEntries (map, globalIDs, nodeIDs, localIDs, computeLIDs);
223 }
224
225 template<class LO, class GO, class NT>
226 bool Directory<LO, GO, NT>::isOneToOne (const Map<LO, GO, NT>& map) const {
227 if (! initialized ()) {
228 // This const_cast is super wrong, but "mutable" is also a lie,
229 // and Map's interface needs this method to be marked const for
230 // some reason.
231 const_cast<Directory<LO, GO, NT>* > (this)->initialize (map);
232 }
233 return impl_->isOneToOne (* (map.getComm ()));
234 }
235
236 template<class LO, class GO, class NT>
237 std::string
239 {
240 using Teuchos::TypeNameTraits;
241
242 std::ostringstream os;
243 os << "Directory"
244 << "<" << TypeNameTraits<LO>::name ()
245 << ", " << TypeNameTraits<GO>::name ()
246 << ", " << TypeNameTraits<NT>::name () << ">";
247 return os.str ();
248 }
249
250} // namespace Tpetra
251
252//
253// Explicit instantiation macro
254//
255// Must be expanded from within the Tpetra namespace!
256//
257
258#define TPETRA_DIRECTORY_INSTANT(LO,GO,NODE) \
259 template class Directory< LO , GO , NODE >;
260
261#endif // TPETRA_DIRECTORY_HPP
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.
Directory()
Default constructor: the only one you should use.
A parallel distribution of indices over processes.
bool isDistributed() const
Whether this Map is globally distributed or locally replicated.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
bool isUniform() const
Whether the range of global indices is uniform.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Accessors for the Teuchos::Comm and Kokkos Node objects.
bool isContiguous() const
True if this Map is distributed contiguously, else false.
local_ordinal_type getMinLocalIndex() const
The minimum local index.
size_t getLocalNumElements() const
The number of elements belonging to the calling process.
local_ordinal_type getMaxLocalIndex() const
The maximum local index on the calling process.
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()).