234void setupReducedMatrices(
const Matrix& massMatrix,
const Matrix& projMatrix,
const std::vector<bool>& dofIsVoid,
235 Matrix& reducedM, Matrix& reducedP, std::vector<std::size_t>& expansionMap)
237 const std::size_t numNonVoidDofs = std::count_if(dofIsVoid.begin(), dofIsVoid.end(), [] (
bool v) { return !v; });
240 std::vector<std::size_t> reductionMap(massMatrix.N());
241 expansionMap.resize(numNonVoidDofs);
243 std::size_t idxInReducedSpace = 0;
244 for (std::size_t dofIdx = 0; dofIdx < dofIsVoid.size(); ++dofIdx)
245 if (!dofIsVoid[dofIdx])
247 reductionMap[dofIdx] = idxInReducedSpace;
248 expansionMap[idxInReducedSpace] = dofIdx;
253 Dune::MatrixIndexSet patternMReduced, patternPReduced;
254 patternMReduced.resize(numNonVoidDofs, numNonVoidDofs);
255 patternPReduced.resize(numNonVoidDofs, projMatrix.M());
256 for (
auto rowIt = massMatrix.begin(); rowIt != massMatrix.end(); ++rowIt)
257 if (!dofIsVoid[rowIt.index()])
259 const auto reducedRowIdx = reductionMap[rowIt.index()];
260 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
261 if (!dofIsVoid[colIt.index()])
262 patternMReduced.add(reducedRowIdx, reductionMap[colIt.index()]);
265 for (
auto rowIt = projMatrix.begin(); rowIt != projMatrix.end(); ++rowIt)
266 if (!dofIsVoid[rowIt.index()])
268 const auto reducedRowIdx = reductionMap[rowIt.index()];
269 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
270 patternPReduced.add(reducedRowIdx, colIt.index());
273 patternMReduced.exportIdx(reducedM);
274 patternPReduced.exportIdx(reducedP);
277 for (
auto rowIt = massMatrix.begin(); rowIt != massMatrix.end(); ++rowIt)
278 if (!dofIsVoid[rowIt.index()])
280 const auto reducedRowIdx = reductionMap[rowIt.index()];
281 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
282 if (!dofIsVoid[colIt.index()])
283 reducedM[reducedRowIdx][reductionMap[colIt.index()]] = *colIt;
286 for (
auto rowIt = projMatrix.begin(); rowIt != projMatrix.end(); ++rowIt)
287 if (!dofIsVoid[rowIt.index()])
289 const auto reducedRowIdx = reductionMap[rowIt.index()];
290 for (
auto colIt = (*rowIt).begin(); colIt != (*rowIt).end(); ++colIt)
291 reducedP[reducedRowIdx][colIt.index()] = *colIt;
318 const FEBasisTarget& feBasisTarget,
319 const GlueType& glue,
320 bool treatDiagonalZeroes =
true,
321 std::optional<int> quadratureOrder = {})
324 static constexpr int domainDim = FEBasisDomain::GridView::dimension;
325 static constexpr int targetDim = FEBasisTarget::GridView::dimension;
326 static_assert(targetDim <= domainDim,
"This expects target dim < domain dim, please swap arguments");
331 using ForwardProjectionMatrix =
typename ForwardProjector::Matrix;
332 using BackwardProjectionMatrix =
typename BackwardProjector::Matrix;
334 auto domainLocalView = feBasisDomain.localView();
335 auto targetLocalView = feBasisTarget.localView();
338 Dune::MatrixIndexSet backwardPatternM, forwardPatternM;
343 Dune::MatrixIndexSet backwardPatternP, forwardPatternP;
344 forwardPatternP.resize(feBasisTarget.size(), feBasisDomain.size());
345 if (doBidirectional) backwardPatternP.resize(feBasisDomain.size(), feBasisTarget.size());
347 for (
const auto& is : intersections(glue))
350 targetLocalView.bind( is.targetEntity(0) );
351 const auto& targetLocalBasis = targetLocalView.tree().finiteElement().localBasis();
353 for (
unsigned int nIdx = 0; nIdx < is.numDomainNeighbors(); ++nIdx)
355 domainLocalView.bind( is.domainEntity(nIdx) );
356 const auto& domainLocalBasis = domainLocalView.tree().finiteElement().localBasis();
358 for (
unsigned int i = 0; i < domainLocalBasis.size(); ++i)
359 for (
unsigned int j = 0; j < targetLocalBasis.size(); ++j)
361 forwardPatternP.add(targetLocalView.index(j), domainLocalView.index(i));
362 if (doBidirectional) backwardPatternP.add(domainLocalView.index(i), targetLocalView.index(j));
368 ForwardProjectionMatrix forwardM, forwardP;
369 forwardPatternM.exportIdx(forwardM); forwardM = 0.0;
370 forwardPatternP.exportIdx(forwardP); forwardP = 0.0;
372 BackwardProjectionMatrix backwardM, backwardP;
375 backwardPatternM.exportIdx(backwardM); backwardM = 0.0;
376 backwardPatternP.exportIdx(backwardP); backwardP = 0.0;
379 const auto totalDegree = [] (
const auto&
localView)
381 const auto& fe =
localView.tree().finiteElement();
382 const auto order = fe.localBasis().order();
383 return fe.type().isCube() ? fe.type().dim()*order : order;
390 const auto integrationOrder = [&] (
const auto& is,
unsigned int targetDegree)
393 return *quadratureOrder;
394 auto degree = targetDegree;
395 for (
unsigned int nIdx = 0; nIdx < is.numDomainNeighbors(); ++nIdx)
397 domainLocalView.bind( is.domainEntity(nIdx) );
398 degree = max(degree, totalDegree(domainLocalView));
400 return static_cast<int>(max(2*degree, 1u));
403 for (
const auto& is : intersections(glue))
405 const auto& targetElement = is.targetEntity(0);
406 const auto& targetElementGeometry = targetElement.geometry();
408 targetLocalView.bind( targetElement );
409 const auto& targetLocalBasis = targetLocalView.tree().finiteElement().localBasis();
412 using IsGeometry =
typename std::decay_t<
decltype(is.geometry())>;
413 using ctype =
typename IsGeometry::ctype;
415 const auto& isGeometry = is.geometry();
416 const int intOrder = integrationOrder(is, totalDegree(targetLocalView));
417 const auto& quad = Dune::QuadratureRules<ctype, IsGeometry::mydimension>::rule(isGeometry.type(), intOrder);
418 for (
auto&& qp : quad)
420 const auto weight = qp.weight();
421 const auto ie = isGeometry.integrationElement(qp.position());
422 const auto globalPos = isGeometry.global(qp.position());
424 std::vector< Dune::FieldVector<ctype, 1> > targetShapeVals;
425 targetLocalBasis.evaluateFunction(targetElementGeometry.local(globalPos), targetShapeVals);
428 for (
unsigned int i = 0; i < targetLocalBasis.size(); ++i)
430 const auto dofIdxI = targetLocalView.index(i);
431 forwardM[dofIdxI][dofIdxI][0][0] += ie*weight*targetShapeVals[i]*targetShapeVals[i];
433 for (
unsigned int j = i+1; j < targetLocalBasis.size(); ++j)
435 const auto dofIdxJ = targetLocalView.index(j);
436 const auto value = ie*weight*targetShapeVals[i]*targetShapeVals[j];
437 forwardM[dofIdxI][dofIdxJ][0][0] += value;
438 forwardM[dofIdxJ][dofIdxI][0][0] += value;
446 const auto numNeighbors = is.numDomainNeighbors();
447 for (
unsigned int nIdx = 0; nIdx < numNeighbors; ++nIdx)
449 const auto& domainElement = is.domainEntity(nIdx);
450 domainLocalView.bind( domainElement );
451 const auto& domainLocalBasis = domainLocalView.tree().finiteElement().localBasis();
453 std::vector< Dune::FieldVector<ctype, 1> > domainShapeVals;
454 domainLocalBasis.evaluateFunction(domainElement.geometry().local(globalPos), domainShapeVals);
457 for (
unsigned int i = 0; i < domainLocalBasis.size(); ++i)
459 const auto dofIdxDomain = domainLocalView.index(i);
460 const auto domainShapeVal = domainShapeVals[i];
463 backwardM[dofIdxDomain][dofIdxDomain][0][0] += ie*weight*domainShapeVal*domainShapeVal;
465 for (
unsigned int j = i+1; j < domainLocalBasis.size(); ++j)
467 const auto dofIdxDomainJ = domainLocalView.index(j);
468 const auto value = ie*weight*domainShapeVal*domainShapeVals[j];
469 backwardM[dofIdxDomain][dofIdxDomainJ][0][0] += value;
470 backwardM[dofIdxDomainJ][dofIdxDomain][0][0] += value;
474 for (
unsigned int j = 0; j < targetLocalBasis.size(); ++j)
476 const auto dofIdxTarget = targetLocalView.index(j);
477 const auto entry = ie*weight*domainShapeVal*targetShapeVals[j];
479 forwardP[dofIdxTarget][dofIdxDomain][0][0] += entry/numNeighbors;
481 backwardP[dofIdxDomain][dofIdxTarget][0][0] += entry;
489 if (treatDiagonalZeroes)
491 for (std::size_t dofIdxTarget = 0; dofIdxTarget < forwardM.N(); ++dofIdxTarget)
492 if (forwardM[dofIdxTarget][dofIdxTarget][0][0] == 0.0)
493 forwardM[dofIdxTarget][dofIdxTarget][0][0] = 1.0;
497 for (std::size_t dofIdxDomain = 0; dofIdxDomain < backwardM.N(); ++dofIdxDomain)
498 if (backwardM[dofIdxDomain][dofIdxDomain][0][0] == 0.0)
499 backwardM[dofIdxDomain][dofIdxDomain][0][0] = 1.0;
503 return std::make_pair( std::make_pair(std::move(forwardM), std::move(forwardP)),
504 std::make_pair(std::move(backwardM), std::move(backwardP)) );
514 const FEBasisTarget& feBasisTarget,
515 const GlueType& glue,
516 std::optional<int> quadratureOrder = {})
521 using ForwardProjectionMatrix =
typename ForwardProjector::Matrix;
522 using BackwardProjectionMatrix =
typename BackwardProjector::Matrix;
525 auto& forwardMatrices = projectionMatrices.first;
526 auto& backwardMatrices = projectionMatrices.second;
528 auto& forwardM = forwardMatrices.first;
529 auto& forwardP = forwardMatrices.second;
531 auto& backwardM = backwardMatrices.first;
532 auto& backwardP = backwardMatrices.second;
535 std::vector<bool> isVoidTarget(forwardM.N(),
false);
536 for (std::size_t dofIdxTarget = 0; dofIdxTarget < forwardM.N(); ++dofIdxTarget)
537 if (forwardM[dofIdxTarget][dofIdxTarget][0][0] == 0.0)
538 isVoidTarget[dofIdxTarget] =
true;
540 std::vector<bool> isVoidDomain;
543 isVoidDomain.resize(backwardM.N(),
false);
544 for (std::size_t dofIdxDomain = 0; dofIdxDomain < backwardM.N(); ++dofIdxDomain)
545 if (backwardM[dofIdxDomain][dofIdxDomain][0][0] == 0.0)
546 isVoidDomain[dofIdxDomain] =
true;
549 const bool hasVoidTarget = std::any_of(isVoidTarget.begin(), isVoidTarget.end(), [] (
bool v) { return v; });
550 const bool hasVoidDomain = std::any_of(isVoidDomain.begin(), isVoidDomain.end(), [] (
bool v) { return v; });
551 if (!hasVoidDomain && !hasVoidTarget)
553 return std::make_pair(ForwardProjector(std::move(forwardM), std::move(forwardP)),
554 BackwardProjector(std::move(backwardM), std::move(backwardP)));
556 else if (!hasVoidDomain && hasVoidTarget)
558 std::vector<std::size_t> expansionMapTarget;
559 ForwardProjectionMatrix forwardMReduced, forwardPReduced;
561 forwardMReduced, forwardPReduced, expansionMapTarget);
563 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
564 std::move(forwardPReduced),
565 std::move(expansionMapTarget),
567 BackwardProjector(std::move(backwardM), std::move(backwardP)) );
569 else if (hasVoidDomain && !hasVoidTarget)
573 std::vector<std::size_t> expansionMapDomain;
574 BackwardProjectionMatrix backwardMReduced, backwardPReduced;
576 backwardMReduced, backwardPReduced, expansionMapDomain);
578 return std::make_pair( ForwardProjector(std::move(forwardM), std::move(forwardP)),
579 BackwardProjector(std::move(backwardMReduced),
580 std::move(backwardPReduced),
581 std::move(expansionMapDomain),
585 return std::make_pair( ForwardProjector(std::move(forwardM), std::move(forwardP)),
586 BackwardProjector(std::move(backwardM), std::move(backwardP)) );
590 std::vector<std::size_t> expansionMapTarget;
591 ForwardProjectionMatrix forwardMReduced, forwardPReduced;
593 forwardMReduced, forwardPReduced, expansionMapTarget);
597 std::vector<std::size_t> expansionMapDomain;
598 BackwardProjectionMatrix backwardMReduced, backwardPReduced;
600 backwardMReduced, backwardPReduced, expansionMapDomain);
602 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
603 std::move(forwardPReduced),
604 std::move(expansionMapTarget),
606 BackwardProjector(std::move(backwardMReduced),
607 std::move(backwardPReduced),
608 std::move(expansionMapDomain),
612 return std::make_pair( ForwardProjector(std::move(forwardMReduced),
613 std::move(forwardPReduced),
614 std::move(expansionMapTarget),
616 BackwardProjector(std::move(backwardM), std::move(backwardP)) );