|
Tpetra Matrix/Vector Services
Version of the Day
|
00001 /* 00002 // @HEADER 00003 // *********************************************************************** 00004 // 00005 // Tpetra: Templated Linear Algebra Services Package 00006 // Copyright (2008) Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00039 // 00040 // ************************************************************************ 00041 // @HEADER 00042 */ 00043 00061 00062 #include <Tpetra_Map.hpp> 00063 #include <Tpetra_Import.hpp> 00064 #include <Tpetra_Util.hpp> 00065 00066 namespace Tpetra { 00067 namespace Details { 00068 00075 template<class MapType> 00076 class OptColMap { 00077 public: 00078 typedef MapType map_type; 00079 typedef typename MapType::local_ordinal_type local_ordinal_type; 00080 typedef typename MapType::global_ordinal_type global_ordinal_type; 00081 typedef typename MapType::node_type node_type; 00082 typedef Import<local_ordinal_type, 00083 global_ordinal_type, 00084 node_type> import_type; 00085 00120 static std::pair<map_type, Teuchos::RCP<import_type> > 00121 make (std::ostream& errStream, 00122 bool& lclErr, 00123 const map_type& domMap, 00124 const map_type& colMap, 00125 const import_type* oldImport, 00126 const bool makeImport) 00127 { 00128 using Teuchos::Array; 00129 using Teuchos::ArrayView; 00130 using Teuchos::RCP; 00131 using Teuchos::rcp; 00132 using std::endl; 00133 typedef local_ordinal_type LO; 00134 typedef global_ordinal_type GO; 00135 const char prefix[] = "Tpetra::makeOptimizedColMapAndImport: "; 00136 std::ostream& err = errStream; 00137 00138 (void) oldImport; // We don't currently use this argument. 00139 00140 RCP<const Teuchos::Comm<int> > comm = colMap.getComm (); 00141 const LO colMapMinLid = colMap.getMinLocalIndex (); 00142 const LO colMapMaxLid = colMap.getMaxLocalIndex (); 00143 00144 // Count the numbers of GIDs in colMap that are in and not in 00145 // domMap on the calling process. Check for zero indices on the 00146 // calling process first, because if it's true, then we shouldn't 00147 // trust [getMinLocalIndex(), getMaxLocalIndex()] to return a 00148 // correct range. 00149 LO numOwnedGids = 0; 00150 LO numRemoteGids = 0; 00151 if (colMap.getNodeNumElements () != 0) { 00152 for (LO colMapLid = colMapMinLid; colMapLid <= colMapMaxLid; ++colMapLid) { 00153 const GO colMapGid = colMap.getGlobalElement (colMapLid); 00154 if (domMap.isNodeLocalElement (colMapGid)) { 00155 ++numOwnedGids; 00156 } else { 00157 ++numRemoteGids; 00158 } 00159 } 00160 } 00161 00162 // Put all colMap GIDs on the calling process in a single array. 00163 // Owned GIDs go in front, and remote GIDs at the end. 00164 Array<GO> allGids (numOwnedGids + numRemoteGids); 00165 ArrayView<GO> ownedGids = allGids.view (0, numOwnedGids); 00166 ArrayView<GO> remoteGids = allGids.view (numOwnedGids, numRemoteGids); 00167 00168 // Fill ownedGids and remoteGids (and therefore allGids). We use 00169 // two loops, one to count (above) and one to fill (here), in 00170 // order to avoid dynamic memory allocation during the loop (in 00171 // this case, lots of calls to push_back()). That will simplify 00172 // use of Kokkos to parallelize these loops later. 00173 LO ownedPos = 0; 00174 LO remotePos = 0; 00175 if (colMap.getNodeNumElements () != 0) { 00176 for (LO colMapLid = colMapMinLid; colMapLid <= colMapMaxLid; ++colMapLid) { 00177 const GO colMapGid = colMap.getGlobalElement (colMapLid); 00178 if (domMap.isNodeLocalElement (colMapGid)) { 00179 ownedGids[ownedPos++] = colMapGid; 00180 } else { 00181 remoteGids[remotePos++] = colMapGid; 00182 } 00183 } 00184 } 00185 00186 // If, for some reason, the running count doesn't match the 00187 // orignal count, fill in any remaining GID spots with an 00188 // obviously invalid value. We don't want to stop yet, because 00189 // other processes might not have noticed this error; Map 00190 // construction is a collective, so we can't stop now. 00191 if (ownedPos != numOwnedGids) { 00192 lclErr = true; 00193 err << prefix << "On Process " << comm->getRank () << ", ownedPos = " 00194 << ownedPos << " != numOwnedGids = " << numOwnedGids << endl; 00195 for (LO colMapLid = ownedPos; colMapLid < numOwnedGids; ++colMapLid) { 00196 ownedGids[colMapLid] = Teuchos::OrdinalTraits<GO>::invalid (); 00197 } 00198 } 00199 if (remotePos != numRemoteGids) { 00200 lclErr = true; 00201 err << prefix << "On Process " << comm->getRank () << ", remotePos = " 00202 << remotePos << " != numRemoteGids = " << numRemoteGids << endl; 00203 for (LO colMapLid = remotePos; colMapLid < numRemoteGids; ++colMapLid) { 00204 remoteGids[colMapLid] = Teuchos::OrdinalTraits<GO>::invalid (); 00205 } 00206 } 00207 00208 // Figure out what processes own what GIDs in the domain Map. 00209 // Initialize the output array of remote PIDs with the "invalid 00210 // process rank" -1, to help us test whether getRemoteIndexList 00211 // did its job. 00212 Array<int> remotePids (numRemoteGids, -1); 00213 Array<LO> remoteLids; 00214 if (makeImport) { 00215 remoteLids.resize (numRemoteGids); 00216 std::fill (remoteLids.begin (), remoteLids.end (), 00217 Teuchos::OrdinalTraits<LO>::invalid ()); 00218 } 00219 LookupStatus lookupStatus; 00220 if (makeImport) { 00221 lookupStatus = domMap.getRemoteIndexList (remoteGids, remotePids (), 00222 remoteLids ()); 00223 } else { 00224 lookupStatus = domMap.getRemoteIndexList (remoteGids, remotePids ()); 00225 } 00226 00227 // If any process returns IDNotPresent, then at least one of the 00228 // remote indices was not present in the domain Map. This means 00229 // that the Import object cannot be constructed, because of 00230 // incongruity between the column Map and domain Map. This means 00231 // that either the column Map or domain Map, or both, is 00232 // incorrect. 00233 const bool getRemoteIndexListFailed = (lookupStatus == IDNotPresent); 00234 if (getRemoteIndexListFailed) { 00235 lclErr = true; 00236 err << prefix << "On Process " << comm->getRank () << ", some indices " 00237 "in the input colMap (the original column Map) are not in domMap (the " 00238 "domain Map). Either these indices or the domain Map is invalid. " 00239 "Likely cause: For a nonsquare matrix, you must give the domain and " 00240 "range Maps as input to fillComplete." << endl; 00241 } 00242 00243 // Check that getRemoteIndexList actually worked, by making sure 00244 // that none of the remote PIDs are -1. 00245 for (LO k = 0; k < numRemoteGids; ++k) { 00246 bool foundInvalidPid = false; 00247 if (remotePids[k] == -1) { 00248 foundInvalidPid = true; 00249 break; 00250 } 00251 if (foundInvalidPid) { 00252 lclErr = true; 00253 err << prefix << "On Process " << comm->getRank () << ", " 00254 "getRemoteIndexList returned -1 for the process ranks of " 00255 "one or more GIDs on this process." << endl; 00256 } 00257 } 00258 00259 // Sort incoming remote column Map indices so that all columns 00260 // coming from a given remote process are contiguous. This means 00261 // the Import's Distributor doesn't need to reorder data. 00262 if (makeImport) { 00263 sort2 (remotePids.begin (), remotePids.end (), remoteGids.begin ()); 00264 } 00265 else { 00266 sort3 (remotePids.begin (), remotePids.end (), 00267 remoteGids.begin (), 00268 remoteLids.begin ()); 00269 } 00270 // Make the new column Map. 00271 MapType newColMap (colMap.getGlobalNumElements (), allGids (), 00272 colMap.getIndexBase (), comm, colMap.getNode ()); 00273 // Optionally, make the new Import object. 00274 RCP<import_type> imp; 00275 if (makeImport) { 00276 imp = rcp (new import_type (rcp (new map_type (domMap)), 00277 rcp (new map_type (newColMap)))); 00278 // FIXME (mfh 06 Jul 2014) This constructor throws a runtime 00279 // error, so I'm not using it for now. 00280 // 00281 // imp = rcp (new import_type (domMap, newColMap, remoteGids, 00282 // remotePids (), remoteLids (), 00283 // Teuchos::null, Teuchos::null)); 00284 } 00285 return std::make_pair (newColMap, imp); 00286 } 00287 }; 00288 00308 template<class MapType> 00309 MapType 00310 makeOptimizedColMap (std::ostream& errStream, 00311 bool& lclErr, 00312 const MapType& domMap, 00313 const MapType& colMap) 00314 { 00315 typedef typename MapType::local_ordinal_type LO; 00316 typedef typename MapType::global_ordinal_type GO; 00317 typedef typename MapType::node_type NT; 00318 typedef ::Tpetra::Import<LO, GO, NT> import_type; 00319 00320 const bool makeImport = false; 00321 std::pair<MapType, Teuchos::RCP<import_type> > ret = 00322 OptColMap<MapType>::make (errStream, lclErr, domMap, colMap, 00323 NULL, makeImport); 00324 return ret.first; 00325 } 00326 00381 template<class MapType> 00382 std::pair<MapType, Teuchos::RCP<typename OptColMap<MapType>::import_type> > 00383 makeOptimizedColMapAndImport (std::ostream& errStream, 00384 bool& lclErr, 00385 const MapType& domMap, 00386 const MapType& colMap, 00387 const typename OptColMap<MapType>::import_type* oldImport, 00388 const bool makeImport) 00389 { 00390 return OptColMap<MapType>::make (errStream, lclErr, domMap, colMap, 00391 oldImport, makeImport); 00392 } 00393 00394 } // namespace Details 00395 } // namespace Tpetra
1.7.6.1