10 #ifndef TPETRA_DETAILS_TRANSFER_DEF_HPP 
   11 #define TPETRA_DETAILS_TRANSFER_DEF_HPP 
   14 #include "Tpetra_Distributor.hpp" 
   15 #include "Tpetra_ImportExportData.hpp" 
   16 #include "Tpetra_Map.hpp" 
   17 #include "Teuchos_CommHelpers.hpp" 
   18 #include "Teuchos_TypeNameTraits.hpp" 
   24 template <
class ElementType, 
class DeviceType>
 
   25 Teuchos::ArrayView<const ElementType>
 
   26 makeConstArrayViewFromDualView(
const Kokkos::DualView<ElementType*, DeviceType>& dv) {
 
   27   TEUCHOS_ASSERT(!dv.need_sync_host());
 
   28   auto hostView   = dv.view_host();
 
   29   const auto size = hostView.extent(0);
 
   30   return Teuchos::ArrayView<const ElementType>(size == 0 ? 
nullptr : hostView.data(), size);
 
   33 template <
class DeviceType, 
class LocalOrdinal>
 
   34 struct OrderedViewFunctor {
 
   35   OrderedViewFunctor(
const Kokkos::View<LocalOrdinal*, DeviceType>& viewToCheck)
 
   36     : viewToCheck_(viewToCheck) {}
 
   37   KOKKOS_INLINE_FUNCTION 
void operator()(
const size_t i, 
unsigned int& isUnordered)
 const {
 
   38     isUnordered |= 
static_cast<unsigned int>(viewToCheck_(i) + 1 != viewToCheck_(i + 1));
 
   40   Kokkos::View<const LocalOrdinal*, DeviceType> viewToCheck_;
 
   43 template <
class DeviceType, 
class LocalOrdinal>
 
   44 bool isViewOrdered(
const Kokkos::View<LocalOrdinal*, DeviceType>& viewToCheck) {
 
   45   using Kokkos::parallel_reduce;
 
   46   typedef DeviceType DT;
 
   47   typedef typename DT::execution_space DES;
 
   48   typedef Kokkos::RangePolicy<DES, size_t> range_type;
 
   50   const size_t size        = viewToCheck.extent(0);
 
   51   unsigned int isUnordered = 0;
 
   53     parallel_reduce(
"isViewOrdered",
 
   54                     range_type(0, size - 1),
 
   55                     OrderedViewFunctor<DeviceType, LocalOrdinal>(viewToCheck),
 
   57   return isUnordered == 0;
 
   65 template <
class LO, 
class GO, 
class NT>
 
   66 Transfer<LO, GO, NT>::
 
   67     Transfer(
const Teuchos::RCP<const map_type>& source,
 
   68              const Teuchos::RCP<const map_type>& target,
 
   69              const Teuchos::RCP<Teuchos::FancyOStream>& out,
 
   70              const Teuchos::RCP<Teuchos::ParameterList>& plist,
 
   71              const std::string& className)
 
   72   : TransferData_(new 
ImportExportData<LO, GO, NT>(source, target, out, plist)) {
 
   74   this->setParameterList(plist, className);
 
   77 template <
class LO, 
class GO, 
class NT>
 
   82   TEUCHOS_ASSERT(!this->TransferData_->out_.is_null());
 
   85 template <
class LO, 
class GO, 
class NT>
 
   88                      const std::string& className) {
 
   89   using ::Tpetra::Details::Behavior;
 
   94   bool verboseParam = 
false;
 
   95   if (!plist.is_null()) {
 
   98     if (plist->isType<
bool>(
"Verbose")) {
 
   99       verboseParam = plist->get<
bool>(
"Verbose");
 
  100     } 
else if (plist->isType<
bool>(
"Debug")) {  
 
  101       verboseParam = plist->get<
bool>(
"Debug");
 
  104   this->TransferData_->verbose_ = verboseEnv || verboseParam;
 
  107 template <
class LO, 
class GO, 
class NT>
 
  111   return TransferData_->numSameIDs_;
 
  114 template <
class LO, 
class GO, 
class NT>
 
  118   return static_cast<size_t>(TransferData_->permuteFromLIDs_.extent(0));
 
  121 template <
class LO, 
class GO, 
class NT>
 
  122 Kokkos::DualView<const LO*, typename Transfer<LO, GO, NT>::device_type>
 
  125   const auto& dv = TransferData_->permuteFromLIDs_;
 
  126   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  127                              "Tpetra::Details::Transfer::getPermuteFromLIDs_dv: " 
  128                              "DualView needs sync to device");
 
  129   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_host(), std::logic_error,
 
  130                              "Tpetra::Details::Transfer::getPermuteFromLIDs_dv: " 
  131                              "DualView needs sync to host");
 
  135 template <
class LO, 
class GO, 
class NT>
 
  136 Teuchos::ArrayView<const LO>
 
  139   return makeConstArrayViewFromDualView(TransferData_->permuteFromLIDs_);
 
  142 template <
class LO, 
class GO, 
class NT>
 
  143 Kokkos::DualView<const LO*, typename Transfer<LO, GO, NT>::device_type>
 
  146   const auto& dv = TransferData_->permuteToLIDs_;
 
  147   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  148                              "Tpetra::Details::Transfer::getPermuteToLIDs_dv: " 
  149                              "DualView needs sync to device");
 
  150   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_host(), std::logic_error,
 
  151                              "Tpetra::Details::Transfer::getPermuteToLIDs_dv: " 
  152                              "DualView needs sync to host");
 
  156 template <
class LO, 
class GO, 
class NT>
 
  157 Teuchos::ArrayView<const LO>
 
  160   return makeConstArrayViewFromDualView(TransferData_->permuteToLIDs_);
 
  163 template <
class LO, 
class GO, 
class NT>
 
  167   return static_cast<size_t>(TransferData_->remoteLIDs_.extent(0));
 
  170 template <
class LO, 
class GO, 
class NT>
 
  171 Kokkos::DualView<const LO*, typename Transfer<LO, GO, NT>::device_type>
 
  174   const auto& dv = TransferData_->remoteLIDs_;
 
  175   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  176                              "Tpetra::Details::Transfer::getRemoteLIDs_dv: " 
  177                              "DualView needs sync to device");
 
  178   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_host(), std::logic_error,
 
  179                              "Tpetra::Details::Transfer::getRemoteLIDs_dv: " 
  180                              "DualView needs sync to host");
 
  184 template <
class LO, 
class GO, 
class NT>
 
  185 Teuchos::ArrayView<const LO>
 
  188   return makeConstArrayViewFromDualView(TransferData_->remoteLIDs_);
 
  191 template <
class LO, 
class GO, 
class NT>
 
  195   return static_cast<size_t>(TransferData_->exportLIDs_.extent(0));
 
  198 template <
class LO, 
class GO, 
class NT>
 
  199 Kokkos::DualView<const LO*, typename Transfer<LO, GO, NT>::device_type>
 
  202   const auto& dv = TransferData_->exportLIDs_;
 
  203   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  204                              "Tpetra::Details::Transfer::getExportLIDs_dv: " 
  205                              "DualView needs sync to device");
 
  206   TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_host(), std::logic_error,
 
  207                              "Tpetra::Details::Transfer::getExportLIDs_dv: " 
  208                              "DualView needs sync to host");
 
  212 template <
