• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MOR_GreedyAtomicBasisSample.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 #include "MOR_GreedyAtomicBasisSample.hpp"
00007 
00008 #include "MOR_CollocationMetricCriterion.hpp"
00009 #include "MOR_MinMaxTools.hpp"
00010 
00011 #include "Epetra_SerialDenseMatrix.h"
00012 #include "Epetra_SerialSymDenseMatrix.h"
00013 #include "Epetra_Comm.h"
00014 
00015 #include "Thyra_EpetraThyraWrappers.hpp"
00016 
00017 #include "Teuchos_RCP.hpp"
00018 #include "Teuchos_Array.hpp"
00019 #include "Teuchos_Comm.hpp"
00020 
00021 #include "Teuchos_Assert.hpp"
00022 
00023 #include <utility>
00024 #include <algorithm>
00025 
00026 namespace MOR {
00027 
00028 namespace Detail {
00029 
00030 Teuchos::Array<Epetra_SerialDenseMatrix>
00031 createAtomicSections(MOR::AtomicBasisSource &basisSource)
00032 {
00033   const Epetra_Map atomMap = basisSource.atomMap();
00034   const int ownedAtomCount = atomMap.NumMyElements();
00035   const int vectorCount = basisSource.vectorCount();
00036 
00037   // Setup
00038   Teuchos::Array<Epetra_SerialDenseMatrix> result(ownedAtomCount);
00039   for (int iAtom = 0; iAtom < ownedAtomCount; ++iAtom) {
00040     TEUCHOS_ASSERT(atomMap.MyLID(iAtom));
00041     result[iAtom].Shape(basisSource.entryCount(iAtom), vectorCount);
00042   }
00043 
00044   // Fill
00045   for (int vectorRank = 0; vectorRank < vectorCount; ++vectorRank) {
00046     basisSource.currentVectorRankIs(vectorRank);
00047     for (int iAtom = 0; iAtom < ownedAtomCount; ++iAtom) {
00048       Teuchos::ArrayView<double> target(result[iAtom][vectorRank], basisSource.entryCount(iAtom));
00049       basisSource.atomData(iAtom, target);
00050     }
00051   }
00052 
00053   return result;
00054 }
00055 
00056 Teuchos::Array<Epetra_SerialSymDenseMatrix>
00057 createAtomicContributions(const Teuchos::ArrayView<const Epetra_SerialDenseMatrix> &atomicSections) {
00058   const int sectionCount = atomicSections.size();
00059   Teuchos::Array<Epetra_SerialSymDenseMatrix> result(sectionCount);
00060 
00061   for (int i = 0; i < sectionCount; ++i) {
00062     const Epetra_SerialDenseMatrix &section = atomicSections[i];
00063     Epetra_SerialSymDenseMatrix &contribution = result[i];
00064 
00065     const int contributionSize = section.ColDim();
00066     if (contributionSize > 0) {
00067       contribution.Shape(contributionSize);
00068       contribution.Multiply('T', 'N', 1.0, section, section, 0.0);
00069     }
00070   }
00071 
00072   return result;
00073 }
00074 
00075 Teuchos::Array<Epetra_SerialSymDenseMatrix>
00076 createAtomicContributions(MOR::AtomicBasisSource &basisSource)
00077 {
00078   return createAtomicContributions(createAtomicSections(basisSource));
00079 }
00080 
00081 Teuchos::Array<double>
00082 computePartialFitnesses(
00083     const Epetra_SerialSymDenseMatrix &reference,
00084     const Teuchos::ArrayView<const Epetra_SerialSymDenseMatrix> &atomicContributions,
00085     const CollocationMetricCriterion &criterion,
00086     int referenceContributionCount)
00087 {
00088   const int localAtomCount = atomicContributions.size();
00089   Teuchos::Array<double> result(localAtomCount);
00090 
00091   if (!result.empty()) {
00092     Epetra_SerialSymDenseMatrix candidate;
00093     const int candidateContributionCount = referenceContributionCount + 1;
00094 
00095     for (int iAtom = 0; iAtom < localAtomCount; ++iAtom) {
00096       {
00097         candidate = reference;
00098         candidate += atomicContributions[iAtom];
00099       }
00100       result[iAtom] = criterion.partialFitness(candidate, candidateContributionCount);
00101     }
00102   }
00103 
00104   return result;
00105 }
00106 
00107 Epetra_SerialSymDenseMatrix negative_eye(int size) {
00108   Epetra_SerialSymDenseMatrix result;
00109   result.Shape(size);
00110   for (int i = 0; i < size; ++i) {
00111     result[i][i] = -1.0;
00112   }
00113   return result;
00114 }
00115 
00116 template <typename Ordinal>
00117 void broadcast(const Teuchos::Comm<Ordinal> &comm, int rootRank, Epetra_SerialDenseMatrix &buffer) {
00118   const int count = buffer.LDA() * buffer.N();
00119   Teuchos::broadcast<Ordinal, double>(comm, rootRank, count, buffer.A());
00120 }
00121 
00122 int
00123 bestCandidateId(
00124     const Epetra_Map &candidateMap,
00125     const Teuchos::ArrayView<const Epetra_SerialSymDenseMatrix> &candidates,
00126     Epetra_SerialSymDenseMatrix &reference,
00127     const CollocationMetricCriterion &criterion,
00128     int referenceContributionCount)
00129 {
00130   const Teuchos::Array<double> fitnesses =
00131     computePartialFitnesses(reference, candidates, criterion, referenceContributionCount);
00132 
00133   const Teuchos::RCP<const Teuchos::Comm<Thyra::Ordinal> > comm =
00134     Thyra::create_Comm(Teuchos::rcpFromRef(candidateMap.Comm()));
00135 
00136   const Teuchos::ArrayView<int> ids(candidateMap.MyGlobalElements(), candidateMap.NumMyElements());
00137   return MOR::globalIdOfGlobalMinimum(*comm, ids, fitnesses);
00138 }
00139 
00140 void
00141 updateReferenceAndCandidates(
00142     const Epetra_Map &candidateMap,
00143     Teuchos::ArrayView<Epetra_SerialSymDenseMatrix> candidates,
00144     int selectedId,
00145     Epetra_SerialSymDenseMatrix &reference)
00146 {
00147   int selectedIdCpu;
00148   int selectedLocalId;
00149   candidateMap.RemoteIDList(1, &selectedId, &selectedIdCpu, &selectedLocalId);
00150   const bool selectedCandidateIsLocal = (selectedIdCpu == candidateMap.Comm().MyPID());
00151 
00152   if (selectedCandidateIsLocal) {
00153     Epetra_SerialSymDenseMatrix &selectedCandidate = candidates[selectedLocalId];
00154     reference += selectedCandidate;
00155     selectedCandidate.Scale(0.0); // Zero-out to prevent reselecting
00156   }
00157   const Teuchos::RCP<const Teuchos::Comm<Thyra::Ordinal> > comm =
00158     Thyra::create_Comm(Teuchos::rcpFromRef(candidateMap.Comm()));
00159   broadcast(*comm, selectedIdCpu, reference);
00160 }
00161 
00162 } // namespace Detail
00163 
00164 GreedyAtomicBasisSample::GreedyAtomicBasisSample(
00165     AtomicBasisSource &basisSource,
00166     const Teuchos::RCP<const CollocationMetricCriterion> &criterion) :
00167   criterion_(criterion),
00168   atomMap_(basisSource.atomMap()),
00169   contributions_(Detail::createAtomicContributions(basisSource)),
00170   discrepancy_(Detail::negative_eye((contributions_.size() > 0) ? contributions_.front().RowDim() : 0)),
00171   sample_()
00172 {
00173   // Nothing to do
00174 }
00175 
00176 void
00177 GreedyAtomicBasisSample::sampleSizeInc(int incr) {
00178   for (int iter = 0; iter < incr; ++iter) {
00179     const int selectedId = Detail::bestCandidateId(atomMap_, contributions_, discrepancy_, *criterion_, iter);
00180     Detail::updateReferenceAndCandidates(atomMap_, contributions_, selectedId, discrepancy_);;
00181     sample_.push_back(selectedId);
00182   }
00183 }
00184 
00185 } // namespace MOR

Generated on Wed Mar 26 2014 18:36:40 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1