46 #ifndef MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP 
   47 #define MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP 
   49 #include "Xpetra_CrsGraph.hpp" 
   50 #include "Xpetra_CrsMatrixUtils.hpp" 
   54 #include "MueLu_Aggregates.hpp" 
   61   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
   65 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name)) 
   68 #undef  SET_VALID_ENTRY 
   72                                                  "Generating factory of the matrix A");
 
   74                                                  "Aggregates generated by StructuredAggregationFactory used to construct a piece-constant prolongator.");
 
   76                                                  "Graph generated by StructuredAggregationFactory used to construct a piece-linear prolongator.");
 
   78                                                  "Fine level coordinates used to construct piece-wise linear prolongator and coarse level coordinates.");
 
   80                                                  "map of the coarse coordinates' GIDs as indexed on the fine mesh.");
 
   82                                                  "map of the coarse coordinates' GIDs as indexed on the coarse mesh.");
 
   84                                                  "Fine level nullspace used to construct the coarse level nullspace.");
 
   86                                                  "Number of spacial dimensions in the problem.");
 
   88                                                  "Number of nodes per spatial dimension on the coarse grid.");
 
   89     validParamList->
set<
bool>                   (
"keep coarse coords",           
false, 
"Flag to keep coordinates for special coarse grid solve");
 
   90     validParamList->