class LO, 
class GO, 
class NT>
 
  213 Teuchos::ArrayView<const LO>
 
  216   return makeConstArrayViewFromDualView(TransferData_->exportLIDs_);
 
  219 template <
class LO, 
class GO, 
class NT>
 
  220 Teuchos::ArrayView<const int>
 
  223   return TransferData_->exportPIDs_();
 
  226 template <
class LO, 
class GO, 
class NT>
 
  227 Teuchos::RCP<const typename Transfer<LO, GO, NT>::map_type>
 
  230   return TransferData_->source_;
 
  233 template <
class LO, 
class GO, 
class NT>
 
  234 Teuchos::RCP<const typename Transfer<LO, GO, NT>::map_type>
 
  237   return TransferData_->target_;
 
  240 template <
class LO, 
class GO, 
class NT>
 
  244   return TransferData_->distributor_;
 
  247 template <
class LO, 
class GO, 
class NT>
 
  250   return TransferData_->isLocallyComplete_;
 
  253 template <
class LO, 
class GO, 
class NT>
 
  256   return (getNumSameIDs() == std::min(getSourceMap()->getLocalNumElements(),
 
  257                                       getTargetMap()->getLocalNumElements()));
 
  260 template <
class LO, 
class GO, 
class NT>
 
  266   bool ordered = (getNumSameIDs() == std::min(getSourceMap()->getLocalNumElements(),
 
  267                                               getTargetMap()->getLocalNumElements()));
 
  268   ordered &= (getTargetMap()->getLocalNumElements() == getNumSameIDs() + getNumRemoteIDs());
 
  270     const auto& dv = TransferData_->remoteLIDs_;
 
  271     TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  272                                "Tpetra::Details::Transfer::getRemoteLIDs_dv: " 
  273                                "DualView needs sync to device");
 
  274     auto v_d = dv.view_device();
 
  275     ordered &= isViewOrdered<device_type, LO>(v_d);
 
  277   TransferData_->remoteLIDsContiguous_ = ordered;
 
  279   ordered = (getNumSameIDs() == std::min(getSourceMap()->getLocalNumElements(),
 
  280                                          getTargetMap()->getLocalNumElements()));
 
  281   ordered &= (getSourceMap()->getLocalNumElements() == getNumSameIDs() + getNumExportIDs());
 
  283     const auto& dv = TransferData_->exportLIDs_;
 
  284     TEUCHOS_TEST_FOR_EXCEPTION(dv.need_sync_device(), std::logic_error,
 
  285                                "Tpetra::Details::Transfer::getRemoteLIDs_dv: " 
  286                                "DualView needs sync to device");
 
  287     auto v_d = dv.view_device();
 
  288     ordered &= isViewOrdered<device_type, LO>(v_d);
 
  290   TransferData_->exportLIDsContiguous_ = ordered;
 
  293 template <
