Commit 45a86958 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

added caching to all local assemblers

parent b01c33f7
Pipeline #1270 passed with stage
in 20 minutes and 58 seconds
......@@ -2,6 +2,7 @@
#include <type_traits>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/LocalOperator.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/Utility.hpp>
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -53,30 +54,34 @@ namespace AMDiS
using RowLocalBasisType = typename std::decay_t<decltype(rowLocalFE)>::Traits::LocalBasisType;
using ColLocalBasisType = typename std::decay_t<decltype(colLocalFE)>::Traits::LocalBasisType;
using RangeType = typename RowLocalBasisType::Traits::RangeType;
using RangeFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using JacobianType = typename ColLocalBasisType::Traits::JacobianType;
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& quad = this->getQuadratureRule(context.type(), rowNode, colNode);
for (auto const& qp : quad) {
auto const& shapeValuesCache = rowCache.evaluateFunctionAtQp(context, quad);
auto const& shapeGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
thread_local std::vector<RangeType> shapeValues;
rowLocalFE.localBasis().evaluateFunction(local, shapeValues);
// the values of the shape functions on the reference element at the quadrature point
auto const& shapeValues = shapeValuesCache[iq];
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > colGradients;
using WorldVector = FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> colGradients;
colGradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -50,32 +51,37 @@ namespace AMDiS
using RowLocalBasisType = typename std::decay_t<decltype(rowLocalFE)>::Traits::LocalBasisType;
using ColLocalBasisType = typename std::decay_t<decltype(colLocalFE)>::Traits::LocalBasisType;
using RangeType = typename RowLocalBasisType::Traits::RangeType;
using RangeFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using JacobianType = typename ColLocalBasisType::Traits::JacobianType;
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& quad = this->getQuadratureRule(context.type(), rowNode, colNode);
for (auto const& qp : quad) {
auto const& shapeValuesCache = rowCache.evaluateFunctionAtQp(context, quad);
auto const& shapeGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = context.integrationElement(qp.position()) * qp.weight();
const auto factor = context.integrationElement(quad[iq].position()) * quad[iq].weight();
const auto b = Super::coefficient(local);
thread_local std::vector<RangeType> shapeValues;
rowLocalFE.localBasis().evaluateFunction(local, shapeValues);
// the values of the shape functions on the reference element at the quadrature point
auto const& shapeValues = shapeValuesCache[iq];
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > colGradients;
using WorldVector = FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> colGradients;
colGradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], colGradients[i]);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -54,29 +55,32 @@ namespace AMDiS
using RowLocalBasisType = typename std::decay_t<decltype(rowLocalFE)>::Traits::LocalBasisType;
using ColLocalBasisType = typename std::decay_t<decltype(colLocalFE)>::Traits::LocalBasisType;
using RangeType = typename RowLocalBasisType::Traits::RangeType;
using RangeFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using JacobianType = typename ColLocalBasisType::Traits::JacobianType;
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& quad = this->getQuadratureRule(context.type(), rowNode, colNode);
for (auto const& qp : quad) {
auto const& shapeValuesCache = rowCache.evaluateFunctionAtQp(context, quad);
auto const& shapeGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
assert(jacobian.M() == Context::dim);
// The multiplicative factor in the integral transformation formula
const auto factor = context.integrationElement(qp.position()) * qp.weight();
const auto factor = context.integrationElement(quad[iq].position()) * quad[iq].weight();
const auto c = Super::coefficient(local);
thread_local std::vector<RangeType> shapeValues;
rowLocalFE.localBasis().evaluateFunction(local, shapeValues);
// the values of the shape functions on the reference element at the quadrature point
auto const& shapeValues = shapeValuesCache[iq];
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<RangeFieldType> colPartial;
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -53,31 +54,36 @@ namespace AMDiS
using RowLocalBasisType = typename std::decay_t<decltype(rowLocalFE)>::Traits::LocalBasisType;
using ColLocalBasisType = typename std::decay_t<decltype(colLocalFE)>::Traits::LocalBasisType;
using RangeType = typename RowLocalBasisType::Traits::RangeType;
using RangeFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using JacobianType = typename ColLocalBasisType::Traits::JacobianType;
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& quad = this->getQuadratureRule(context.type(), rowNode, colNode);
for (auto const& qp : quad) {
auto const& shapeValuesCache = rowCache.evaluateFunctionAtQp(context, quad);
auto const& shapeGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
thread_local std::vector<RangeType> shapeValues;
rowLocalFE.localBasis().evaluateFunction(local, shapeValues);
// the values of the shape functions on the reference element at the quadrature point
auto const& shapeValues = shapeValuesCache[iq];
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > colGradients;
using WorldVector = FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> colGradients;
colGradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], colGradients[i]);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -73,34 +74,38 @@ namespace AMDiS
using RowFieldType = typename RowLocalBasisType::Traits::RangeFieldType;
using ColFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using RowJacobianType = typename RowLocalBasisType::Traits::JacobianType;
using ColJacobianType = typename ColLocalBasisType::Traits::JacobianType;
for (auto const& qp : quad) {
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& rowGradientsCache = rowCache.evaluateJacobianAtQp(context, quad);
auto const& colGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
// The gradients of the shape functions on the reference element
thread_local std::vector<RowJacobianType> rowShapeGradients;
rowLocalFE.localBasis().evaluateJacobian(local, rowShapeGradients);
thread_local std::vector<ColJacobianType> colShapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, colShapeGradients);
auto const& rowShapeGradients = rowGradientsCache[iq];
auto const& colShapeGradients = colGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RowFieldType,Context::dow> > rowGradients;
using RowWorldVector = FieldVector<RowFieldType,Context::dow>;
thread_local std::vector<RowWorldVector> rowGradients;
rowGradients.resize(rowShapeGradients.size());
for (std::size_t i = 0; i < rowGradients.size(); ++i)
jacobian.mv(rowShapeGradients[i][0], rowGradients[i]);
thread_local std::vector<Dune::FieldVector<ColFieldType,Context::dow> > colGradients;
using ColWorldVector = FieldVector<ColFieldType,Context::dow>;
thread_local std::vector<ColWorldVector> colGradients;
colGradients.resize(colShapeGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(colShapeGradients[i][0], colGradients[i]);
......@@ -130,25 +135,28 @@ namespace AMDiS
using LocalBasisType = typename std::decay_t<decltype(localFE)>::Traits::LocalBasisType;
using RangeFieldType = typename LocalBasisType::Traits::RangeFieldType;
using JacobianType = typename LocalBasisType::Traits::JacobianType;
for (auto const& qp : quad) {
LocalBasisCache<LocalBasisType> cache(localFE.localBasis());
auto const& shapeGradientsCache = cache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
localFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > gradients;
using WorldVector = FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> gradients;
gradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], gradients[i]);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -72,26 +73,29 @@ namespace AMDiS
using LocalBasisType = typename std::decay_t<decltype(localFE)>::Traits::LocalBasisType;
using RangeFieldType = typename LocalBasisType::Traits::RangeFieldType;
using JacobianType = typename LocalBasisType::Traits::JacobianType;
for (auto const& qp : quad) {
LocalBasisCache<LocalBasisType> cache(localFE.localBasis());
auto const& shapeGradientsCache = cache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = context.integrationElement(qp.position()) * qp.weight();
const auto factor = context.integrationElement(quad[iq].position()) * quad[iq].weight();
const auto exprValue = Super::coefficient(local);
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
localFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > gradients;
using WorldVector = Dune::FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> gradients;
gradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], gradients[i]);
......@@ -135,7 +139,8 @@ namespace AMDiS
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > gradients;
using WorldVector = Dune::FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> gradients;
gradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], gradients[i]);
......@@ -168,25 +173,26 @@ namespace AMDiS
using LocalBasisType = typename std::decay_t<decltype(localFE)>::Traits::LocalBasisType;
using RangeFieldType = typename LocalBasisType::Traits::RangeFieldType;
using JacobianType = typename LocalBasisType::Traits::JacobianType;
for (auto const& qp : quad) {
LocalBasisCache<LocalBasisType> cache(localFE.localBasis());
auto const& shapeGradientsCache = cache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = context.integrationElement(qp.position()) * qp.weight();
const auto factor = context.integrationElement(quad[iq].position()) * quad[iq].weight();
const auto exprValue = Super::coefficient(local);
// The gradients of the shape functions on the reference element
thread_local std::vector<JacobianType> shapeGradients;
localFE.localBasis().evaluateJacobian(local, shapeGradients);
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > gradients;
using WorldVector = Dune::FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> gradients;
gradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], gradients[i]);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/ValueCategory.hpp>
......@@ -58,26 +59,28 @@ namespace AMDiS
using RowFieldType = typename RowLocalBasisType::Traits::RangeFieldType;
using ColFieldType = typename ColLocalBasisType::Traits::RangeFieldType;
using RowJacobianType = typename RowLocalBasisType::Traits::JacobianType;
using ColJacobianType = typename ColLocalBasisType::Traits::JacobianType;
auto const& quad = this->getQuadratureRule(context.type(), rowNode, colNode);
for (auto const& qp : quad) {
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
auto const& rowGradientsCache = rowCache.evaluateJacobianAtQp(context, quad);
auto const& colGradientsCache = colCache.evaluateJacobianAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = context.geometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const auto factor = context.integrationElement(qp.position()) * qp.weight();
const auto factor = context.integrationElement(quad[iq].position()) * quad[iq].weight();
const auto c = Super::coefficient(local);
// The gradients of the shape functions on the reference element
thread_local std::vector<RowJacobianType> rowShapeGradients;
rowLocalFE.localBasis().evaluateJacobian(local, rowShapeGradients);
thread_local std::vector<ColJacobianType> colShapeGradients;
colLocalFE.localBasis().evaluateJacobian(local, colShapeGradients);
auto const& rowShapeGradients = rowGradientsCache[iq];
auto const& colShapeGradients = colGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<RowFieldType> rowPartial;
......
......@@ -4,6 +4,7 @@
#include <vector>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/common/ValueCategory.hpp>
namespace AMDiS
......@@ -65,8 +66,6 @@ namespace AMDiS
auto const& shapeGradientsCache = velocityCache.evaluateJacobianAtQp(context, quad);
auto const& pressureValuesCache = pressureCache.evaluateFunctionAtQp(context, quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(quad[iq].position());
......@@ -81,7 +80,8 @@ namespace AMDiS
auto const& shapeGradients = shapeGradientsCache[iq];
// Compute the shape function gradients on the real element
thread_local std::vector<Dune::FieldVector<RangeFieldType,Context::dow> > gradients;
using WorldVector = Dune::FieldVector<RangeFieldType,Context::dow>;
thread_local std::vector<WorldVector> gradients;
gradients.resize(shapeGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(shapeGradients[i][0], gradients[i]);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/common/ValueCategory.hpp>
namespace AMDiS
......@@ -66,34 +67,28 @@ namespace AMDiS
using RowLocalBasisType = typename std::decay_t<decltype(rowLocalFE)>::Traits::LocalBasisType;
using ColLocalBasisType = typename std::decay_t<decltype(colLocalFE)>::Traits::LocalBasisType;
using RowRangeType = typename RowLocalBasisType::Traits::RangeType;
using ColRangeType = typename ColLocalBasisType::Traits::RangeType;
LocalBasisCache<RowLocalBasisType> rowCache(rowLocalFE.localBasis());
LocalBasisCache<ColLocalBasisType> colCache(colLocalFE.localBasis());
thread_local std::vector<RowRangeType> rowShapeValueBuffer;
thread_local std::vector<ColRangeType> colShapeValueBuffer;
const bool sameFE = std::is_same<decltype(rowLocalFE),decltype(colLocalFE)>::value;
auto* rowShapeValues = &rowShapeValueBuffer;
auto* colShapeValues = (sameFE ? &rowShapeValueBuffer : &colShapeValueBuffer);
for (auto const& qp : quad) {
auto const& rowShapeValuesCache = rowCache.evaluateFunctionAtQp(context,quad);
auto const& colShapeValuesCache = colCache.evaluateFunctionAtQp(context,quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
rowLocalFE.localBasis().evaluateFunction(local, rowShapeValueBuffer);
if (!sameFE)
colLocalFE.localBasis().evaluateFunction(local, colShapeValueBuffer);
auto const& rowShapeValues = rowShapeValuesCache[iq];
auto const& colShapeValues = colShapeValuesCache[iq];
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
const auto local_i = rowNode.localIndex(i);
const auto value = factor * (*rowShapeValues)[i];
const auto value = factor * rowShapeValues[i];
for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
const auto local_j = colNode.localIndex(j);
elementMatrix[local_i][local_j] += value * (*colShapeValues)[j];
elementMatrix[local_i][local_j] += value * colShapeValues[j];
}
}
}
......@@ -114,17 +109,17 @@ namespace AMDiS
auto const& localFE = node.finiteElement();
using LocalBasisType = typename std::decay_t<decltype(localFE)>::Traits::LocalBasisType;
using RangeType = typename LocalBasisType::Traits::RangeType;
LocalBasisCache<LocalBasisType> cache(localFE.localBasis());
for (auto const& qp : quad) {
auto const& shapeValuesCache = cache.evaluateFunctionAtQp(context,quad);
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) local = context.local(qp.position());
decltype(auto) local = context.local(quad[iq].position());
// The multiplicative factor in the integral transformation formula
const auto factor = Super::coefficient(local) * context.integrationElement(qp.position()) * qp.weight();
const auto factor = Super::coefficient(local) * context.integrationElement(quad[iq].position()) * quad[iq].weight();
thread_local std::vector<RangeType> shapeValues;
localFE.localBasis().evaluateFunction(local, shapeValues);
auto const& shapeValues = shapeValuesCache[iq];
for (std::size_t i = 0; i < localFE.size(); ++i) {
const auto local_i = node.localIndex(i);
......
......@@ -3,6 +3,7 @@
#include <type_traits>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/LocalBasisCache.hpp>
#include <amdis/common/ValueCategory.hpp>