Xpetra Version of the Day
Loading...
Searching...
No Matches
Xpetra_MapUtils.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Xpetra: A linear algebra interface package
4//
5// Copyright 2012 NTESS and the Xpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef PACKAGES_XPETRA_SUP_MAP_UTILS_HPP_
11#define PACKAGES_XPETRA_SUP_MAP_UTILS_HPP_
12
13#include "Xpetra_ConfigDefs.hpp"
14
15#include "Xpetra_Exceptions.hpp"
16#include "Xpetra_Map.hpp"
17#include "Xpetra_MapFactory.hpp"
18
19namespace Xpetra {
20
21#ifndef DOXYGEN_SHOULD_SKIP_THIS
22// forward declaration of BlockedMap, needed to prevent circular inclusions
23template <class LO, class GO, class N>
24class BlockedMap;
25#endif
26
34template <class LocalOrdinal,
35 class GlobalOrdinal,
36 class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
37class MapUtils {
38#undef XPETRA_MAPUTILS_SHORT
40
41 public:
57 // ToDo Resolve header issues to allow for using this routing in Xpetra::BlockedMap.
58
59 // merge submaps to global map
60 std::vector<GlobalOrdinal> gids;
61 for (size_t tt = 0; tt < subMaps.size(); ++tt) {
63 Teuchos::ArrayView<const GlobalOrdinal> subMapGids = subMap->getLocalElementList();
64 gids.insert(gids.end(), subMapGids.begin(), subMapGids.end());
65 }
66
67 const GlobalOrdinal INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
68 // std::sort(gids.begin(), gids.end());
69 // gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
70 Teuchos::ArrayView<GlobalOrdinal> gidsView(&gids[0], gids.size());
71 Teuchos::RCP<Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullMap = Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(subMaps[0]->lib(), INVALID, gidsView, subMaps[0]->getIndexBase(), subMaps[0]->getComm());
72 return fullMap;
73 }
74
95 "Xpetra::MatrixUtils::shrinkMapGIDs: the non-overlapping map must not have more local ids than the overlapping map.")
96
99 "Xpetra::MatrixUtils::shrinkMapGIDs: the maximum GIDs of the overlapping and non-overlapping maps must be the same.")
100
101 RCP<const Teuchos::Comm<int> > comm = input.getComm();
102
103 // we expect input to be the potentially overlapping map associated with nonOvlInput as the non-overlapping
104 // map with the same GIDs over all processors (e.g. column map and domain map). We use the nonOvlInput map
105 // to determine which GIDs are owned by which processor.
106
107 // calculate offset for new global Ids
108 std::vector<int> myGIDs(comm->getSize(), 0);
109 std::vector<int> numGIDs(comm->getSize(), 0);
110 myGIDs[comm->getRank()] = nonOvlInput.getLocalNumElements();
111 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myGIDs[0], &numGIDs[0]);
112 size_t gidOffset = 0;
113 for (int p = 0; p < comm->getRank(); p++) gidOffset += numGIDs[p];
114
115 // we use nonOvlInput to assign the globally unique shrinked GIDs and communicate them to input.
116 std::map<const GlobalOrdinal, GlobalOrdinal> origGID2newGID;
117 for (size_t i = 0; i < nonOvlInput.getLocalNumElements(); i++) {
118 origGID2newGID[nonOvlInput.getGlobalElement(i)] = Teuchos::as<GlobalOrdinal>(i) + Teuchos::as<GlobalOrdinal>(gidOffset);
119 }
120 // build an overlapping version of mySpecialMap
121 Teuchos::Array<GlobalOrdinal> ovlUnknownStatusGids;
122 Teuchos::Array<GlobalOrdinal> ovlFoundStatusGids;
123 // loop over global column map of A and find all GIDs where it is not sure, whether they are special or not
124 for (size_t i = 0; i < input.getLocalNumElements(); i++) {
125 GlobalOrdinal gcid = input.getGlobalElement(i);
126 if (nonOvlInput.isNodeGlobalElement(gcid) == false) {
127 ovlUnknownStatusGids.push_back(gcid);
128 }
129 }
130
131 // Communicate the number of DOFs on each processor
132 std::vector<int> myUnknownDofGIDs(comm->getSize(), 0);
133 std::vector<int> numUnknownDofGIDs(comm->getSize(), 0);
134 myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.size();
135 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myUnknownDofGIDs[0], &numUnknownDofGIDs[0]);
136
137 // create array containing all DOF GIDs
138 size_t cntUnknownDofGIDs = 0;
139 for (int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
140 std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs, 0); // local version to be filled
141 std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs, 0); // global version after communication
142 // calculate the offset and fill chunk of memory with local data on each processor
143 size_t cntUnknownOffset = 0;
144 for (int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
145 for (size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
146 lUnknownDofGIDs[k + cntUnknownOffset] = ovlUnknownStatusGids[k];
147 }
148 if (cntUnknownDofGIDs > 0) // only perform communication if there are unknown DOF GIDs
149 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lUnknownDofGIDs[0], &gUnknownDofGIDs[0]);
150 std::vector<GlobalOrdinal> lTranslatedDofGIDs(cntUnknownDofGIDs, 0); // local version to be filled
151 std::vector<GlobalOrdinal> gTranslatedDofGIDs(cntUnknownDofGIDs, 0); // global version after communication
152 // loop through all GIDs with unknown status
153 for (size_t k = 0; k < gUnknownDofGIDs.size(); k++) {
154 GlobalOrdinal curgid = gUnknownDofGIDs[k];
155 if (nonOvlInput.isNodeGlobalElement(curgid)) {
156 lTranslatedDofGIDs[k] = origGID2newGID[curgid]; // curgid is in special map (on this processor)
157 }
158 }
159 if (cntUnknownDofGIDs > 0) // only perform communication if there are unknown DOF GIDs
160 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lTranslatedDofGIDs[0], &gTranslatedDofGIDs[0]);
161
162 for (size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
163 origGID2newGID[ovlUnknownStatusGids[k]] = gTranslatedDofGIDs[k + cntUnknownOffset];
164 }
165 Teuchos::Array<GlobalOrdinal> ovlDomainMapArray;
166 for (size_t i = 0; i < input.getLocalNumElements(); i++) {
167 GlobalOrdinal gcid = input.getGlobalElement(i);
168 ovlDomainMapArray.push_back(origGID2newGID[gcid]);
169 }
172 return ovlDomainMap;
173 }
174
194 const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>& nonOvlReferenceInput) {
195 // TEUCHOS_TEST_FOR_EXCEPTION(nonOvlInput.getLocalNumElements() > input.getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::transformThyra2XpetraGIDs: the non-overlapping map must not have more local ids than the overlapping map.");
196 TEUCHOS_TEST_FOR_EXCEPTION(nonOvlInput.getLocalNumElements() != nonOvlReferenceInput.getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::transformThyra2XpetraGIDs: the number of local Xpetra reference GIDs and local Thyra GIDs of the non-overlapping maps must be the same!");
197 // TEUCHOS_TEST_FOR_EXCEPTION(nonOvlInput.getMaxAllGlobalIndex() != input.getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::transformThyra2XpetraGIDs: the maximum GIDs of the overlapping and non-overlapping maps must be the same. nonOvlInput.getMaxAllGlobalIndex() = " << nonOvlInput.getMaxAllGlobalIndex() << " ovlInput.getMaxAllGlobalIndex() = " << input.getMaxAllGlobalIndex());
198
199 RCP<const Teuchos::Comm<int> > comm = input.getComm();
200
201 // fill translation map as far as possible
202 std::map<const GlobalOrdinal, GlobalOrdinal> thyra2xpetraGID;
203 for (size_t i = 0; i < nonOvlInput.getLocalNumElements(); i++) {
204 thyra2xpetraGID[nonOvlInput.getGlobalElement(i)] =
205 nonOvlReferenceInput.getGlobalElement(i);
206 }
207
208 // find all GIDs of the overlapping Thyra map which are not owned by this proc
209 Teuchos::Array<GlobalOrdinal> ovlUnknownStatusGids;
210 // loop over global column map of A and find all GIDs where it is not sure, whether they are special or not
211 for (size_t i = 0; i < input.getLocalNumElements(); i++) {
212 GlobalOrdinal gcid = input.getGlobalElement(i);
213 if (nonOvlInput.isNodeGlobalElement(gcid) == false) {
214 ovlUnknownStatusGids.push_back(gcid);
215 }
216 }
217
218 // Communicate the number of DOFs on each processor
219 std::vector<int> myUnknownDofGIDs(comm->getSize(), 0);
220 std::vector<int> numUnknownDofGIDs(comm->getSize(), 0);
221 myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.size();
222 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myUnknownDofGIDs[0], &numUnknownDofGIDs[0]);
223
224 // create array containing all DOF GIDs
225 size_t cntUnknownDofGIDs = 0;
226 for (int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
227 std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs, 0); // local version to be filled
228 std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs, 0); // global version after communication
229 // calculate the offset and fill chunk of memory with local data on each processor
230 size_t cntUnknownOffset = 0;
231 for (int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
232 for (size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
233 lUnknownDofGIDs[k + cntUnknownOffset] = ovlUnknownStatusGids[k];
234 }
235 if (cntUnknownDofGIDs > 0) // only perform communication if there are unknown DOF GIDs
236 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lUnknownDofGIDs[0], &gUnknownDofGIDs[0]);
237 std::vector<GlobalOrdinal> lTranslatedDofGIDs(cntUnknownDofGIDs, 0); // local version to be filled
238 std::vector<GlobalOrdinal> gTranslatedDofGIDs(cntUnknownDofGIDs, 0); // global version after communication
239 // loop through all GIDs with unknown status
240 for (size_t k = 0; k < gUnknownDofGIDs.size(); k++) {
241 GlobalOrdinal curgid = gUnknownDofGIDs[k];
242 if (nonOvlInput.isNodeGlobalElement(curgid)) {
243 lTranslatedDofGIDs[k] = thyra2xpetraGID[curgid];
244 }
245 }
246 if (cntUnknownDofGIDs > 0) // only perform communication if there are unknown DOF GIDs
247 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lTranslatedDofGIDs[0], &gTranslatedDofGIDs[0]);
248
249 for (size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
250 thyra2xpetraGID[ovlUnknownStatusGids[k]] = gTranslatedDofGIDs[k + cntUnknownOffset];
251 }
252 Teuchos::Array<GlobalOrdinal> ovlDomainMapArray;
253 for (size_t i = 0; i < input.getLocalNumElements(); i++) {
254 GlobalOrdinal gcid = input.getGlobalElement(i);
255 ovlDomainMapArray.push_back(thyra2xpetraGID[gcid]);
256 }
259
260 TEUCHOS_TEST_FOR_EXCEPTION(input.getLocalNumElements() != ovlDomainMap->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::transformThyra2XpetraGIDs: the number of local Thyra reference GIDs (overlapping) and local Xpetra GIDs (overlapping) must be the same!");
261 // TEUCHOS_TEST_FOR_EXCEPTION(nonOvlReferenceInput.getMaxAllGlobalIndex() != ovlDomainMap->getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::transformThyra2XpetraGIDs: the maximum GIDs of the overlapping and non-overlapping Xpetra maps must be the same.");
262
263 return ovlDomainMap;
264 }
265
273 const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>& input, GlobalOrdinal offset) {
275 RCP<const Teuchos::Comm<int> > comm = input.getComm();
276
277 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > rcpInput = Teuchos::rcpFromRef(input);
278
279 // check whether input map is a BlockedMap or a standard Map
280 RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node> > rcpBlockedInput = Teuchos::rcp_dynamic_cast<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node> >(rcpInput);
281 if (rcpBlockedInput.is_null() == true) {
282 // create a new map with Xpetra GIDs (may start not from GID = 0)
283 std::vector<GlobalOrdinal> gids;
284 for (LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(rcpInput->getLocalNumElements()); ++l) {
285 GlobalOrdinal gid = rcpInput->getGlobalElement(l) + offset;
286 gids.push_back(gid);
287 }
288 Teuchos::ArrayView<GO> gidsView(&gids[0], gids.size());
289 RCP<Map> fullMap = MapFactory::Build(rcpInput->lib(), INVALID, gidsView, rcpInput->getIndexBase(), comm);
290 return fullMap;
291 }
292
293 // SPECIAL CASE: input is a blocked map
294 // we have to recursively call this routine to get a BlockedMap containing (unique) Xpetra style GIDs
295
296 size_t numMaps = rcpBlockedInput->getNumMaps();
297
298 // first calucale GID offsets in submaps
299 // we need that for generating Xpetra GIDs
300 std::vector<GlobalOrdinal> gidOffsets(numMaps, 0);
301 for (size_t i = 1; i < numMaps; ++i) {
302 gidOffsets[i] = rcpBlockedInput->getMap(i - 1, true)->getMaxAllGlobalIndex() + gidOffsets[i - 1] + 1;
303 }
304
305 std::vector<RCP<const Map> > mapsXpetra(rcpBlockedInput->getNumMaps(), Teuchos::null);
306 std::vector<RCP<const Map> > mapsThyra(rcpBlockedInput->getNumMaps(), Teuchos::null);
307 for (size_t b = 0; b < rcpBlockedInput->getNumMaps(); ++b) {
308 // extract sub map with Thyra style gids
309 // this can be an underlying Map or BlockedMap object
310 RCP<const Map> subMapThyra = rcpBlockedInput->getMap(b, true);
311 RCP<const Map> subMapXpetra = MapUtils::transformThyra2XpetraGIDs(*subMapThyra, gidOffsets[b] + offset); // recursive call
312 mapsXpetra[b] = subMapXpetra; // map can be of type Map or BlockedMap
313 mapsThyra[b] = subMapThyra; // map can be of type Map or BlockedMap
314 }
315
317 return resultMap;
318 }
319};
320
321} // end namespace Xpetra
322
323#define XPETRA_MAPUTILS_SHORT
324
325#endif // PACKAGES_XPETRA_SUP_MAP_UTILS_HPP_
GlobalOrdinal GO
iterator end() const
iterator begin() const
size_type size() const
void push_back(const value_type &x)
bool is_null() const
Exception throws to report incompatible objects (like maps).
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
Xpetra utility class for common map-related routines.
static Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > transformThyra2XpetraGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, GlobalOrdinal offset)
replace set of global ids by new global ids
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > transformThyra2XpetraGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlReferenceInput)
replace set of global ids by new global ids
static Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > concatenateMaps(const std::vector< Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > > &subMaps)
Helper function to concatenate several maps.
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > shrinkMapGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput)
Helper function to shrink the GIDs and generate a standard map whith GIDs starting at 0.
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
virtual bool isNodeGlobalElement(GlobalOrdinal globalIndex) const =0
Whether the given global index is valid for this Map on this process.
virtual GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const =0
The global index corresponding to the given local index.
virtual GlobalOrdinal getMaxAllGlobalIndex() const =0
The maximum global index over all processes in the communicator.
virtual size_t getLocalNumElements() const =0
The number of elements belonging to the calling process.
virtual Teuchos::RCP< const Teuchos::Comm< int > > getComm() const =0
Get this Map's Comm object.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)