MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_GeometricInterpolationPFactory_kokkos_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
47 #define MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
48 
49 #include "Xpetra_CrsGraph.hpp"
51 
52 #include "MueLu_MasterList.hpp"
53 #include "MueLu_Monitor.hpp"
54 #include "MueLu_IndexManager_kokkos.hpp"
55 
56 #include "Xpetra_TpetraCrsMatrix.hpp"
57 
58 // Including this one last ensure that the short names of the above headers are defined properly
60 
61 namespace MueLu {
62 
63 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65  RCP<ParameterList> validParamList = rcp(new ParameterList());
66 
67 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
68  SET_VALID_ENTRY("interp: build coarse coordinates");
69 #undef SET_VALID_ENTRY
70 
71  // general variables needed in GeometricInterpolationPFactory_kokkos
72  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null,
73  "Generating factory of the matrix A");
74  validParamList->set<RCP<const FactoryBase> >("prolongatorGraph", Teuchos::null,
75  "Graph generated by StructuredAggregationFactory used to construct a piece-linear prolongator.");
76  validParamList->set<RCP<const FactoryBase> >("Coordinates", Teuchos::null,
77  "Fine level coordinates used to construct piece-wise linear prolongator and coarse level coordinates.");
78  validParamList->set<RCP<const FactoryBase> >("Nullspace", Teuchos::null,
79  "Fine level nullspace used to construct the coarse level nullspace.");
80  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
81  "Number of spacial dimensions in the problem.");
82  validParamList->set<RCP<const FactoryBase> >("lCoarseNodesPerDim", Teuchos::null,
83  "Number of nodes per spatial dimension on the coarse grid.");
84  validParamList->set<RCP<const FactoryBase> >("indexManager", Teuchos::null,
85  "The index manager associated with the local mesh.");
86  validParamList->set<RCP<const FactoryBase> >("structuredInterpolationOrder", Teuchos::null,
87  "Interpolation order for constructing the prolongator.");
88 
89  return validParamList;
90 }
91 
92 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
94  DeclareInput(Level& fineLevel, Level& coarseLevel) const {
95  const ParameterList& pL = GetParameterList();
96 
97  Input(fineLevel, "A");
98  Input(fineLevel, "Nullspace");
99  Input(fineLevel, "numDimensions");
100  Input(fineLevel, "prolongatorGraph");
101  Input(fineLevel, "lCoarseNodesPerDim");
102  Input(fineLevel, "structuredInterpolationOrder");
103 
104  if (pL.get<bool>("interp: build coarse coordinates") ||
105  Get<int>(fineLevel, "structuredInterpolationOrder") == 1) {
106  Input(fineLevel, "Coordinates");
107  Input(fineLevel, "indexManager");
108  }
109 }
110 
111 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
113  Build(Level& fineLevel, Level& coarseLevel) const {
114  return BuildP(fineLevel, coarseLevel);
115 }
116 
117 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
119  BuildP(Level& fineLevel, Level& coarseLevel) const {
120  FactoryMonitor m(*this, "BuildP", coarseLevel);
121 
122  // Set debug outputs based on environment variable
124  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
125  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
126  out->setShowAllFrontMatter(false).setShowProcRank(true);
127  } else {
128  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
129  }
130 
131  *out << "Starting GeometricInterpolationPFactory_kokkos::BuildP." << std::endl;
132 
133  // Get inputs from the parameter list
134  const ParameterList& pL = GetParameterList();
135  const bool buildCoarseCoordinates = pL.get<bool>("interp: build coarse coordinates");
136  const int interpolationOrder = Get<int>(fineLevel, "structuredInterpolationOrder");
137  const int numDimensions = Get<int>(fineLevel, "numDimensions");
138 
139  // Declared main input/outputs to be retrieved and placed on the fine resp. coarse level
140  RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
141  RCP<const CrsGraph> prolongatorGraph = Get<RCP<CrsGraph> >(fineLevel, "prolongatorGraph");
142  RCP<realvaluedmultivector_type> fineCoordinates, coarseCoordinates;
143  RCP<Matrix> P;
144 
145  // Check if we need to build coarse coordinates as they are used if we construct
146  // a linear interpolation prolongator
147  if (buildCoarseCoordinates || (interpolationOrder == 1)) {
148  SubFactoryMonitor sfm(*this, "BuildCoordinates", coarseLevel);
149 
150  // Extract data from fine level
151  RCP<IndexManager_kokkos> geoData = Get<RCP<IndexManager_kokkos> >(fineLevel, "indexManager");
152  fineCoordinates = Get<RCP<realvaluedmultivector_type> >(fineLevel, "Coordinates");
153 
154  // Build coarse coordinates map/multivector
155  RCP<const Map> coarseCoordsMap = MapFactory::Build(fineCoordinates->getMap()->lib(),
157  geoData->getNumCoarseNodes(),
158  fineCoordinates->getMap()->getIndexBase(),
159  fineCoordinates->getMap()->getComm());
161  Build(coarseCoordsMap, fineCoordinates->getNumVectors());
162 
163  // Construct and launch functor to fill coarse coordinates values
164  // function should take a const view really
165  coarseCoordinatesBuilderFunctor myCoarseCoordinatesBuilder(geoData,
166  fineCoordinates->getDeviceLocalView(Xpetra::Access::ReadWrite),
167  coarseCoordinates->getDeviceLocalView(Xpetra::Access::OverwriteAll));
168  Kokkos::parallel_for("GeometricInterpolation: build coarse coordinates",
169  Kokkos::RangePolicy<execution_space>(0, geoData->getNumCoarseNodes()),
170  myCoarseCoordinatesBuilder);
171 
172  Set(coarseLevel, "Coordinates", coarseCoordinates);
173  }
174 
175  *out << "Fine and coarse coordinates have been loaded from the fine level and set on the coarse level." << std::endl;
176 
177  if (interpolationOrder == 0) {
178  SubFactoryMonitor sfm(*this, "BuildConstantP", coarseLevel);
179  // Compute the prolongator using piece-wise constant interpolation
180  BuildConstantP(P, prolongatorGraph, A);
181  } else if (interpolationOrder == 1) {
182  // Compute the prolongator using piece-wise linear interpolation
183  // First get all the required coordinates to compute the local part of P
184  RCP<realvaluedmultivector_type> ghostCoordinates = Xpetra::MultiVectorFactory<real_type, LO, GO, NO>::Build(prolongatorGraph->getColMap(),
185  fineCoordinates->getNumVectors());
186  RCP<const Import> ghostImporter = ImportFactory::Build(coarseCoordinates->getMap(),
187  prolongatorGraph->getColMap());
188  ghostCoordinates->doImport(*coarseCoordinates, *ghostImporter, Xpetra::INSERT);
189 
190  SubFactoryMonitor sfm(*this, "BuildLinearP", coarseLevel);
191  BuildLinearP(A, prolongatorGraph, fineCoordinates, ghostCoordinates, numDimensions, P);
192  }
193 
194  *out << "The prolongator matrix has been built." << std::endl;
195 
196  {
197  SubFactoryMonitor sfm(*this, "BuildNullspace", coarseLevel);
198  // Build the coarse nullspace
199  RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel, "Nullspace");
200  RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
201  fineNullspace->getNumVectors());
202  P->apply(*fineNullspace, *coarseNullspace, Teuchos::TRANS, Teuchos::ScalarTraits<SC>::one(),
204  Set(coarseLevel, "Nullspace", coarseNullspace);
205  }
206 
207  *out << "The coarse nullspace is constructed and set on the coarse level." << std::endl;
208 
209  Array<LO> lNodesPerDir = Get<Array<LO> >(fineLevel, "lCoarseNodesPerDim");
210  Set(coarseLevel, "numDimensions", numDimensions);
211  Set(coarseLevel, "lNodesPerDim", lNodesPerDir);
212  Set(coarseLevel, "P", P);
213 
214  *out << "GeometricInterpolationPFactory_kokkos::BuildP has completed." << std::endl;
215 
216 } // BuildP
217 
218 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
220  BuildConstantP(RCP<Matrix>& P, RCP<const CrsGraph>& prolongatorGraph, RCP<Matrix>& A) const {
221  // Set debug outputs based on environment variable
223  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
224  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
225  out->setShowAllFrontMatter(false).setShowProcRank(true);
226  } else {
227  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
228  }
229 
230  *out << "BuildConstantP" << std::endl;
231 
232  std::vector<size_t> strideInfo(1);
233  strideInfo[0] = A->GetFixedBlockSize();
234  RCP<const StridedMap> stridedDomainMap =
235  StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
236 
237  *out << "Call prolongator constructor" << std::endl;
239  if (helpers::isTpetraBlockCrs(A)) {
240  LO NSDim = A->GetStorageBlockSize();
241 
242  // Build the exploded Map
243  // FIXME: Should look at doing this on device
244  RCP<const Map> BlockMap = prolongatorGraph->getDomainMap();
245  Teuchos::ArrayView<const GO> block_dofs = BlockMap->getLocalElementList();
246  Teuchos::Array<GO> point_dofs(block_dofs.size() * NSDim);
247  for (LO i = 0, ct = 0; i < block_dofs.size(); i++) {
248  for (LO j = 0; j < NSDim; j++) {
249  point_dofs[ct] = block_dofs[i] * NSDim + j;
250  ct++;
251  }
252  }
253 
254  RCP<const Map> PointMap = MapFactory::Build(BlockMap->lib(),
255  BlockMap->getGlobalNumElements() * NSDim,
256  point_dofs(),
257  BlockMap->getIndexBase(),
258  BlockMap->getComm());
259  strideInfo[0] = A->GetFixedBlockSize();
260  RCP<const StridedMap> stridedPointMap = StridedMapFactory::Build(PointMap, strideInfo);
261 
262  RCP<Xpetra::CrsMatrix<SC, LO, GO, NO> > P_xpetra = Xpetra::CrsMatrixFactory<SC, LO, GO, NO>::BuildBlock(prolongatorGraph, PointMap, A->getRangeMap(), NSDim);
264  if (P_tpetra.is_null()) throw std::runtime_error("BuildConstantP: Matrix factory did not return a Tpetra::BlockCrsMatrix");
265  RCP<CrsMatrixWrap> P_wrap = rcp(new CrsMatrixWrap(P_xpetra));
266 
267  const LO stride = strideInfo[0] * strideInfo[0];
268  const LO in_stride = strideInfo[0];
269  typename CrsMatrix::local_graph_type localGraph = prolongatorGraph->getLocalGraphDevice();
270  auto rowptr = localGraph.row_map;
271  auto indices = localGraph.entries;
272  auto values = P_tpetra->getTpetra_BlockCrsMatrix()->getValuesDeviceNonConst();
273 
276 
277  const Kokkos::TeamPolicy<execution_space> policy(prolongatorGraph->getLocalNumRows(), 1);
278 
279  Kokkos::parallel_for(
280  "MueLu:GeoInterpFact::BuildConstantP::fill", policy,
281  KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<execution_space>::member_type& thread) {
282  auto row = thread.league_rank();
283  for (LO j = (LO)rowptr[row]; j < (LO)rowptr[row + 1]; j++) {
284  LO block_offset = j * stride;
285  for (LO k = 0; k < in_stride; k++)
286  values[block_offset + k * (in_stride + 1)] = one;
287  }
288  });
289 
290  P = P_wrap;
291  if (A->IsView("stridedMaps") == true) {
292  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedPointMap);
293  } else {
294  P->CreateView("stridedMaps", P->getRangeMap(), PointMap);
295  }
296  } else {
297  // Create the prolongator matrix and its associated objects
298  RCP<ParameterList> dummyList = rcp(new ParameterList());
299  P = rcp(new CrsMatrixWrap(prolongatorGraph, dummyList));
300  RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
301  PCrs->setAllToScalar(1.0);
302  PCrs->fillComplete();
303 
304  // set StridingInformation of P
305  if (A->IsView("stridedMaps") == true) {
306  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedDomainMap);
307  } else {
308  P->CreateView("stridedMaps", P->getRangeMap(), stridedDomainMap);
309  }
310  }
311 
312 } // BuildConstantP
313 
314 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
317  RCP<realvaluedmultivector_type>& fineCoordinates,
318  RCP<realvaluedmultivector_type>& ghostCoordinates,
319  const int numDimensions, RCP<Matrix>& P) const {
320  // Set debug outputs based on environment variable
322  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
323  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
324  out->setShowAllFrontMatter(false).setShowProcRank(true);
325  } else {
326  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
327  }
328 
329  *out << "Entering BuildLinearP" << std::endl;
330 
331  // Extract coordinates for interpolation stencil calculations
332  const LO numFineNodes = fineCoordinates->getLocalLength();
333  const LO numGhostNodes = ghostCoordinates->getLocalLength();
334  Array<ArrayRCP<const real_type> > fineCoords(3);
335  Array<ArrayRCP<const real_type> > ghostCoords(3);
336  const real_type realZero = Teuchos::as<real_type>(0.0);
337  ArrayRCP<real_type> fineZero(numFineNodes, realZero);
338  ArrayRCP<real_type> ghostZero(numGhostNodes, realZero);
339  for (int dim = 0; dim < 3; ++dim) {
340  if (dim < numDimensions) {
341  fineCoords[dim] = fineCoordinates->getData(dim);
342  ghostCoords[dim] = ghostCoordinates->getData(dim);
343  } else {
344  fineCoords[dim] = fineZero;
345  ghostCoords[dim] = ghostZero;
346  }
347  }
348 
349  *out << "Coordinates extracted from the multivectors!" << std::endl;
350 
351  // Compute 2^numDimensions using bit logic to avoid round-off errors
352  const int numInterpolationPoints = 1 << numDimensions;
353  const int dofsPerNode = A->GetFixedBlockSize();
354 
355  std::vector<size_t> strideInfo(1);
356  strideInfo[0] = dofsPerNode;
357  RCP<const StridedMap> stridedDomainMap =
358  StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
359 
360  *out << "The maps of P have been computed" << std::endl;
361 
362  RCP<ParameterList> dummyList = rcp(new ParameterList());
363  P = rcp(new CrsMatrixWrap(prolongatorGraph, dummyList));
364  RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
365  PCrs->resumeFill(); // The Epetra matrix is considered filled at this point.
366 
367  LO interpolationNodeIdx = 0, rowIdx = 0;
368  ArrayView<const LO> colIndices;
369  Array<SC> values;
370  Array<Array<real_type> > coords(numInterpolationPoints + 1);
371  Array<real_type> stencil(numInterpolationPoints);
372  for (LO nodeIdx = 0; nodeIdx < numFineNodes; ++nodeIdx) {
373  if (PCrs->getNumEntriesInLocalRow(nodeIdx * dofsPerNode) == 1) {
374  values.resize(1);
375  values[0] = 1.0;
376  for (LO dof = 0; dof < dofsPerNode; ++dof) {
377  rowIdx = nodeIdx * dofsPerNode + dof;
378  prolongatorGraph->getLocalRowView(rowIdx, colIndices);
379  PCrs->replaceLocalValues(rowIdx, colIndices, values());
380  }
381  } else {
382  // Extract the coordinates associated with the current node
383  // and the neighboring coarse nodes
384  coords[0].resize(3);
385  for (int dim = 0; dim < 3; ++dim) {
386  coords[0][dim] = fineCoords[dim][nodeIdx];
387  }
388  prolongatorGraph->getLocalRowView(nodeIdx * dofsPerNode, colIndices);
389  for (int interpolationIdx = 0; interpolationIdx < numInterpolationPoints; ++interpolationIdx) {
390  coords[interpolationIdx + 1].resize(3);
391  interpolationNodeIdx = colIndices[interpolationIdx] / dofsPerNode;
392  for (int dim = 0; dim < 3; ++dim) {
393  coords[interpolationIdx + 1][dim] = ghostCoords[dim][interpolationNodeIdx];
394  }
395  }
396  ComputeLinearInterpolationStencil(numDimensions, numInterpolationPoints, coords, stencil);
397  values.resize(numInterpolationPoints);
398  for (LO valueIdx = 0; valueIdx < numInterpolationPoints; ++valueIdx) {
399  values[valueIdx] = Teuchos::as<SC>(stencil[valueIdx]);
400  }
401 
402  // Set values in all the rows corresponding to nodeIdx
403  for (LO dof = 0; dof < dofsPerNode; ++dof) {
404  rowIdx = nodeIdx * dofsPerNode + dof;
405  prolongatorGraph->getLocalRowView(rowIdx, colIndices);
406  PCrs->replaceLocalValues(rowIdx, colIndices, values());
407  }
408  }
409  }
410 
411  *out << "The calculation of the interpolation stencils has completed." << std::endl;
412 
413  PCrs->fillComplete();
414 
415  *out << "All values in P have been set and expertStaticFillComplete has been performed." << std::endl;
416 
417  // set StridingInformation of P
418  if (A->IsView("stridedMaps") == true) {
419  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedDomainMap);
420  } else {
421  P->CreateView("stridedMaps", P->getRangeMap(), stridedDomainMap);
422  }
423 
424 } // BuildLinearP
425 
426 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
428  ComputeLinearInterpolationStencil(const int numDimensions, const int numInterpolationPoints,
429  const Array<Array<real_type> > coord,
430  Array<real_type>& stencil) const {
431  // 7 8 Find xi, eta and zeta such that
432  // x---------x
433  // /| /| Rx = x_p - sum N_i(xi,eta,zeta)x_i = 0
434  // 5/ | 6/ | Ry = y_p - sum N_i(xi,eta,zeta)y_i = 0
435  // x---------x | Rz = z_p - sum N_i(xi,eta,zeta)z_i = 0
436  // | | *P | |
437  // | x------|--x We can do this with a Newton solver:
438  // | /3 | /4 We will start with initial guess (xi,eta,zeta) = (0,0,0)
439  // |/ |/ We compute the Jacobian and iterate until convergence...
440  // z y x---------x
441  // | / 1 2 Once we have (xi,eta,zeta), we can evaluate all N_i which
442  // |/ give us the weights for the interpolation stencil!
443  // o---x
444  //
445 
446  Teuchos::SerialDenseMatrix<LO, real_type> Jacobian(numDimensions, numDimensions);
448  Teuchos::SerialDenseVector<LO, real_type> solutionDirection(numDimensions);
449  Teuchos::SerialDenseVector<LO, real_type> paramCoords(numDimensions);
451  int iter = 0, max_iter = 5;
452  real_type functions[4][8], norm_ref = 1.0, norm2 = 1.0, tol = 1.0e-5;
453  paramCoords.size(numDimensions);
454 
455  while ((iter < max_iter) && (norm2 > tol * norm_ref)) {
456  ++iter;
457  norm2 = 0.0;
458  solutionDirection.size(numDimensions);
459  residual.size(numDimensions);
460  Jacobian = 0.0;
461 
462  // Compute Jacobian and Residual
463  GetInterpolationFunctions(numDimensions, paramCoords, functions);
464  for (LO i = 0; i < numDimensions; ++i) {
465  residual(i) = coord[0][i]; // Add coordinates from point of interest
466  for (LO k = 0; k < numInterpolationPoints; ++k) {
467  residual(i) -= functions[0][k] * coord[k + 1][i]; // Remove contribution from all coarse points
468  }
469  if (iter == 1) {
470  norm_ref += residual(i) * residual(i);
471  if (i == numDimensions - 1) {
472  norm_ref = std::sqrt(norm_ref);
473  }
474  }
475 
476  for (LO j = 0; j < numDimensions; ++j) {
477  for (LO k = 0; k < numInterpolationPoints; ++k) {
478  Jacobian(i, j) += functions[j + 1][k] * coord[k + 1][i];
479  }
480  }
481  }
482 
483  // Set Jacobian, Vectors and solve problem
484  problem.setMatrix(Teuchos::rcp(&Jacobian, false));
485  problem.setVectors(Teuchos::rcp(&solutionDirection, false), Teuchos::rcp(&residual, false));
486  if (problem.shouldEquilibrate()) {
487  problem.factorWithEquilibration(true);
488  }
489  problem.solve();
490 
491  for (LO i = 0; i < numDimensions; ++i) {
492  paramCoords(i) = paramCoords(i) + solutionDirection(i);
493  }
494 
495  // Recompute Residual norm
496  GetInterpolationFunctions(numDimensions, paramCoords, functions);
497  for (LO i = 0; i < numDimensions; ++i) {
498  real_type tmp = coord[0][i];
499  for (LO k = 0; k < numInterpolationPoints; ++k) {
500  tmp -= functions[0][k] * coord[k + 1][i];
501  }
502  norm2 += tmp * tmp;
503  tmp = 0.0;
504  }
505  norm2 = std::sqrt(norm2);
506  }
507 
508  // Load the interpolation values onto the stencil.
509  for (LO i = 0; i < numInterpolationPoints; ++i) {
510  stencil[i] = functions[0][i];
511  }
512 
513 } // End ComputeLinearInterpolationStencil
514 
515 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
517  GetInterpolationFunctions(const LO numDimensions,
518  const Teuchos::SerialDenseVector<LO, real_type> parametricCoordinates,
519  real_type functions[4][8]) const {
520  real_type xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
521  if (numDimensions == 1) {
522  xi = parametricCoordinates[0];
523  denominator = 2.0;
524  } else if (numDimensions == 2) {
525  xi = parametricCoordinates[0];
526  eta = parametricCoordinates[1];
527  denominator = 4.0;
528  } else if (numDimensions == 3) {
529  xi = parametricCoordinates[0];
530  eta = parametricCoordinates[1];
531  zeta = parametricCoordinates[2];
532  denominator = 8.0;
533  }
534 
535  functions[0][0] = (1.0 - xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
536  functions[0][1] = (1.0 + xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
537  functions[0][2] = (1.0 - xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
538  functions[0][3] = (1.0 + xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
539  functions[0][4] = (1.0 - xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
540  functions[0][5] = (1.0 + xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
541  functions[0][6] = (1.0 - xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
542  functions[0][7] = (1.0 + xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
543 
544  functions[1][0] = -(1.0 - eta) * (1.0 - zeta) / denominator;
545  functions[1][1] = (1.0 - eta) * (1.0 - zeta) / denominator;
546  functions[1][2] = -(1.0 + eta) * (1.0 - zeta) / denominator;
547  functions[1][3] = (1.0 + eta) * (1.0 - zeta) / denominator;
548  functions[1][4] = -(1.0 - eta) * (1.0 + zeta) / denominator;
549  functions[1][5] = (1.0 - eta) * (1.0 + zeta) / denominator;
550  functions[1][6] = -(1.0 + eta) * (1.0 + zeta) / denominator;
551  functions[1][7] = (1.0 + eta) * (1.0 + zeta) / denominator;
552 
553  functions[2][0] = -(1.0 - xi) * (1.0 - zeta) / denominator;
554  functions[2][1] = -(1.0 + xi) * (1.0 - zeta) / denominator;
555  functions[2][2] = (1.0 - xi) * (1.0 - zeta) / denominator;
556  functions[2][3] = (1.0 + xi) * (1.0 - zeta) / denominator;
557  functions[2][4] = -(1.0 - xi) * (1.0 + zeta) / denominator;
558  functions[2][5] = -(1.0 + xi) * (1.0 + zeta) / denominator;
559  functions[2][6] = (1.0 - xi) * (1.0 + zeta) / denominator;
560  functions[2][7] = (1.0 + xi) * (1.0 + zeta) / denominator;
561 
562  functions[3][0] = -(1.0 - xi) * (1.0 - eta) / denominator;
563  functions[3][1] = -(1.0 + xi) * (1.0 - eta) / denominator;
564  functions[3][2] = -(1.0 - xi) * (1.0 + eta) / denominator;
565  functions[3][3] = -(1.0 + xi) * (1.0 + eta) / denominator;
566  functions[3][4] = (1.0 - xi) * (1.0 - eta) / denominator;
567  functions[3][5] = (1.0 + xi) * (1.0 - eta) / denominator;
568  functions[3][6] = (1.0 - xi) * (1.0 + eta) / denominator;
569  functions[3][7] = (1.0 + xi) * (1.0 + eta) / denominator;
570 
571 } // End GetInterpolationFunctions
572 
573 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
576  coord_view_type fineCoordView,
577  coord_view_type coarseCoordView)
578  : geoData_(*geoData)
579  , fineCoordView_(fineCoordView)
580  , coarseCoordView_(coarseCoordView) {
581 } // coarseCoordinatesBuilderFunctor()
582 
583 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
586  LO fineNodeIdx;
587  LO nodeCoarseTuple[3] = {0, 0, 0};
588  LO nodeFineTuple[3] = {0, 0, 0};
589  auto coarseningRate = geoData_.getCoarseningRates();
590  auto fineNodesPerDir = geoData_.getLocalFineNodesPerDir();
591  auto coarseNodesPerDir = geoData_.getCoarseNodesPerDir();
592  geoData_.getCoarseLID2CoarseTuple(coarseNodeIdx, nodeCoarseTuple);
593  for (int dim = 0; dim < 3; ++dim) {
594  if (nodeCoarseTuple[dim] == coarseNodesPerDir(dim) - 1) {
595  nodeFineTuple[dim] = fineNodesPerDir(dim) - 1;
596  } else {
597  nodeFineTuple[dim] = nodeCoarseTuple[dim] * coarseningRate(dim);
598  }
599  }
600 
601  fineNodeIdx = nodeFineTuple[2] * fineNodesPerDir(1) * fineNodesPerDir(0) + nodeFineTuple[1] * fineNodesPerDir(0) + nodeFineTuple[0];
602 
603  for (int dim = 0; dim < fineCoordView_.extent_int(1); ++dim) {
604  coarseCoordView_(coarseNodeIdx, dim) = fineCoordView_(fineNodeIdx, dim);
605  }
606 }
607 
608 } // namespace MueLu
609 
610 #endif // MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
typename BMV::impl_scalar_type impl_scalar_type
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
coarseCoordinatesBuilderFunctor(RCP< IndexManager_kokkos > geoData, coord_view_type fineCoordView, coord_view_type coarseCoordView)
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.
size_type size() const
LocalOrdinal LO
void GetInterpolationFunctions(const LO numDimensions, const Teuchos::SerialDenseVector< LO, real_type > parametricCoordinates, real_type functions[4][8]) const
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
typename Teuchos::ScalarTraits< SC >::coordinateType real_type
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
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)
typename Kokkos::View< impl_scalar_type **, Kokkos::LayoutLeft, device_type > coord_view_type
void BuildConstantP(RCP< Matrix > &P, RCP< const CrsGraph > &prolongatorGraph, RCP< Matrix > &A) const
#define SET_VALID_ENTRY(name)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
void resize(size_type new_size, const value_type &x=value_type())
TransListIter iter
int size(OrdinalType length_in)
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
void BuildLinearP(RCP< Matrix > &A, RCP< const CrsGraph > &prolongatorGraph, RCP< realvaluedmultivector_type > &fineCoordinates, RCP< realvaluedmultivector_type > &ghostCoordinates, const int numDimensions, RCP< Matrix > &P) const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void residual(const Operator< SC, LO, GO, NO > &Aop, const MultiVector< SC, LO, GO, NO > &X_in, const MultiVector< SC, LO, GO, NO > &B_in, MultiVector< SC, LO, GO, NO > &R_in)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)