class LO, 
class GO, 
class NT>
 
  294 bool Transfer<LO, GO, NT>::
 
  295     areRemoteLIDsContiguous()
 const {
 
  296   return TransferData_->remoteLIDsContiguous_;
 
  299 template <
class LO, 
class GO, 
class NT>
 
  300 bool Transfer<LO, GO, NT>::
 
  301     areExportLIDsContiguous()
 const {
 
  302   return TransferData_->exportLIDsContiguous_;
 
  305 template <
class LO, 
class GO, 
class NT>
 
  308              const Teuchos::EVerbosityLevel verbLevel)
 const {
 
  309   this->describeImpl(out, 
"Tpetra::Details::Transfer", verbLevel);
 
  312 template <
class LO, 
class GO, 
class NT>
 
  313 Teuchos::FancyOStream&
 
  316   Teuchos::FancyOStream* outPtr = TransferData_->out_.getRawPtr();
 
  317   TEUCHOS_ASSERT(outPtr != 
nullptr);
 
  321 template <
class LO, 
class GO, 
class NT>
 
  324   return TransferData_->verbose_;
 
  327 template <
class LO, 
class GO, 
class NT>
 
  330                  const std::string& className,
 
  331                  const Teuchos::EVerbosityLevel verbLevel)
 const {
 
  333   using Teuchos::TypeNameTraits;
 
  334   using Teuchos::VERB_DEFAULT;
 
  335   using Teuchos::VERB_LOW;
 
  336   using Teuchos::VERB_NONE;
 
  337   const Teuchos::EVerbosityLevel vl =
 
  338       (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
 
  340   if (vl == VERB_NONE) {
 
  347   auto srcMap = this->getSourceMap();
 
  348   if (srcMap.is_null()) {
 
  351   auto comm = srcMap->getComm();
 
  352   if (comm.is_null()) {
 
  355   if (this->getTargetMap().is_null() ||
 
  356       this->getTargetMap()->getComm().is_null()) {
 
  360   const int myRank   = comm->getRank();
 
  361   const int numProcs = comm->getSize();
 
  368   Teuchos::RCP<Teuchos::OSTab> tab0, tab1;
 
  374     tab0 = Teuchos::rcp(
new Teuchos::OSTab(out));
 
  376     out << 
"\"" << className << 
"\":" << endl;
 
  377     tab1 = Teuchos::rcp(
new Teuchos::OSTab(out));
 
  380       out << 
"Template parameters:" << endl;
 
  381       Teuchos::OSTab tab2(out);
 
  382       out << 
"LocalOrdinal: " << TypeNameTraits<LO>::name() << endl
 
  383           << 
"GlobalOrdinal: " << TypeNameTraits<GO>::name() << endl
 
  384           << 
"Node: " << TypeNameTraits<NT>::name() << endl;
 
  387     const std::string label = this->getObjectLabel();
 
  389       out << 
"Label: " << label << endl;
 
  391     out << 
"Number of processes: " << numProcs << endl;
 
  398     this->globalDescribe(out, vl);
 
  410     out << 
"Source Map:" << endl;
 
  413   this->getSourceMap()->describe(out, vl);
 
  416     out << 
"Target Map:" << endl;
 
  419   this->getTargetMap()->describe(out, vl);
 
  422     out << 
"Distributor:" << endl;
 
  424   this->getDistributor().describe(out, vl);
 
  427 template <
class LO, 
class GO, 
class NT>
 
  430                    const Teuchos::EVerbosityLevel vl)
 const {
 
  433   using Teuchos::OSTab;
 
  435   using Teuchos::toString;
 
  441   auto srcMap = this->getSourceMap();
 
  442   if (srcMap.is_null()) {
 
  445   RCP<const Teuchos::Comm<int> > comm = srcMap->getComm();
 
  446   if (comm.is_null()) {
 
  450   const std::string myStr = localDescribeToString(vl);
 
  451   ::Tpetra::Details::gathervPrint(out, myStr, *comm);
 
  454 template <
class LO, 
class GO, 
class NT>
 
  456 Transfer<LO, GO, NT>::
 
  457     localDescribeToString(
const Teuchos::EVerbosityLevel vl)
 const {
 
  459   using Teuchos::OSTab;
 
  462   RCP<std::ostringstream> outString(
new std::ostringstream);
 
  463   RCP<Teuchos::FancyOStream> outp = Teuchos::getFancyOStream(outString);
 
  464   Teuchos::FancyOStream& out      = *outp;  
 
  466   RCP<const Teuchos::Comm<int> > comm = this->getSourceMap()->getComm();
 
  467   if (this->getSourceMap().is_null() ||
 
  468       this->getSourceMap()->getComm().is_null()) {
 
  473     return std::string(
"");
 
  475     const int myRank   = comm->getRank();
 
  476     const int numProcs = comm->getSize();
 
  478     out << 
"Process " << myRank << 
" of " << numProcs << 
":" << endl;
 
  481     out << 
"numSameIDs: " << getNumSameIDs() << endl;
 
  482     out << 
"numPermuteIDs: " << getNumPermuteIDs() << endl;
 
  483     out << 
"numRemoteIDs: " << getNumRemoteIDs() << endl;
 
  484     out << 
"numExportIDs: " << getNumExportIDs() << endl;
 
  488     if (vl <= Teuchos::VERB_MEDIUM) {
 
  489       out << 
"permuteFromLIDs count: " << getPermuteFromLIDs().size() << endl
 
  490           << 
"permuteToLIDs count: " << getPermuteToLIDs().size() << endl
 
  491           << 
"remoteLIDs count: " << getRemoteLIDs().size() << endl
 
  492           << 
"exportLIDs count: " << getExportLIDs().size() << endl
 
  493           << 
"exportPIDs count: " << getExportPIDs() << endl;
 
  496       RCP<const Map<LO, GO, NT> > tmap = getTargetMap();
 
  497       RCP<const Map<LO, GO, NT> > smap = getSourceMap();
 
  498       Teuchos::Array<GO> RemoteGIDs(getRemoteLIDs().size());
 
  499       Teuchos::Array<int> RemotePIDs(getRemoteLIDs().size());
 
  500       for (
size_t i = 0; i < (size_t)getRemoteLIDs().size(); i++)
 
  501         RemoteGIDs[i] = tmap->getGlobalElement(getRemoteLIDs()[i]);
 
  503       Teuchos::Array<int> ExportGIDs(getExportLIDs().size());
 
  504       for (
size_t i = 0; i < (size_t)getExportLIDs().size(); i++)
 
  505         ExportGIDs[i] = smap->getGlobalElement(getExportLIDs()[i]);
 
  510       Teuchos::ArrayView<const int> ProcsFrom      = D.
getProcsFrom();
 
  511       Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
 
  512       for (
size_t i = 0, j = 0; i < NumReceives; ++i) {
 
  513         const int pid = ProcsFrom[i];
 
  514         for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
 
  520       out << 
"distor.NumRecvs   : " << NumReceives << endl
 
  521           << 
"distor.ProcsFrom  : " << toString(ProcsFrom) << endl
 
  522           << 
"distor.LengthsFrom: " << toString(LengthsFrom) << endl;
 
  524       out << 
"distor.NumSends   : " << D.
getNumSends() << endl
 
  525           << 
"distor.ProcsTo    : " << toString(D.
getProcsTo()) << endl
 
  526           << 
"distor.LengthsTo  : " << toString(D.
getLengthsTo()) << endl;
 
  530       out << 
"permuteFromLIDs: " << toString(getPermuteFromLIDs()) << endl
 
  531           << 
"permuteToLIDs: " << toString(getPermuteToLIDs()) << endl
 
  532           << 
"remoteLIDs: " << toString(getRemoteLIDs()) << endl
 
  533           << 
"remoteGIDs: " << toString(RemoteGIDs()) << endl
 
  534           << 
"remotePIDs: " << toString(RemotePIDs()) << endl
 
  535           << 
"exportLIDs: " << toString(getExportLIDs()) << endl
 
  536           << 
"exportGIDs: " << toString(ExportGIDs()) << endl
 
  537           << 
"exportPIDs: " << toString(getExportPIDs()) << endl;
 
  541     return outString->str();
 
  545 template <
class LO, 
class GO, 
class NT>
 
  546 void expertSetRemoteLIDsContiguous(Transfer<LO, GO, NT> transfer, 
bool contig) {
 
  547   transfer.TransferData_->remoteLIDsContiguous_ = contig;
 
  550 template <
class LO, 
class GO, 
class NT>
 
  551 void expertSetExportLIDsContiguous(Transfer<LO, GO, NT> transfer, 
bool contig) {
 
  552   transfer.TransferData_->exportLIDsContiguous_ = contig;
 
  558 #endif  // TPETRA_DETAILS_TRANSFER_DEF_HPP 
Kokkos::DualView< const LO *, device_type > getRemoteLIDs_dv() const 
List of entries in the target Map to receive from other processes, as a const DualView (that is sync'...
void describeImpl(Teuchos::FancyOStream &out, const std::string &className, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const 
Implementation of describe() for subclasses (Tpetra::Import and Tpetra::Export). 
Common base class of Import and Export. 
size_t getNumReceives() const 
The number of processes from which we will receive data. 
Teuchos::FancyOStream & verboseOutputStream() const 
Valid (nonnull) output stream for verbose output. 
bool isLocallyFitted() const 
Are source and target map locally fitted? 
Declaration of a function that prints strings from each process. 
Teuchos::ArrayView< const int > getExportPIDs() const 
List of processes to which entries will be sent. 
Teuchos::ArrayView< const LO > getPermuteToLIDs() const 
List of local IDs in the target Map that are permuted. 
Teuchos::RCP< const map_type > getTargetMap() const 
The target Map used to construct this Export or Import. 
size_t getNumSameIDs() const 
Number of initial identical IDs. 
Teuchos::ArrayView< const size_t > getLengthsFrom() const 
Number of values this process will receive from each process. 
Teuchos::ArrayView< const int > getProcsFrom() const 
Ranks of the processes sending values to this process. 
size_t getNumRemoteIDs() const 
Number of entries not on the calling process. 
Kokkos::DualView< const LO *, device_type > getPermuteFromLIDs_dv() const 
List of local IDs in the source Map that are permuted, as a const DualView (that is sync'd to both ho...
Teuchos::ArrayView< const LO > getRemoteLIDs() const 
List of entries in the target Map to receive from other processes. 
Teuchos::ArrayView< const int > getProcsTo() const 
Ranks of the processes to which this process will send values. 
Kokkos::DualView< const LO *, device_type > getPermuteToLIDs_dv() const 
List of local IDs in the target Map that are permuted, as a const DualView (that is sync'd to both ho...
size_t getNumPermuteIDs() const 
Number of IDs to permute but not to communicate. 
bool hasSelfMessage() const 
Whether the calling process will send or receive messages to itself. 
Implementation detail of Import and Export. 
Sets up and executes a communication plan for a Tpetra DistObject. 
static bool verbose()
Whether Tpetra is in verbose mode. 
Teuchos::RCP< ImportExportData< LO, GO, NT > > TransferData_
All the data needed for executing the Export communication plan. 
Kokkos::DualView< const LO *, device_type > getExportLIDs_dv() const 
List of entries in the source Map that will be sent to other processes, as a const DualView (that is ...
Teuchos::RCP< const map_type > getSourceMap() const 
The source Map used to construct this Export or Import. 
size_t getNumExportIDs() const 
Number of entries that must be sent by the calling process to other processes. 
bool isLocallyComplete() const 
Is this Export or Import locally complete? 
Teuchos::ArrayView< const size_t > getLengthsTo() const 
Number of values this process will send to each process. 
Teuchos::ArrayView< const LO > getExportLIDs() const 
List of entries in the source Map that will be sent to other processes. 
Teuchos::ArrayView< const LO > getPermuteFromLIDs() const 
List of local IDs in the source Map that are permuted. 
::Tpetra::Distributor & getDistributor() const 
The Distributor that this Export or Import object uses to move data. 
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const 
Describe this object in a human-readable way to the given output stream. 
size_t getNumSends() const 
The number of processes to which we will send data. 
bool verbose() const 
Whether to print verbose debugging output.