MueLu Version of the Day
Loading...
Searching...
No Matches
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
25namespace MueLu {
26
27template <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
56template <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
75template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
77 Build(Level& fineLevel, Level& coarseLevel) const {
78 return BuildP(fineLevel, coarseLevel);
79}
80
81template <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
87 RCP<Teuchos::FancyOStream> out;
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(),
120 Teuchos::OrdinalTraits<GO>::invalid(),
121 geoData->getNumCoarseNodes(),
122 fineCoordinates->getMap()->getIndexBase(),
123 fineCoordinates->getMap()->getComm());
124 coarseCoordinates = Xpetra::MultiVectorFactory<real_type, LO, GO, Node>::
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->getLocalViewDevice(Tpetra::Access::ReadWrite),
131 coarseCoordinates->getLocalViewDevice(Tpetra::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(),
167 Teuchos::ScalarTraits<SC>::zero());
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
182template <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
186 RCP<Teuchos::FancyOStream> out;
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;
202 using helpers = Xpetra::Helpers<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
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);
227 RCP<Xpetra::TpetraBlockCrsMatrix<SC, LO, GO, NO> > P_tpetra = rcp_dynamic_cast<Xpetra::TpetraBlockCrsMatrix<SC, LO, GO, NO> >(P_xpetra);
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_device_type localGraph = prolongatorGraph->getLocalGraphDevice();
234 auto rowptr = localGraph.row_map;
235 auto indices = localGraph.entries;
236 auto values = P_tpetra->getTpetra_BlockCrsMatrix()->getValuesDeviceNonConst();
237
238 using ISC = typename Tpetra::BlockCrsMatrix<SC, LO, GO, NO>::impl_scalar_type;
239 ISC one = Teuchos::ScalarTraits<ISC>::one();
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 = toCrsMatrix(P);
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
278template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
280 BuildLinearP(RCP<Matrix>& A, RCP<const CrsGraph>& prolongatorGraph,
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
285 RCP<Teuchos::FancyOStream> out;
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 = toCrsMatrix(P);
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
390template <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);
411 Teuchos::SerialDenseVector<LO, real_type> residual(numDimensions);
412 Teuchos::SerialDenseVector<LO, real_type> solutionDirection(numDimensions);
413 Teuchos::SerialDenseVector<LO, real_type> paramCoords(numDimensions);
414 Teuchos::SerialDenseSolver<LO, real_type> problem;
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
479template <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
537template <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
547template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
549 coarseCoordinatesBuilderFunctor::operator()(const LO coarseNodeIdx) const {
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
#define SET_VALID_ENTRY(name)
Timer to be used in factories. Similar to Monitor but with additional timers.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void ComputeLinearInterpolationStencil(const int numDimensions, const int numInterpolationPoints, const Array< Array< real_type > > coord, Array< real_type > &stencil) const
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.
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
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
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.
Class that holds all level-specific information.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Namespace for MueLu classes and methods.
coarseCoordinatesBuilderFunctor(RCP< IndexManager_kokkos > geoData, coord_view_type fineCoordView, coord_view_type coarseCoordView)