set<
bool>                   (
"interp: remove small entries", 
true, 
"Remove small interpolation coeficient from prolongator to reduce fill-in on coarse level");
 
   92     return validParamList;
 
   95   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  100     Input(fineLevel, 
"A");
 
  101     Input(fineLevel, 
"Nullspace");
 
  102     Input(fineLevel, 
"numDimensions");
 
  103     Input(fineLevel, 
"prolongatorGraph");
 
  104     Input(fineLevel, 
"lCoarseNodesPerDim");
 
  106     if( pL.
get<
bool>(
"interp: build coarse coordinates") ||
 
  107         (pL.
get<
int>(
"interp: interpolation order") == 1) ) {
 
  108       Input(fineLevel, 
"Coordinates");
 
  109       Input(fineLevel, 
"coarseCoordinatesFineMap");
 
  110       Input(fineLevel, 
"coarseCoordinatesMap");
 
  115   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  118     return BuildP(fineLevel, coarseLevel);
 
  121   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  128     if(
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
 
  129       out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
 
  135     *out << 
"Starting GeometricInterpolationPFactory::BuildP." << std::endl;
 
  139     const bool removeSmallEntries     = pL.
get<
bool>(
"interp: remove small entries");
 
  140     const bool buildCoarseCoordinates = pL.
get<
bool>(
"interp: build coarse coordinates");
 
  141     const int interpolationOrder      = pL.
get<
int> (
"interp: interpolation order");
 
  142     const int numDimensions           = Get<int>(fineLevel, 
"numDimensions");
 
  152     if(buildCoarseCoordinates || (interpolationOrder == 1)) {
 
  154       RCP<const Map> coarseCoordsFineMap = Get< RCP<const Map> >(fineLevel, 
"coarseCoordinatesFineMap");
 
  155       RCP<const Map> coarseCoordsMap = Get< RCP<const Map> >(fineLevel, 
"coarseCoordinatesMap");
 
  156       fineCoordinates   = Get< RCP<realvaluedmultivector_type> >(fineLevel, 
"Coordinates");
 
  157       coarseCoordinates = Xpetra::MultiVectorFactory<real_type,LO,GO,Node>::Build(coarseCoordsFineMap,
 
  158                                                                                   fineCoordinates->getNumVectors());
 
  159       RCP<const Import> coordsImporter = ImportFactory::Build(fineCoordinates->getMap(),
 
  160                                                               coarseCoordsFineMap);
 
  161       coarseCoordinates->doImport(*fineCoordinates, *coordsImporter, Xpetra::INSERT);
 
  162       coarseCoordinates->replaceMap(coarseCoordsMap);
 
  164       Set(coarseLevel, 
"Coordinates", coarseCoordinates);
 
  166       if(pL.
get<
bool>(
"keep coarse coords")) {
 
  171     *out << 
"Fine and coarse coordinates have been loaded from the fine level and set on the coarse level." << std::endl;
 
  173     if(interpolationOrder == 0) {
 
  176       BuildConstantP(P, prolongatorGraph, A);
 
  177     } 
else if(interpolationOrder == 1) {
 
  182       const size_t dofsPerNode = 
static_cast<size_t>(A->GetFixedBlockSize());
 
  183       const size_t numColIndices = prolongatorColMap->getNodeNumElements();
 
  186                                  "Something went wrong, the number of columns in the prolongator is not a multiple of dofsPerNode!");
 
  187       const size_t numGhostCoords = numColIndices / dofsPerNode;
 
  188       const GO indexBase = prolongatorColMap->getIndexBase();
 
  189       const GO coordIndexBase = fineCoordinates->getMap()->getIndexBase();
 
  192       Array<GO> ghostCoordIndices(numGhostCoords);
 
  193       for(
size_t ghostCoordIdx = 0; ghostCoordIdx < numGhostCoords; ++ghostCoordIdx) {
 
  194         ghostCoordIndices[ghostCoordIdx]
 
  195           = (prolongatorColIndices[ghostCoordIdx*dofsPerNode] - indexBase) / dofsPerNode
 
  198       RCP<Map> ghostCoordMap = MapFactory::Build(fineCoordinates->getMap()->lib(),
 
  199                                                  prolongatorColMap->getGlobalNumElements() / dofsPerNode,
 
  202                                                  fineCoordinates->getMap()->getComm());
 
  205         = Xpetra::MultiVectorFactory<real_type,LO,GO,NO>::Build(ghostCoordMap,
 
  206                                                                 fineCoordinates->getNumVectors());
 
  207       RCP<const Import> ghostImporter = ImportFactory::Build(coarseCoordinates->getMap(),
 
  209       ghostCoordinates->doImport(*coarseCoordinates, *ghostImporter, Xpetra::INSERT);
 
  211       BuildLinearP(coarseLevel, A, prolongatorGraph, fineCoordinates,
 
  212                    ghostCoordinates, numDimensions, removeSmallEntries, P);
 
  215     *out << 
"The prolongator matrix has been built." << std::endl;
 
  220       RCP<MultiVector> fineNullspace   = Get< RCP<MultiVector> > (fineLevel, 
"Nullspace");
 
  221       RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
 
  222                                                                    fineNullspace->getNumVectors());
 
  225       Set(coarseLevel, 
"Nullspace", coarseNullspace);
 
  228     *out << 
"The coarse nullspace is constructed and set on the coarse level." << std::endl;
 
  230     Set(coarseLevel, 
"P", P);
 
  232     *out << 
"GeometricInterpolationPFactory::BuildP has completed." << std::endl;
 
  236   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  242     if(
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
 
  243       out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
 
  249     *out << 
"BuildConstantP" << std::endl;
 
  251     std::vector<size_t> strideInfo(1);
 
  252     strideInfo[0]    = A->GetFixedBlockSize();
 
  254       StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
 
  256     *out << 
"Call prolongator constructor" << std::endl;
 
  260     P = 
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
 
  261     RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
 
  262     PCrs->setAllToScalar(1.0);
 
  263     PCrs->fillComplete();
 
  266     if (A->IsView(
"stridedMaps") == 
true) {
 
  267       P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
 
  269       P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
 
  274   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  280                const int numDimensions, 
const bool removeSmallEntries,
 
  285     if(
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
 
  286       out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
 
  293     const int numInterpolationPoints = 1 << numDimensions;
 
  294     const int dofsPerNode = A->GetFixedBlockSize();
 
  297     P = 
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
 
  298     RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
 
  302       *out << 
"Entering BuildLinearP" << std::endl;
 
  306       const LO numFineNodes  = fineCoordinates->getLocalLength();
 
  307       const LO numGhostNodes = ghostCoordinates->getLocalLength();
 
  310       const real_type realZero = Teuchos::as<real_type>(0.0);
 
  313       for(
int dim = 0; dim < 3; ++dim) {
 
  314         if(dim < numDimensions) {
 
  315           fineCoords[dim]  = fineCoordinates->getData(dim);
 
  316           ghostCoords[dim] = ghostCoordinates->getData(dim);
 
  318           fineCoords[dim]  = fineZero;
 
  319           ghostCoords[dim] = ghostZero;
 
  323       *out << 
"Coordinates extracted from the multivectors!" << std::endl;
 
  326         LO interpolationNodeIdx = 0, rowIdx = 0;
 
  331         for(LO nodeIdx = 0; nodeIdx < numFineNodes; ++nodeIdx) {
 
  332           if(PCrs->getNumEntriesInLocalRow(nodeIdx*dofsPerNode) == 1) {
 
  335             for(LO dof = 0; dof < dofsPerNode; ++dof) {
 
  336               rowIdx = nodeIdx*dofsPerNode + dof;
 
  337               prolongatorGraph->getLocalRowView(rowIdx, colIndices);
 
  338               PCrs->replaceLocalValues(rowIdx, colIndices, values());
 
  344             for(
int dim = 0; dim < 3; ++dim) {
 
  345               coords[0][dim] = fineCoords[dim][nodeIdx];
 
  347             prolongatorGraph->getLocalRowView(nodeIdx*dofsPerNode, colIndices);
 
  348             for(
int interpolationIdx=0; interpolationIdx < numInterpolationPoints; ++interpolationIdx) {
 
  349               coords[interpolationIdx + 1].
resize(3);
 
  350               interpolationNodeIdx = colIndices[interpolationIdx] / dofsPerNode;
 
  351               for(
int dim = 0; dim < 3; ++dim) {
 
  352                 coords[interpolationIdx + 1][dim] = ghostCoords[dim][interpolationNodeIdx];
 
  356             ComputeLinearInterpolationStencil(numDimensions, numInterpolationPoints, coords, stencil);
 
  358             values.
resize(numInterpolationPoints);
 
  359             for(LO valueIdx = 0; valueIdx < numInterpolationPoints; ++valueIdx) {
 
  360               values[valueIdx] = Teuchos::as<SC>(stencil[valueIdx]);
 
  364             for(LO dof = 0; dof < dofsPerNode; ++dof) {
 
  365               rowIdx = nodeIdx*dofsPerNode + dof;
 
  366               prolongatorGraph->getLocalRowView(rowIdx, colIndices);
 
  367               PCrs->replaceLocalValues(rowIdx, colIndices, values());
 
  373       *out << 
"The calculation of the interpolation stencils has completed." << std::endl;
 
  375       PCrs->fillComplete();
 
  378     *out << 
"All values in P have been set and fillComplete has been performed." << std::endl;
 
  386     if(removeSmallEntries) {
 
  387       *out << 
"Entering remove small entries" << std::endl;
 
  393       PCrs->getAllValues(rowptrOrig, colindOrig, valuesOrig);
 
  395       const size_t numRows = 
static_cast<size_t>(rowptrOrig.
size() - 1);
 
  399       size_t countRemovedEntries = 0;
 
  400       for(
size_t rowIdx = 0; rowIdx < numRows; ++rowIdx) {
 
  401         for(
size_t entryIdx = rowptrOrig[rowIdx]; entryIdx < rowptrOrig[rowIdx + 1]; ++entryIdx) {
 
  404         rowPtr[rowIdx + 1] = rowptrOrig[rowIdx + 1] - countRemovedEntries;
 
  405         nnzOnRows[rowIdx] = rowPtr[rowIdx + 1] - rowPtr[rowIdx];
 
  407       GetOStream(
Statistics1) << 
"interp: number of small entries removed= " << countRemovedEntries << 
" / " << rowptrOrig[numRows] << std::endl;
 
  409       size_t countKeptEntries = 0;
 
  412       for(
size_t entryIdx = 0; entryIdx < rowptrOrig[numRows]; ++entryIdx) {
 
  414           colInd[countKeptEntries] = colindOrig[entryIdx];
 
  415           values[countKeptEntries] = valuesOrig[entryIdx];
 
  420       P = 
rcp(
new CrsMatrixWrap(prolongatorGraph->getRowMap(),
 
  421                                 prolongatorGraph->getColMap(),
 
  423       RCP<CrsMatrix> PCrsSqueezed = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
 
  424       PCrsSqueezed->resumeFill(); 
 
  425       PCrsSqueezed->setAllValues(rowPtr, colInd, values);
 
  426       PCrsSqueezed->expertStaticFillComplete(prolongatorGraph->getDomainMap(),
 
  427                                              prolongatorGraph->getRangeMap());
 
  430     std::vector<size_t> strideInfo(1);
 
  431     strideInfo[0] = dofsPerNode;
 
  433       StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
 
  435     *out << 
"The strided maps of P have been computed" << std::endl;
 
  438     if (A->IsView(
"stridedMaps") == 
true) {
 
  439       P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
 
  441       P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
 
  447   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  473     int iter = 0, max_iter = 5;
 
  474     real_type functions[4][8], norm_ref = 1.0, norm2 = 1.0, tol = 1.0e-5;
 
  475     paramCoords.
size(numDimensions);
 
  477     while( (iter < max_iter) && (norm2 > tol*norm_ref) ) {
 
  480       solutionDirection.
size(numDimensions);
 
  481       residual.
size(numDimensions);
 
  485       GetInterpolationFunctions(numDimensions, paramCoords, functions);
 
  486       for(LO i = 0; i < numDimensions; ++i) {
 
  487         residual(i) = coord[0][i];                 
 
  488         for(LO k = 0; k < numInterpolationPoints; ++k) {
 
  489           residual(i) -= functions[0][k]*coord[k+1][i]; 
 
  492           norm_ref += residual(i)*residual(i);
 
  493           if(i == numDimensions - 1) {
 
  494             norm_ref = std::sqrt(norm_ref);
 
  498         for(LO j = 0; j < numDimensions; ++j) {
 
  499           for(LO k = 0; k < numInterpolationPoints; ++k) {
 
  500             Jacobian(i,j) += functions[j+1][k]*coord[k+1][i];
 
  511       for(LO i = 0; i < numDimensions; ++i) {
 
  512         paramCoords(i) = paramCoords(i) + solutionDirection(i);
 
  516       GetInterpolationFunctions(numDimensions, paramCoords, functions);
 
  517       for(LO i = 0; i < numDimensions; ++i) {
 
  519         for(LO k = 0; k < numInterpolationPoints; ++k) {
 
  520           tmp -= functions[0][k]*coord[k+1][i];
 
  525       norm2 = std::sqrt(norm2);
 
  529     for(LO i = 0; i < numInterpolationPoints; ++i) {
 
  530       stencil[i] = functions[0][i];
 
  535   template <
class Scalar, 
class LocalOrdinal, 
class GlobalOrdinal, 
class Node>
 
  540     real_type xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
 
  541     if(numDimensions == 1) {
 
  542       xi = parametricCoordinates[0];
 
  544     } 
else if(numDimensions == 2) {
 
  545       xi  = parametricCoordinates[0];
 
  546       eta = parametricCoordinates[1];
 
  548     } 
else if(numDimensions == 3) {
 
  549       xi   = parametricCoordinates[0];
 
  550       eta  = parametricCoordinates[1];
 
  551       zeta = parametricCoordinates[2];
 
  555     functions[0][0] = (1.0 - xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
 
  556     functions[0][1] = (1.0 + xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
 
  557     functions[0][2] = (1.0 - xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
 
  558     functions[0][3] = (1.0 + xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
 
  559     functions[0][4] = (1.0 - xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
 
  560     functions[0][5] = (1.0 + xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
 
  561     functions[0][6] = (1.0 - xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
 
  562     functions[0][7] = (1.0 + xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
 
  564     functions[1][0] = -(1.0 - eta)*(1.0 - zeta) / denominator;
 
  565     functions[1][1] =  (1.0 - eta)*(1.0 - zeta) / denominator;
 
  566     functions[1][2] = -(1.0 + eta)*(1.0 - zeta) / denominator;
 
  567     functions[1][3] =  (1.0 + eta)*(1.0 - zeta) / denominator;
 
  568     functions[1][4] = -(1.0 - eta)*(1.0 + zeta) / denominator;
 
  569     functions[1][5] =  (1.0 - eta)*(1.0 + zeta) / denominator;
 
  570     functions[1][6] = -(1.0 + eta)*(1.0 + zeta) / denominator;
 
  571     functions[1][7] =  (1.0 + eta)*(1.0 + zeta) / denominator;
 
  573     functions[2][0] = -(1.0 - xi)*(1.0 - zeta) / denominator;
 
  574     functions[2][1] = -(1.0 + xi)*(1.0 - zeta) / denominator;
 
  575     functions[2][2] =  (1.0 - xi)*(1.0 - zeta) / denominator;
 
  576     functions[2][3] =  (1.0 + xi)*(1.0 - zeta) / denominator;
 
  577     functions[2][4] = -(1.0 - xi)*(1.0 + zeta) / denominator;
 
  578     functions[2][5] = -(1.0 + xi)*(1.0 + zeta) / denominator;
 
  579     functions[2][6] =  (1.0 - xi)*(1.0 + zeta) / denominator;
 
  580     functions[2][7] =  (1.0 + xi)*(1.0 + zeta) / denominator;
 
  582     functions[3][0] = -(1.0 - xi)*(1.0 - eta) / denominator;
 
  583     functions[3][1] = -(1.0 + xi)*(1.0 - eta) / denominator;
 
  584     functions[3][2] = -(1.0 - xi)*(1.0 + eta) / denominator;
 
  585     functions[3][3] = -(1.0 + xi)*(1.0 + eta) / denominator;
 
  586     functions[3][4] =  (1.0 - xi)*(1.0 - eta) / denominator;
 
  587     functions[3][5] =  (1.0 + xi)*(1.0 - eta) / denominator;
 
  588     functions[3][6] =  (1.0 - xi)*(1.0 + eta) / denominator;
 
  589     functions[3][7] =  (1.0 + xi)*(1.0 + eta) / denominator;
 
  595 #endif // MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP 
basic_FancyOStream & setShowProcRank(const bool showProcRank)
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers. 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void BuildLinearP(Level &coarseLevel, RCP< Matrix > &A, RCP< const CrsGraph > &prolongatorGraph, RCP< realvaluedmultivector_type > &fineCoordinates, RCP< realvaluedmultivector_type > &ghostCoordinates, const int numDimensions, const bool keepD2, RCP< Matrix > &P) const 
static const NoFactory * get()
void GetInterpolationFunctions(const LO numDimensions, const Teuchos::SerialDenseVector< LO, real_type > parametricCoordinates, real_type functions[4][8]) const 
static RCP< Time > getNewTimer(const std::string &name)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void Build(Level &fineLevel, Level &coarseLevel) const 
Build an object with this factory. 
Class that holds all level-specific information. 
void ComputeLinearInterpolationStencil(const int numDimensions, const int numInterpolationPoints, const Array< Array< real_type > > coord, Array< real_type > &stencil) const 
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level. 
void factorWithEquilibration(bool flag)
#define SET_VALID_ENTRY(name)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
void resize(size_type new_size, const value_type &x=value_type())
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void DeclareInput(Level &fineLevel, Level &coarseLevel) const 
Input. 
int size(OrdinalType length_in)
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
RCP< const ParameterList > GetValidParameterList() const 
Return a const parameter list of valid parameters that setParameterList() will accept. 
Exception throws to report errors in the internal logical of the program. 
void BuildConstantP(RCP< Matrix > &P, RCP< const CrsGraph > &prolongatorGraph, RCP< Matrix > &A) const 
typename Teuchos::ScalarTraits< SC >::coordinateType real_type
void BuildP(Level &fineLevel, Level &coarseLevel) const 
Abstract Build method. 
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)