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 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
11 #define MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
12 
13 #include "Xpetra_CrsGraph.hpp"
15 
16 #include "MueLu_MasterList.hpp"
17 #include "MueLu_Monitor.hpp"
18 #include "MueLu_IndexManager_kokkos.hpp"
19 
20 #include "Xpetra_TpetraCrsMatrix.hpp"
21 
22 // Including this one last ensure that the short names of the above headers are defined properly
24 
25 namespace MueLu {
26 
27 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
29  RCP<ParameterList> validParamList = rcp(new ParameterList());
30 
31 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
32  SET_VALID_ENTRY("interp: build coarse coordinates");
33 #undef SET_VALID_ENTRY
34 
35  // general variables needed in GeometricInterpolationPFactory_kokkos
36  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null,
37  "Generating factory of the matrix A");
38  validParamList->set<RCP<const FactoryBase> >("prolongatorGraph", Teuchos::null,
39  "Graph generated by StructuredAggregationFactory used to construct a piece-linear prolongator.");
40  validParamList->set<RCP<const FactoryBase> >("Coordinates", Teuchos::null,
41  "Fine level coordinates used to construct piece-wise linear prolongator and coarse level coordinates.");
42  validParamList->set<RCP<const FactoryBase> >("Nullspace", Teuchos::null,
43  "Fine level nullspace used to construct the coarse level nullspace.");
44  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
45  "Number of spacial dimensions in the problem.");
46  validParamList->set<RCP<const FactoryBase> >("lCoarseNodesPerDim", Teuchos::null,
47  "Number of nodes per spatial dimension on the coarse grid.");
48  validParamList->set<RCP<const FactoryBase> >("indexManager", Teuchos::null,
49  "The index manager associated with the local mesh.");
50  validParamList->set<RCP<const FactoryBase> >("structuredInterpolationOrder", Teuchos::null,
51  "Interpolation order for constructing the prolongator.");
52 
53  return validParamList;
54 }
55 
56 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
58  DeclareInput(Level& fineLevel, Level& coarseLevel) const {
59  const ParameterList& pL = GetParameterList();
60 
61  Input(fineLevel, "A");
62  Input(fineLevel, "Nullspace");
63  Input(fineLevel, "numDimensions");
64  Input(fineLevel, "prolongatorGraph");
65  Input(fineLevel, "lCoarseNodesPerDim");
66  Input(fineLevel, "structuredInterpolationOrder");
67 
68  if (pL.get<bool>("interp: build coarse coordinates") ||
69  Get<int>(fineLevel, "structuredInterpolationOrder") == 1) {
70  Input(fineLevel, "Coordinates");
71  Input(fineLevel, "indexManager");
72  }
73 }
74 
75 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
77  Build(Level& fineLevel, Level& coarseLevel) const {
78  return BuildP(fineLevel, coarseLevel);
79 }
80 
81 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
83  BuildP(Level& fineLevel, Level& coarseLevel) const {
84  FactoryMonitor m(*this, "BuildP", coarseLevel);
85 
86  // Set debug outputs based on environment variable
88  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
89  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
90  out->setShowAllFrontMatter(false).setShowProcRank(true);
91  } else {
92  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
93  }
94 
95  *out << "Starting GeometricInterpolationPFactory_kokkos::BuildP." << std::endl;
96 
97  // Get inputs from the parameter list
98  const ParameterList& pL = GetParameterList();
99  const bool buildCoarseCoordinates = pL.get<bool>("interp: build coarse coordinates");
100  const int interpolationOrder = Get<int>(fineLevel, "structuredInterpolationOrder");
101  const int numDimensions = Get<int>(fineLevel, "numDimensions");
102 
103  // Declared main input/outputs to be retrieved and placed on the fine resp. coarse level
104  RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
105  RCP<const CrsGraph> prolongatorGraph = Get<RCP<CrsGraph> >(fineLevel, "prolongatorGraph");
106  RCP<realvaluedmultivector_type> fineCoordinates, coarseCoordinates;
107  RCP<Matrix> P;
108 
109  // Check if we need to build coarse coordinates as they are used if we construct
110  // a linear interpolation prolongator
111  if (buildCoarseCoordinates || (interpolationOrder == 1)) {
112  SubFactoryMonitor sfm(*this, "BuildCoordinates", coarseLevel);
113 
114  // Extract data from fine level
115  RCP<IndexManager_kokkos> geoData = Get<RCP<IndexManager_kokkos> >(fineLevel, "indexManager");
116  fineCoordinates = Get<RCP<realvaluedmultivector_type> >(fineLevel, "Coordinates");
117 
118  // Build coarse coordinates map/multivector
119  RCP<const Map> coarseCoordsMap = MapFactory::Build(fineCoordinates->getMap()->lib(),
121  geoData->getNumCoarseNodes(),
122  fineCoordinates->getMap()->getIndexBase(),
123  fineCoordinates->getMap()->getComm());
125  Build(coarseCoordsMap, fineCoordinates->getNumVectors());
126 
127  // Construct and launch functor to fill coarse coordinates values
128  // function should take a const view really
129  coarseCoordinatesBuilderFunctor myCoarseCoordinatesBuilder(geoData,
130  fineCoordinates->getDeviceLocalView(Xpetra::Access::ReadWrite),
131  coarseCoordinates->getDeviceLocalView(Xpetra::Access::OverwriteAll));
132  Kokkos::parallel_for("GeometricInterpolation: build coarse coordinates",
133  Kokkos::RangePolicy<execution_space>(0, geoData->getNumCoarseNodes()),
134  myCoarseCoordinatesBuilder);
135 
136  Set(coarseLevel, "Coordinates", coarseCoordinates);
137  }
138 
139  *out << "Fine and coarse coordinates have been loaded from the fine level and set on the coarse level." << std::endl;
140 
141  if (interpolationOrder == 0) {
142  SubFactoryMonitor sfm(*this, "BuildConstantP", coarseLevel);
143  // Compute the prolongator using piece-wise constant interpolation
144  BuildConstantP(P, prolongatorGraph, A);
145  } else if (interpolationOrder == 1) {
146  // Compute the prolongator using piece-wise linear interpolation
147  // First get all the required coordinates to compute the local part of P
148  RCP<realvaluedmultivector_type> ghostCoordinates = Xpetra::MultiVectorFactory<real_type, LO, GO, NO>::Build(prolongatorGraph->getColMap(),
149  fineCoordinates->getNumVectors());
150  RCP<const Import> ghostImporter = ImportFactory::Build(coarseCoordinates->getMap(),
151  prolongatorGraph->getColMap());
152  ghostCoordinates->doImport(*coarseCoordinates, *ghostImporter, Xpetra::INSERT);
153 
154  SubFactoryMonitor sfm(*this, "BuildLinearP", coarseLevel);
155  BuildLinearP(A, prolongatorGraph, fineCoordinates, ghostCoordinates, numDimensions, P);
156  }
157 
158  *out << "The prolongator matrix has been built." << std::endl;
159 
160  {
161  SubFactoryMonitor sfm(*this, "BuildNullspace", coarseLevel);
162  // Build the coarse nullspace
163  RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel, "Nullspace");
164  RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
165  fineNullspace->getNumVectors());
166  P->apply(*fineNullspace, *coarseNullspace, Teuchos::TRANS, Teuchos::ScalarTraits<SC>::one(),
168  Set(coarseLevel, "Nullspace", coarseNullspace);
169  }
170 
171  *out << "The coarse nullspace is constructed and set on the coarse level." << std::endl;
172 
173  Array<LO> lNodesPerDir = Get<Array<LO> >(fineLevel, "lCoarseNodesPerDim");
174  Set(coarseLevel, "numDimensions", numDimensions);
175  Set(coarseLevel, "lNodesPerDim", lNodesPerDir);
176  Set(coarseLevel, "P", P);
177 
178  *out << "GeometricInterpolationPFactory_kokkos::BuildP has completed." << std::endl;
179 
180 } // BuildP
181 
182 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
184  BuildConstantP(RCP<Matrix>& P, RCP<const CrsGraph>& prolongatorGraph, RCP<Matrix>& A) const {
185  // Set debug outputs based on environment variable
187  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
188  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
189  out->setShowAllFrontMatter(false).setShowProcRank(true);
190  } else {
191  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
192  }
193 
194  *out << "BuildConstantP" << std::endl;
195 
196  std::vector<size_t> strideInfo(1);
197  strideInfo[0] = A->GetFixedBlockSize();
198  RCP<const StridedMap> stridedDomainMap =
199  StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
200 
201  *out << "Call prolongator constructor" << std::endl;
203  if (helpers::isTpetraBlockCrs(A)) {
204  LO NSDim = A->GetStorageBlockSize();
205 
206  // Build the exploded Map
207  // FIXME: Should look at doing this on device
208  RCP<const Map> BlockMap = prolongatorGraph->getDomainMap();
209  Teuchos::ArrayView<const GO> block_dofs = BlockMap->getLocalElementList();
210  Teuchos::Array<GO> point_dofs(block_dofs.size() * NSDim);
211  for (LO i = 0, ct = 0; i < block_dofs.size(); i++) {
212  for (LO j = 0; j < NSDim; j++) {
213  point_dofs[ct] = block_dofs[i] * NSDim + j;
214  ct++;
215  }
216  }
217 
218  RCP<const Map> PointMap = MapFactory::Build(BlockMap->lib(),
219  BlockMap->getGlobalNumElements() * NSDim,
220  point_dofs(),
221  BlockMap->getIndexBase(),
222  BlockMap->getComm());
223  strideInfo[0] = A->GetFixedBlockSize();
224  RCP<const StridedMap> stridedPointMap = StridedMapFactory::Build(PointMap, strideInfo);
225 
226  RCP<Xpetra::CrsMatrix<SC, LO, GO, NO> > P_xpetra = Xpetra::CrsMatrixFactory<SC, LO, GO, NO>::BuildBlock(prolongatorGraph, PointMap, A->getRangeMap(), NSDim);
228  if (P_tpetra.is_null()) throw std::runtime_error("BuildConstantP: Matrix factory did not return a Tpetra::BlockCrsMatrix");
229  RCP<CrsMatrixWrap> P_wrap = rcp(new CrsMatrixWrap(P_xpetra));
230 
231  const LO stride = strideInfo[0] * strideInfo[0];
232  const LO in_stride = strideInfo[0];
233  typename CrsMatrix::local_graph_type localGraph = prolongatorGraph->getLocalGraphDevice();
234  auto rowptr = localGraph.row_map;
235  auto indices = localGraph.entries;
236  auto values = P_tpetra->getTpetra_BlockCrsMatrix()->getValuesDeviceNonConst();
237 
240 
241  const Kokkos::TeamPolicy<execution_space> policy(prolongatorGraph->getLocalNumRows(), 1);
242 
243  Kokkos::parallel_for(
244  "MueLu:GeoInterpFact::BuildConstantP::fill", policy,
245  KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<execution_space>::member_type& thread) {
246  auto row = thread.league_rank();
247  for (LO j = (LO)rowptr[row]; j < (LO)rowptr[row + 1]; j++) {
248  LO block_offset = j * stride;
249  for (LO k = 0; k < in_stride; k++)
250  values[block_offset + k * (in_stride + 1)] = one;
251  }
252  });
253 
254  P = P_wrap;
255  if (A->IsView("stridedMaps") == true) {
256  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedPointMap);
257  } else {
258  P->CreateView("stridedMaps", P->getRangeMap(), PointMap);
259  }
260  } else {
261  // Create the prolongator matrix and its associated objects
262  RCP<ParameterList> dummyList = rcp(new ParameterList());
263  P = rcp(new CrsMatrixWrap(prolongatorGraph, dummyList));
264  RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
265  PCrs->setAllToScalar(1.0);
266  PCrs->fillComplete();
267 
268  // set StridingInformation of P
269  if (A->IsView("stridedMaps") == true) {
270  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedDomainMap);
271  } else {
272  P->CreateView("stridedMaps", P->getRangeMap(), stridedDomainMap);
273  }
274  }
275 
276 } // BuildConstantP
277 
278 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
281  RCP<realvaluedmultivector_type>& fineCoordinates,
282  RCP<realvaluedmultivector_type>& ghostCoordinates,
283  const int numDimensions, RCP<Matrix>& P) const {
284  // Set debug outputs based on environment variable
286  if (const char* dbg = std::getenv("MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
287  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
288  out->setShowAllFrontMatter(false).setShowProcRank(true);
289  } else {
290  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
291  }
292 
293  *out << "Entering BuildLinearP" << std::endl;
294 
295  // Extract coordinates for interpolation stencil calculations
296  const LO numFineNodes = fineCoordinates->getLocalLength();
297  const LO numGhostNodes = ghostCoordinates->getLocalLength();
298  Array<ArrayRCP<const real_type> > fineCoords(3);
299  Array<ArrayRCP<const real_type> > ghostCoords(3);
300  const real_type realZero = Teuchos::as<real_type>(0.0);
301  ArrayRCP<real_type> fineZero(numFineNodes, realZero);
302  ArrayRCP<real_type> ghostZero(numGhostNodes, realZero);
303  for (int dim = 0; dim < 3; ++dim) {
304  if (dim < numDimensions) {
305  fineCoords[dim] = fineCoordinates->getData(dim);
306  ghostCoords[dim] = ghostCoordinates->getData(dim);
307  } else {
308  fineCoords[dim] = fineZero;
309  ghostCoords[dim] = ghostZero;
310  }
311  }
312 
313  *out << "Coordinates extracted from the multivectors!" << std::endl;
314 
315  // Compute 2^numDimensions using bit logic to avoid round-off errors
316  const int numInterpolationPoints = 1 << numDimensions;
317  const int dofsPerNode = A->GetFixedBlockSize();
318 
319  std::vector<size_t> strideInfo(1);
320  strideInfo[0] = dofsPerNode;
321  RCP<const StridedMap> stridedDomainMap =
322  StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
323 
324  *out << "The maps of P have been computed" << std::endl;
325 
326  RCP<ParameterList> dummyList = rcp(new ParameterList());
327  P = rcp(new CrsMatrixWrap(prolongatorGraph, dummyList));
328  RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
329  PCrs->resumeFill(); // The Epetra matrix is considered filled at this point.
330 
331  LO interpolationNodeIdx = 0, rowIdx = 0;
332  ArrayView<const LO> colIndices;
333  Array<SC> values;
334  Array<Array<real_type> > coords(numInterpolationPoints + 1);
335  Array<real_type> stencil(numInterpolationPoints);
336  for (LO nodeIdx = 0; nodeIdx < numFineNodes; ++nodeIdx) {
337  if (PCrs->getNumEntriesInLocalRow(nodeIdx * dofsPerNode) == 1) {
338  values.resize(1);
339  values[0] = 1.0;
340  for (LO dof = 0; dof < dofsPerNode; ++dof) {
341  rowIdx = nodeIdx * dofsPerNode + dof;
342  prolongatorGraph->getLocalRowView(rowIdx, colIndices);
343  PCrs->replaceLocalValues(rowIdx, colIndices, values());
344  }
345  } else {
346  // Extract the coordinates associated with the current node
347  // and the neighboring coarse nodes
348  coords[0].resize(3);
349  for (int dim = 0; dim < 3; ++dim) {
350  coords[0][dim] = fineCoords[dim][nodeIdx];
351  }
352  prolongatorGraph->getLocalRowView(nodeIdx * dofsPerNode, colIndices);
353  for (int interpolationIdx = 0; interpolationIdx < numInterpolationPoints; ++interpolationIdx) {
354  coords[interpolationIdx + 1].resize(3);
355  interpolationNodeIdx = colIndices[interpolationIdx] / dofsPerNode;
356  for (int dim = 0; dim < 3; ++dim) {
357  coords[interpolationIdx + 1][dim] = ghostCoords[dim][interpolationNodeIdx];
358  }
359  }
360  ComputeLinearInterpolationStencil(numDimensions, numInterpolationPoints, coords, stencil);
361  values.resize(numInterpolationPoints);
362  for (LO valueIdx = 0; valueIdx < numInterpolationPoints; ++valueIdx) {
363  values[valueIdx] = Teuchos::as<SC>(stencil[valueIdx]);
364  }
365 
366  // Set values in all the rows corresponding to nodeIdx
367  for (LO dof = 0; dof < dofsPerNode; ++dof) {
368  rowIdx = nodeIdx * dofsPerNode + dof;
369  prolongatorGraph->getLocalRowView(rowIdx, colIndices);
370  PCrs->replaceLocalValues(rowIdx, colIndices, values());
371  }
372  }
373  }
374 
375  *out << "The calculation of the interpolation stencils has completed." << std::endl;
376 
377  PCrs->fillComplete();
378 
379  *out << "All values in P have been set and expertStaticFillComplete has been performed." << std::endl;
380 
381  // set StridingInformation of P
382  if (A->IsView("stridedMaps") == true) {
383  P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), stridedDomainMap);
384  } else {
385  P->CreateView("stridedMaps", P->getRangeMap(), stridedDomainMap);
386  }
387 
388 } // BuildLinearP
389 
390 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
392  ComputeLinearInterpolationStencil(const int numDimensions, const int numInterpolationPoints,
393  const Array<Array<real_type> > coord,
394  Array<real_type>& stencil) const {
395  // 7 8 Find xi, eta and zeta such that
396  // x---------x
397  // /| /| Rx = x_p - sum N_i(xi,eta,zeta)x_i = 0
398  // 5/ | 6/ | Ry = y_p - sum N_i(xi,eta,zeta)y_i = 0
399  // x---------x | Rz = z_p - sum N_i(xi,eta,zeta)z_i = 0
400  // | | *P | |
401  // | x------|--x We can do this with a Newton solver:
402  // | /3 | /4 We will start with initial guess (xi,eta,zeta) = (0,0,0)
403  // |/ |/ We compute the Jacobian and iterate until convergence...
404  // z y x---------x
405  // | / 1 2 Once we have (xi,eta,zeta), we can evaluate all N_i which
406  // |/ give us the weights for the interpolation stencil!
407  // o---x
408  //
409 
410  Teuchos::SerialDenseMatrix<LO, real_type> Jacobian(numDimensions, numDimensions);
412  Teuchos::SerialDenseVector<LO, real_type> solutionDirection(numDimensions);
413  Teuchos::SerialDenseVector<LO, real_type> paramCoords(numDimensions);
415  int iter = 0, max_iter = 5;
416  real_type functions[4][8], norm_ref = 1.0, norm2 = 1.0, tol = 1.0e-5;
417  paramCoords.size(numDimensions);
418 
419  while ((iter < max_iter) && (norm2 > tol * norm_ref)) {
420  ++iter;
421  norm2 = 0.0;
422  solutionDirection.size(numDimensions);
423  residual.size(numDimensions);
424  Jacobian = 0.0;
425 
426  // Compute Jacobian and Residual
427  GetInterpolationFunctions(numDimensions, paramCoords, functions);
428  for (LO i = 0; i < numDimensions; ++i) {
429  residual(i) = coord[0][i]; // Add coordinates from point of interest
430  for (LO k = 0; k < numInterpolationPoints; ++k) {
431  residual(i) -= functions[0][k] * coord[k + 1][i]; // Remove contribution from all coarse points
432  }
433  if (iter == 1) {
434  norm_ref += residual(i) * residual(i);
435  if (i == numDimensions - 1) {
436  norm_ref = std::sqrt(norm_ref);
437  }
438  }
439 
440  for (LO j = 0; j < numDimensions; ++j) {
441  for (LO k = 0; k < numInterpolationPoints; ++k) {
442  Jacobian(i, j) += functions[j + 1][k] * coord[k + 1][i];
443  }
444  }
445  }
446 
447  // Set Jacobian, Vectors and solve problem
448  problem.setMatrix(Teuchos::rcp(&Jacobian, false));
449  problem.setVectors(Teuchos::rcp(&solutionDirection, false), Teuchos::rcp(&residual, false));
450  if (problem.shouldEquilibrate()) {
451  problem.factorWithEquilibration(true);
452  }
453  problem.solve();
454 
455  for (LO i = 0; i < numDimensions; ++i) {
456  paramCoords(i) = paramCoords(i) + solutionDirection(i);
457  }
458 
459  // Recompute Residual norm
460  GetInterpolationFunctions(numDimensions, paramCoords, functions);
461  for (LO i = 0; i < numDimensions; ++i) {
462  real_type tmp = coord[0][i];
463  for (LO k = 0; k < numInterpolationPoints; ++k) {
464  tmp -= functions[0][k] * coord[k + 1][i];
465  }
466  norm2 += tmp * tmp;
467  tmp = 0.0;
468  }
469  norm2 = std::sqrt(norm2);
470  }
471 
472  // Load the interpolation values onto the stencil.
473  for (LO i = 0; i < numInterpolationPoints; ++i) {
474  stencil[i] = functions[0][i];
475  }
476 
477 } // End ComputeLinearInterpolationStencil
478 
479 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
481  GetInterpolationFunctions(const LO numDimensions,
482  const Teuchos::SerialDenseVector<LO, real_type> parametricCoordinates,
483  real_type functions[4][8]) const {
484  real_type xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
485  if (numDimensions == 1) {
486  xi = parametricCoordinates[0];
487  denominator = 2.0;
488  } else if (numDimensions == 2) {
489  xi = parametricCoordinates[0];
490  eta = parametricCoordinates[1];
491  denominator = 4.0;
492  } else if (numDimensions == 3) {
493  xi = parametricCoordinates[0];
494  eta = parametricCoordinates[1];
495  zeta = parametricCoordinates[2];
496  denominator = 8.0;
497  }
498 
499  functions[0][0] = (1.0 - xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
500  functions[0][1] = (1.0 + xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
501  functions[0][2] = (1.0 - xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
502  functions[0][3] = (1.0 + xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
503  functions[0][4] = (1.0 - xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
504  functions[0][5] = (1.0 + xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
505  functions[0][6] = (1.0 - xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
506  functions[0][7] = (1.0 + xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
507 
508  functions[1][0] = -(1.0 - eta) * (1.0 - zeta) / denominator;
509  functions[1][1] = (1.0 - eta) * (1.0 - zeta) / denominator;
510  functions[1][2] = -(1.0 + eta) * (1.0 - zeta) / denominator;
511  functions[1][3] = (1.0 + eta) * (1.0 - zeta) / denominator;
512  functions[1][4] = -(1.0 - eta) * (1.0 + zeta) / denominator;
513  functions[1][5] = (1.0 - eta) * (1.0 + zeta) / denominator;
514  functions[1][6] = -(1.0 + eta) * (1.0 + zeta) / denominator;
515  functions[1][7] = (1.0 + eta) * (1.0 + zeta) / denominator;
516 
517  functions[2][0] = -(1.0 - xi) * (1.0 - zeta) / denominator;
518  functions[2][1] = -(1.0 + xi) * (1.0 - zeta) / denominator;
519  functions[2][2] = (1.0 - xi) * (1.0 - zeta) / denominator;
520  functions[2][3] = (1.0 + xi) * (1.0 - zeta) / denominator;
521  functions[2][4] = -(1.0 - xi) * (1.0 + zeta) / denominator;
522  functions[2][5] = -(1.0 + xi) * (1.0 + zeta) / denominator;
523  functions[2][6] = (1.0 - xi) * (1.0 + zeta) / denominator;
524  functions[2][7] = (1.0 + xi) * (1.0 + zeta) / denominator;
525 
526  functions[3][0] = -(1.0 - xi) * (1.0 - eta) / denominator;
527  functions[3][1] = -(1.0 + xi) * (1.0 - eta) / denominator;
528  functions[3][2] = -(1.0 - xi) * (1.0 + eta) / denominator;
529  functions[3][3] = -(1.0 + xi) * (1.0 + eta) / denominator;
530  functions[3][4] = (1.0 - xi) * (1.0 - eta) / denominator;
531  functions[3][5] = (1.0 + xi) * (1.0 - eta) / denominator;
532  functions[3][6] = (1.0 - xi) * (1.0 + eta) / denominator;
533  functions[3][7] = (1.0 + xi) * (1.0 + eta) / denominator;
534 
535 } // End GetInterpolationFunctions
536 
537 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
540  coord_view_type fineCoordView,
541  coord_view_type coarseCoordView)
542  : geoData_(*geoData)
543  , fineCoordView_(fineCoordView)
544  , coarseCoordView_(coarseCoordView) {
545 } // coarseCoordinatesBuilderFunctor()
546 
547 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
550  LO fineNodeIdx;
551  LO nodeCoarseTuple[3] = {0, 0, 0};
552  LO nodeFineTuple[3] = {0, 0, 0};
553  auto coarseningRate = geoData_.getCoarseningRates();
554  auto fineNodesPerDir = geoData_.getLocalFineNodesPerDir();
555  auto coarseNodesPerDir = geoData_.getCoarseNodesPerDir();
556  geoData_.getCoarseLID2CoarseTuple(coarseNodeIdx, nodeCoarseTuple);
557  for (int dim = 0; dim < 3; ++dim) {
558  if (nodeCoarseTuple[dim] == coarseNodesPerDir(dim) - 1) {
559  nodeFineTuple[dim] = fineNodesPerDir(dim) - 1;
560  } else {
561  nodeFineTuple[dim] = nodeCoarseTuple[dim] * coarseningRate(dim);
562  }
563  }
564 
565  fineNodeIdx = nodeFineTuple[2] * fineNodesPerDir(1) * fineNodesPerDir(0) + nodeFineTuple[1] * fineNodesPerDir(0) + nodeFineTuple[0];
566 
567  for (int dim = 0; dim < fineCoordView_.extent_int(1); ++dim) {
568  coarseCoordView_(coarseNodeIdx, dim) = fineCoordView_(fineNodeIdx, dim);
569  }
570 }
571 
572 } // namespace MueLu
573 
574 #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)
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
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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:63
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)