233void setupReducedMatrices(
const Matrix& massMatrix,
const Matrix& projMatrix,
const std::vector<bool>& dofIsVoid,
234 Matrix& reducedM, Matrix& reducedP, std::vector<std::size_t>& expansionMap)
236 const std::size_t numNonVoidDofs = std::count_if(dofIsVoid.begin(), dofIsVoid.end(), [] (
bool v) { return !v; });
239 std::vector<std::size_t> reductionMap(massMatrix.N());
240 expansionMap.resize(numNonVoidDofs);
242 std::size_t idxInReducedSpace = 0;
243 for (std::size_t dofIdx = 0; dofIdx < dofIsVoid.size(); ++dofIdx)
244 if (!dofIsVoid[dofIdx])
246 reductionMap[dofIdx] = idxInReducedSpace;
247 expansionMap[idxInReducedSpace] = dofIdx;
252 Dune::MatrixIndexSet patternMReduced, patternPReduced;
253 patternMReduced.resize(numNonVoidDofs, numNonVoidDofs);
254 patternPReduced.resize(numNonVoidDofs, projMatrix.M());
255 for (
auto rowIt = massMatrix.begin(); rowIt != massMatrix.end(); ++rowIt)
256 if (!dofIsVoid[rowIt.index()])
258 const auto reducedRowIdx = reductionMap[rowIt.index()];
259 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
260 if (!dofIsVoid[colIt.index()])
261 patternMReduced.add(reducedRowIdx, reductionMap[colIt.index()]);
264 for (
auto rowIt = projMatrix.begin(); rowIt != projMatrix.end(); ++rowIt)
265 if (!dofIsVoid[rowIt.index()])
267 const auto reducedRowIdx = reductionMap[rowIt.index()];
268 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
269 patternPReduced.add(reducedRowIdx, colIt.index());
272 patternMReduced.exportIdx(reducedM);
273 patternPReduced.exportIdx(reducedP);
276 for (
auto rowIt = massMatrix.begin(); rowIt != massMatrix.end(); ++rowIt)
277 if (!dofIsVoid[rowIt.index()])
279 const auto reducedRowIdx = reductionMap[rowIt.index()];
280 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
281 if (!dofIsVoid[colIt.index()])
282 reducedM[reducedRowIdx][reductionMap[colIt.index()]] = *colIt;
285 for (
auto rowIt = projMatrix.begin(); rowIt != projMatrix.end(); ++rowIt)
286 if (!dofIsVoid[rowIt.index()])
288 const auto reducedRowIdx = reductionMap[rowIt.index()];
289 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
290 reducedP[reducedRowIdx][colIt.index()] = *colIt;
312 const FEBasisTarget& feBasisTarget,
313 const GlueType& glue,
314 bool treatDiagonalZeroes =
true)
317 static constexpr int domainDim = FEBasisDomain::GridView::dimension;
318 static constexpr int targetDim = FEBasisTarget::GridView::dimension;
319 static_assert(targetDim <= domainDim,
"This expects target dim < domain dim, please swap arguments");
324 using ForwardProjectionMatrix =
typename ForwardProjector::Matrix;
325 using BackwardProjectionMatrix =
typename BackwardProjector::Matrix;
327 auto domainLocalView = feBasisDomain.localView();
328 auto targetLocalView = feBasisTarget.localView();
331 Dune::MatrixIndexSet backwardPatternM, forwardPatternM;
336 Dune::MatrixIndexSet backwardPatternP, forwardPatternP;
337 forwardPatternP.resize(feBasisTarget.size(), feBasisDomain.size());
338 if (doBidirectional) backwardPatternP.resize(feBasisDomain.size(), feBasisTarget.size());
341 unsigned int maxBasisOrder = 0;
342 for (
const auto& is : intersections(glue))
345 targetLocalView.bind( is.targetEntity(0) );
346 const auto& targetLocalBasis = targetLocalView.tree().finiteElement().localBasis();
348 for (
unsigned int nIdx = 0; nIdx < is.numDomainNeighbors(); ++nIdx)
350 domainLocalView.bind( is.domainEntity(nIdx) );
351 const auto& domainLocalBasis = domainLocalView.tree().finiteElement().localBasis();
354 maxBasisOrder = max(maxBasisOrder, max(domainLocalBasis.order(), targetLocalBasis.order()));
356 for (
unsigned int i = 0; i < domainLocalBasis.size(); ++i)
357 for (
unsigned int j = 0; j < targetLocalBasis.size(); ++j)
359 forwardPatternP.add(targetLocalView.index(j), domainLocalView.index(i));
360 if (doBidirectional) backwardPatternP.add(domainLocalView.index(i), targetLocalView.index(j));
366 ForwardProjectionMatrix forwardM, forwardP;
367 forwardPatternM.exportIdx(forwardM); forwardM = 0.0;
368 forwardPatternP.exportIdx(forwardP); forwardP = 0.0;
370 BackwardProjectionMatrix backwardM, backwardP;
373 backwardPatternM.exportIdx(backwardM); backwardM = 0.0;
374 backwardPatternP.exportIdx(backwardP); backwardP = 0.0;
377 for (
const auto& is : intersections(glue))
379 const auto& targetElement = is.targetEntity(0);
380 const auto& targetElementGeometry = targetElement.geometry();
382 targetLocalView.bind( targetElement );
383 const auto& targetLocalBasis = targetLocalView.tree().finiteElement().localBasis();
386 using IsGeometry =
typename std::decay_t<
decltype(is.geometry())>;
387 using ctype =
typename IsGeometry::ctype;
389 const auto& isGeometry = is.geometry();
390 const int intOrder = maxBasisOrder + 1;
391 const auto& quad = Dune::QuadratureRules<ctype, IsGeometry::mydimension>::rule(isGeometry.type(), intOrder);
392 for (
auto&& qp : quad)
394 const auto weight = qp.weight();
395 const auto ie = isGeometry.integrationElement(qp.position());
396 const auto globalPos = isGeometry.global(qp.position());
398 std::vector< Dune::FieldVector<ctype, 1> > targetShapeVals;
399 targetLocalBasis.evaluateFunction(targetElementGeometry.local(globalPos), targetShapeVals);
402 for (
unsigned int i = 0; i < targetLocalBasis.size(); ++i)
404 const auto dofIdxI = targetLocalView.index(i);
405 forwardM[dofIdxI][dofIdxI][0][0] += ie*weight*targetShapeVals[i]*targetShapeVals[i];
407 for (
unsigned int j = i+1; j < targetLocalBasis.size(); ++j)
409 const auto dofIdxJ = targetLocalView.index(j);
410 const auto value = ie*weight*targetShapeVals[i]*targetShapeVals[j];
411 forwardM[dofIdxI][dofIdxJ][0][0] += value;
412 forwardM[dofIdxJ][dofIdxI][0][0] += value;
420 const auto numNeighbors = is.numDomainNeighbors();
421 for (
unsigned int nIdx = 0; nIdx < numNeighbors; ++nIdx)
423 const auto& domainElement = is.domainEntity(nIdx);
424 domainLocalView.bind( domainElement );
425 const auto& domainLocalBasis = domainLocalView.tree().finiteElement().localBasis();
427 std::vector< Dune::FieldVector<ctype, 1> > domainShapeVals;
428 domainLocalBasis.evaluateFunction(domainElement.geometry().local(globalPos), domainShapeVals);
431 for (
unsigned int i = 0; i < domainLocalBasis.size(); ++i)
433 const auto dofIdxDomain = domainLocalView.index(i);
434 const auto domainShapeVal = domainShapeVals[i];
437 backwardM[dofIdxDomain][dofIdxDomain][0][0] += ie*weight*domainShapeVal*domainShapeVal;
439 for (
unsigned int j = i+1; j < domainLocalBasis.size(); ++j)
441 const auto dofIdxDomainJ = domainLocalView.index(j);
442 const auto value = ie*weight*domainShapeVal*domainShapeVals[j];
443 backwardM[dofIdxDomain][dofIdxDomainJ][0][0] += value;
444 backwardM[dofIdxDomainJ][dofIdxDomain][0][0] += value;
448 for (
unsigned int j = 0; j < targetLocalBasis.size(); ++j)
450 const auto dofIdxTarget = targetLocalView.index(j);
451 const auto entry = ie*weight*domainShapeVal*targetShapeVals[j];
453 forwardP[dofIdxTarget][dofIdxDomain][0][0] += entry/numNeighbors;
455 backwardP[dofIdxDomain][dofIdxTarget][0][0] += entry;
463 if (treatDiagonalZeroes)
465 for (std::size_t dofIdxTarget = 0; dofIdxTarget < forwardM.N(); ++dofIdxTarget)
466 if (forwardM[dofIdxTarget][dofIdxTarget][0][0] == 0.0)
467 forwardM[dofIdxTarget][dofIdxTarget][0][0] = 1.0;
471 for (std::size_t dofIdxDomain = 0; dofIdxDomain < backwardM.N(); ++dofIdxDomain)
472 if (backwardM[dofIdxDomain][dofIdxDomain][0][0] == 0.0)
473 backwardM[dofIdxDomain][dofIdxDomain][0][0] = 1.0;
477 return std::make_pair( std::make_pair(std::move(forwardM), std::move(forwardP)),
478 std::make_pair(std::move(backwardM), std::move(backwardP)) );
488 const FEBasisTarget& feBasisTarget,
489 const GlueType& glue)
494 using ForwardProjectionMatrix =
typename ForwardProjector::Matrix;
495 using BackwardProjectionMatrix =
typename BackwardProjector::Matrix;
498 auto& forwardMatrices = projectionMatrices.first;
499 auto& backwardMatrices = projectionMatrices.second;
501 auto& forwardM = forwardMatrices.first;
502 auto& forwardP = forwardMatrices.second;
504 auto& backwardM = backwardMatrices.first;
505 auto& backwardP = backwardMatrices.second;
508 std::vector<bool> isVoidTarget(forwardM.N(),
false);
509 for (std::size_t dofIdxTarget = 0; dofIdxTarget < forwardM.N(); ++dofIdxTarget)
510 if (forwardM[dofIdxTarget][dofIdxTarget][0][0] == 0.0)
511 isVoidTarget[dofIdxTarget] =
true;
513 std::vector<bool> isVoidDomain;
516 isVoidDomain.resize(backwardM.N(),
false);
517 for (std::size_t dofIdxDomain = 0; dofIdxDomain < backwardM.N(); ++dofIdxDomain)
518 if (backwardM[dofIdxDomain][dofIdxDomain][0][0] == 0.0)
519 isVoidDomain[dofIdxDomain] =
true;
522 const bool hasVoidTarget = std::any_of(isVoidTarget.begin(), isVoidTarget.end(), [] (
bool v) { return v; });
523 const bool hasVoidDomain = std::any_of(isVoidDomain.begin(), isVoidDomain.end(), [] (
bool v) { return v; });
524 if (!hasVoidDomain && !hasVoidTarget)
526 return std::make_pair(ForwardProjector(std::move(forwardM), std::move(forwardP)),
527 BackwardProjector(std::move(backwardM), std::move(backwardP)));
529 else if (!hasVoidDomain && hasVoidTarget)
531 std::vector<std::size_t> expansionMapTarget;
532 ForwardProjectionMatrix forwardMReduced, forwardPReduced;
534 forwardMReduced, forwardPReduced, expansionMapTarget);
536 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
537 std::move(forwardPReduced),
538 std::move(expansionMapTarget),
540 BackwardProjector(std::move(backwardM), std::move(backwardP)) );
542 else if (hasVoidDomain && !hasVoidTarget)
546 std::vector<std::size_t> expansionMapDomain;
547 BackwardProjectionMatrix backwardMReduced, backwardPReduced;
549 backwardMReduced, backwardPReduced, expansionMapDomain);
551 return std::make_pair( ForwardProjector(std::move(forwardM), std::move(forwardP)),
552 BackwardProjector(std::move(backwardMReduced),
553 std::move(backwardPReduced),
554 std::move(expansionMapDomain),
558 return std::make_pair( ForwardProjector(std::move(forwardM), std::move(forwardP)),
559 BackwardProjector(std::move(backwardM), std::move(backwardP)) );
563 std::vector<std::size_t> expansionMapTarget;
564 ForwardProjectionMatrix forwardMReduced, forwardPReduced;
566 forwardMReduced, forwardPReduced, expansionMapTarget);
570 std::vector<std::size_t> expansionMapDomain;
571 BackwardProjectionMatrix backwardMReduced, backwardPReduced;
573 backwardMReduced, backwardPReduced, expansionMapDomain);
575 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
576 std::move(forwardPReduced),
577 std::move(expansionMapTarget),
579 BackwardProjector(std::move(backwardMReduced),
580 std::move(backwardPReduced),
581 std::move(expansionMapDomain),
585 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
586 std::move(forwardPReduced),
587 std::move(expansionMapTarget),
589 BackwardProjector(std::move(backwardM), std::move(backwardP)) );