Commit 301640ea authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

some examples modified to make it running

parent 5c70d545
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <dune/common/fmatrix.hh> #include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh> #include <dune/common/fvector.hh>
#include <dune/amdis/DirichletBC.hpp>
#include <dune/amdis/LinearAlgebra.hpp> #include <dune/amdis/LinearAlgebra.hpp>
#include <dune/amdis/Operator.hpp> #include <dune/amdis/Operator.hpp>
#include <dune/amdis/common/Mpl.hpp> #include <dune/amdis/common/Mpl.hpp>
...@@ -23,10 +24,12 @@ namespace AMDiS ...@@ -23,10 +24,12 @@ namespace AMDiS
/// Constructor, stores a shared-pointer to the feSpaces /// Constructor, stores a shared-pointer to the feSpaces
Assembler(GlobalBasis& globalBasis, Assembler(GlobalBasis& globalBasis,
MatrixOperators<GlobalBasis>& matrixOperators, MatrixOperators<GlobalBasis>& matrixOperators,
VectorOperators<GlobalBasis>& rhsOperators) VectorOperators<GlobalBasis>& rhsOperators,
Constraints<GlobalBasis>& constraints)
: globalBasis_(globalBasis) : globalBasis_(globalBasis)
, matrixOperators_(matrixOperators) , matrixOperators_(matrixOperators)
, rhsOperators_(rhsOperators) , rhsOperators_(rhsOperators)
, constraints_(constraints)
{} {}
void update(GridView const& gv) void update(GridView const& gv)
...@@ -88,6 +91,7 @@ namespace AMDiS ...@@ -88,6 +91,7 @@ namespace AMDiS
GlobalBasis& globalBasis_; GlobalBasis& globalBasis_;
MatrixOperators<GlobalBasis>& matrixOperators_; MatrixOperators<GlobalBasis>& matrixOperators_;
VectorOperators<GlobalBasis>& rhsOperators_; VectorOperators<GlobalBasis>& rhsOperators_;
Constraints<GlobalBasis>& constraints_;
}; };
} // end namespace AMDiS } // end namespace AMDiS
......
#pragma once #pragma once
#include <dune/functions/functionspacebases/subspacebasis.hh> #include <dune/functions/functionspacebases/subspacebasis.hh>
#include <dune/typetree/treepath.hh> #include <dune/amdis/utility/TreePath.hpp>
#include <dune/amdis/utility/Visitor.hpp> #include <dune/amdis/utility/Visitor.hpp>
namespace AMDiS { namespace AMDiS {
...@@ -64,15 +64,19 @@ void Assembler<GlobalBasis>::assemble( ...@@ -64,15 +64,19 @@ void Assembler<GlobalBasis>::assemble(
for (std::size_t i = 0; i < localView.size(); ++i) { for (std::size_t i = 0; i < localView.size(); ++i) {
auto const row = localIndexSet.index(i); auto const row = localIndexSet.index(i);
for (std::size_t j = 0; j < localView.size(); ++j) { for (std::size_t j = 0; j < localView.size(); ++j) {
auto const col = localIndexSet.index(j); if (elementMatrix(i,j) != 0.0) {
matrix(row,col) += elementMatrix(i,j); auto const col = localIndexSet.index(j);
matrix(row,col) += elementMatrix(i,j);
}
} }
} }
// add element-vector to system-vector // add element-vector to system-vector
for (std::size_t i = 0; i < localView.size(); ++i) { for (std::size_t i = 0; i < localView.size(); ++i) {
auto const idx = localIndexSet.index(i); if (elementVector[i] != 0.0) {
rhs[idx] += elementVector[i]; auto const idx = localIndexSet.index(i);
rhs[idx] += elementVector[i];
}
} }
localIndexSet.unbind(); localIndexSet.unbind();
...@@ -86,43 +90,6 @@ void Assembler<GlobalBasis>::assemble( ...@@ -86,43 +90,6 @@ void Assembler<GlobalBasis>::assemble(
} }
template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType>
void Assembler<GlobalBasis>::initMatrixVector(
SystemMatrixType& matrix,
SystemVectorType& solution,
SystemVectorType& rhs,
bool asmMatrix, bool asmVector) const
{
matrix.init(asmMatrix);
solution.compress();
rhs.compress();
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
if (rowNode.isLeaf)
msg(0, " DOFs for Basis[", 1, "]"); // TODO: add right values
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
if (rhsOperators_[rowNode].assemble(asmVector))
rhsOperators_[rowNode].init(rowBasis);
forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
if (matrixOperators_[rowNode][colNode].assemble(asmMatrix))
matrixOperators_[rowNode][colNode].init(rowBasis, colBasis);
// init boundary condition
// for (int c = 0; c < nComponents; ++c)
// for (auto bc : matrixOperators[R][c].dirichlet)
// bc->init(c == C, matrix(_r, _c), solution[_c], rhs[_r]);
});
});
}
template <class GlobalBasis> template <class GlobalBasis>
template <class ElementContainer, class Container, class Operators, class... LocalViews> template <class ElementContainer, class Container, class Operators, class... LocalViews>
void Assembler<GlobalBasis>::assembleElementOperators( void Assembler<GlobalBasis>::assembleElementOperators(
...@@ -160,6 +127,44 @@ void Assembler<GlobalBasis>::assembleElementOperators( ...@@ -160,6 +127,44 @@ void Assembler<GlobalBasis>::assembleElementOperators(
} }
template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType>
void Assembler<GlobalBasis>::initMatrixVector(
SystemMatrixType& matrix,
SystemVectorType& solution,
SystemVectorType& rhs,
bool asmMatrix, bool asmVector) const
{
matrix.init(asmMatrix);
solution.compress();
rhs.compress();
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
if (rowNode.isLeaf)
msg(0, " DOFs for Basis[", to_string(rowTreePath), "]"); // TODO: add right values
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
if (rhsOperators_[rowNode].assemble(asmVector))
rhsOperators_[rowNode].init(rowBasis);
forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
if (matrixOperators_[rowNode][colNode].assemble(asmMatrix))
matrixOperators_[rowNode][colNode].init(rowBasis, colBasis);
for (auto bc : constraints_[rowNode][colNode].scalar)
bc->init(matrix, solution, rhs, rowBasis, colBasis);
for (auto bc : constraints_[rowNode][colNode].vector)
bc->init(matrix, solution, rhs, rowBasis, colBasis);
});
});
msg(globalBasis_.dimension(), " total DOFs");
}
template <class GlobalBasis> template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType> template <class SystemMatrixType, class SystemVectorType>
std::size_t Assembler<GlobalBasis>::finishMatrixVector( std::size_t Assembler<GlobalBasis>::finishMatrixVector(
...@@ -171,27 +176,25 @@ std::size_t Assembler<GlobalBasis>::finishMatrixVector( ...@@ -171,27 +176,25 @@ std::size_t Assembler<GlobalBasis>::finishMatrixVector(
matrix.finish(); matrix.finish();
auto localView = globalBasis_.localView(); auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto /*rowTreePath*/) forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{ {
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
auto& rhsOp = rhsOperators_[rowNode]; auto& rhsOp = rhsOperators_[rowNode];
if (rhsOp.assemble(asmVector)) if (rhsOp.assemble(asmVector))
rhsOp.assembled = true; rhsOp.assembled = true;
forEachNode(localView.tree(), [&,this](auto const& colNode, auto /*colTreePath*/) forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{ {
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
auto& matOp = matrixOperators_[rowNode][colNode]; auto& matOp = matrixOperators_[rowNode][colNode];
if (matOp.assemble(asmMatrix)) if (matOp.assemble(asmMatrix))
matOp.assembled = true; matOp.assembled = true;
// finish boundary condition // finish boundary condition
// for (int c = 0; c < nComponents; ++c) { for (auto bc : constraints_[rowNode][colNode].scalar)
// for (int r = 0; r < nComponents; ++r) { bc->finish(matrix, solution, rhs, rowBasis, colBasis);
// if (r != R && c != C) for (auto bc : constraints_[rowNode][colNode].vector)
// continue; bc->finish(matrix, solution, rhs, rowBasis, colBasis);
// for (auto bc : matrixOperators[r][c].dirichlet)
// bc->finish(r == R, c == C, matrix(_r, _c), solution[_c], rhs[_r]);
// }
// }
}); });
}); });
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/Output.hpp> #include <dune/amdis/Output.hpp>
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/utility/TreeData.hpp>
namespace AMDiS namespace AMDiS
{ {
...@@ -25,13 +25,13 @@ namespace AMDiS ...@@ -25,13 +25,13 @@ namespace AMDiS
* support this symmetric modification. As a result, this method returns a list * support this symmetric modification. As a result, this method returns a list
* of columns values, that should be subtracted from the rhs. * of columns values, that should be subtracted from the rhs.
**/ **/
template <class WorldVector> template <class Domain, class Range = double>
class DirichletBC class DirichletBC
{ {
public: public:
template <class Predicate, class Values, template <class Predicate, class Values,
REQUIRES(Concepts::Functor<Predicate, bool(WorldVector)> && REQUIRES(Concepts::Functor<Predicate, bool(Domain)> &&
Concepts::Functor<Values, double(WorldVector)>) > Concepts::Functor<Values, Range(Domain)>) >
DirichletBC(Predicate&& predicate, Values&& values) DirichletBC(Predicate&& predicate, Values&& values)
: predicate(std::forward<Predicate>(predicate)) : predicate(std::forward<Predicate>(predicate))
, values(std::forward<Values>(values)) , values(std::forward<Values>(values))
...@@ -41,11 +41,15 @@ namespace AMDiS ...@@ -41,11 +41,15 @@ namespace AMDiS
/// Prepare the matrix, rhs and solution block for assembling dirichlet /// Prepare the matrix, rhs and solution block for assembling dirichlet
/// boundary conditions, e.g. collect the corresponding indices of boundary /// boundary conditions, e.g. collect the corresponding indices of boundary
/// DOFS for later elimination in \ref finish. /// DOFS for later elimination in \ref finish.
template <class Matrix, class VectorX, class VectorB> template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void init(bool apply, void init(Matrix& /*matrix*/, VectorX& /*rhs*/, VectorB& /*solution*/,
Matrix& matrix, RowBasis const& rowBasis,
VectorX& rhs, ColBasis const& /*colBasis*/)
VectorB& solution); {
using RowNode = typename RowBasis::LocalView::Tree;
initImpl(rowBasis, typename RowNode::NodeTag{});
}
/// \brief Apply dirichlet BC to matrix and vector, i.e., add a unit-row /// \brief Apply dirichlet BC to matrix and vector, i.e., add a unit-row
...@@ -55,21 +59,51 @@ namespace AMDiS ...@@ -55,21 +59,51 @@ namespace AMDiS
* is assembled. The \p matrix, \p rhs, and \p solution correspond to the * is assembled. The \p matrix, \p rhs, and \p solution correspond to the
* currently visited blocks of system-matrix and system-vector. * currently visited blocks of system-matrix and system-vector.
**/ **/
template <class Matrix, class VectorX, class VectorB> template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void finish(bool apply_row, void finish(Matrix& matrix,
bool apply_col,
Matrix& matrix,
VectorX& rhs, VectorX& rhs,
VectorB& solution); VectorB& solution,
RowBasis const& rowBasis,
ColBasis const& colBasis);
protected:
template <class RowBasis>
void initImpl(RowBasis const& rowBasis, Dune::TypeTree::LeafNodeTag);
template <class RowBasis>
void initImpl(RowBasis const& rowBasis, Dune::TypeTree::PowerNodeTag);
template <class RB, class RowNodeTag>
void initImpl(RB const&, RowNodeTag) {}
private: private:
std::function<bool(WorldVector)> predicate; std::function<bool(Domain)> predicate;
std::function<double(WorldVector)> values; std::function<Range(Domain)> values;
bool initialized = false; bool initialized = false;
std::vector<char> dirichletNodes; std::vector<char> dirichletNodes;
}; };
template <class GlobalBasis>
struct DirichletData
{
using WorldVector = typename GlobalBasis::GridView::template Codim<0>::Geometry::GlobalCoordinate;
template <class Node>
struct type
{
std::list<std::shared_ptr<DirichletBC<WorldVector, double>>> scalar;
std::list<std::shared_ptr<DirichletBC<WorldVector, WorldVector>>> vector;
void push_back(std::shared_ptr<DirichletBC<WorldVector, double>> const& bc) { scalar.push_back(bc); }
void push_back(std::shared_ptr<DirichletBC<WorldVector, WorldVector>> const& bc) { vector.push_back(bc); }
};
};
template <class GlobalBasis>
using Constraints = MatrixData<GlobalBasis, DirichletData<GlobalBasis>::template type>;
} // end namespace AMDiS } // end namespace AMDiS
#include "DirichletBC.inc.hpp" #include "DirichletBC.inc.hpp"
#pragma once #pragma once
#include <dune/functions/functionspacebases/interpolate.hh> #include <dune/functions/functionspacebases/interpolate.hh>
#include <dune/functions/functionspacebases/subspacebasis.hh>
#include <dune/amdis/LinearAlgebra.hpp> #include <dune/amdis/LinearAlgebra.hpp>
#include <dune/amdis/linear_algebra/HierarchicWrapper.hpp>
namespace AMDiS namespace AMDiS
{ {
template <class WorldVector> template <class WorldVector, class Range>
template <class Matrix, class VectorX, class VectorB> template <class RowBasis>
void DirichletBC<WorldVector>::init(bool /*apply*/, void DirichletBC<WorldVector, Range>::initImpl(
Matrix& matrix, RowBasis const& rowBasis, Dune::TypeTree::LeafNodeTag)
VectorX& /*solution*/,
VectorB& /*rhs*/)
{ {
using Dune::Functions::interpolate; using Dune::Functions::interpolate;
if (!initialized) { if (!initialized) {
interpolate(matrix.getRowFeSpace(), dirichletNodes, predicate); interpolate(rowBasis, hierarchicVectorWrapper(dirichletNodes), predicate);
initialized = true; initialized = true;
} }
} }
template <class WorldVector, class Range>
template <class RowBasis>
void DirichletBC<WorldVector, Range>::initImpl(
RowBasis const& rowBasis, Dune::TypeTree::PowerNodeTag)
{
using Dune::Functions::interpolate;
template <class WorldVector> if (!initialized) {
template <class Matrix, class VectorX, class VectorB> auto tp = rowBasis.prefixPath();
void DirichletBC<WorldVector>::finish(bool apply_row, auto const& basis = rowBasis.rootBasis();
bool apply_col, for (std::size_t i = 0; i < degree(rowBasis.localView().tree()); ++i)
Matrix& matrix, interpolate(Dune::Functions::subspaceBasis(basis, push_back(tp,i)),
VectorX& solution, hierarchicVectorWrapper(dirichletNodes), predicate);
VectorB& rhs) initialized = true;
}
}
template <class WorldVector, class Range>
template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void DirichletBC<WorldVector, Range>::finish(
Matrix& matrix, VectorX& solution, VectorB& rhs,
RowBasis const& rowBasis, ColBasis const& colBasis)
// Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag)
{ {
using Dune::Functions::interpolate; using Dune::Functions::interpolate;
test_exit_dbg(initialized, "Boundary condition not initialized!"); test_exit_dbg(initialized, "Boundary condition not initialized!");
auto columns = matrix.applyDirichletBC(dirichletNodes, apply_row, apply_col); auto columns = matrix.applyDirichletBC(dirichletNodes);
if (apply_col) { interpolate(rowBasis, hierarchicVectorWrapper(rhs.getVector()), values, hierarchicVectorWrapper(dirichletNodes));
interpolate(matrix.getRowFeSpace(), wrapper(rhs.getVector()), values, dirichletNodes); interpolate(colBasis, hierarchicVectorWrapper(solution.getVector()), values, hierarchicVectorWrapper(dirichletNodes));
if (apply_row)
interpolate(matrix.getColFeSpace(), wrapper(solution.getVector()), values, dirichletNodes);
// subtract columns of dirichlet nodes from rhs // subtract columns of dirichlet nodes from rhs
for (auto const& triplet : columns) for (auto const& triplet : columns)
rhs[triplet.row] -= triplet.value * solution[triplet.col]; rhs[triplet.row] -= triplet.value * solution[triplet.col];
}
} }
......
...@@ -60,19 +60,17 @@ namespace AMDiS ...@@ -60,19 +60,17 @@ namespace AMDiS
template <class Operator, class RowView, class ColView> template <class Operator, class RowView, class ColView>
void calculateElementMatrix(Operator& op, void calculateElementMatrix(Operator& op,
RowView const& rowView, RowView const& rowView, ColView const& colView,
ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix,
double fac, double fac,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PHI>) FirstOrderType_t<GRD_PHI>)
{ {
auto geometry = rowView.element().geometry(); auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry(); auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); auto const& rowLocalFE = rowView.tree().finiteElement();
auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); auto const& colLocalFE = colView.tree().finiteElement();
auto const& quad = Super::getQuadrature().getRule(); auto const& quad = Super::getQuadrature().getRule();
for (std::size_t iq = 0; iq < quad.size(); ++iq) { for (std::size_t iq = 0; iq < quad.size(); ++iq) {
...@@ -86,11 +84,11 @@ namespace AMDiS ...@@ -86,11 +84,11 @@ namespace AMDiS
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac; const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
std::vector<Dune::FieldVector<double,1> > rowShapeValues; std::vector<Dune::FieldVector<double,1> > rowShapeValues;
rowLocalBasis.evaluateFunction(quadPos, rowShapeValues); rowLocalFE.localBasis().evaluateFunction(quadPos, rowShapeValues);
// The gradients of the shape functions on the reference element // The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > colReferenceGradients; std::vector<Dune::FieldMatrix<double,1,dim> > colReferenceGradients;
colLocalBasis.evaluateJacobian(quadPos, colReferenceGradients); colLocalFE.localBasis().evaluateJacobian(quadPos, colReferenceGradients);
// Compute the shape function gradients on the real element // Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size()); std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size());
...@@ -98,8 +96,8 @@ namespace AMDiS ...@@ -98,8 +96,8 @@ namespace AMDiS
for (std::size_t i = 0; i < colGradients.size(); ++i) for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(colReferenceGradients[i][0], colGradients[i]); jacobian.mv(colReferenceGradients[i][0], colGradients[i]);
for (std::size_t i = 0; i < num_rows(elementMatrix); ++i) { for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
for (std::size_t j = 0; j < num_cols(elementMatrix); ++j) { for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
const int local_i = rowView.tree().localIndex(i); const int local_i = rowView.tree().localIndex(i);
const int local_j = colView.tree().localIndex(j); const int local_j = colView.tree().localIndex(j);
op.evalFot1(elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j]); op.evalFot1(elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j]);
...@@ -110,19 +108,17 @@ namespace AMDiS ...@@ -110,19 +108,17 @@ namespace AMDiS
template <class Operator, class RowView, class ColView> template <class Operator, class RowView, class ColView>
void calculateElementMatrix(Operator& op, void calculateElementMatrix(Operator& op,
RowView const& rowView, RowView const& rowView, ColView const& colView,
ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix,
double fac, double fac,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>) FirstOrderType_t<GRD_PSI>)
{ {
auto geometry = rowView.element().geometry(); auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry(); auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); auto const& rowLocalFE = rowView.tree().finiteElement();
auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); auto const& colLocalFE = colView.tree().finiteElement();
auto const& quad = Super::getQuadrature().getRule(); auto const& quad = Super::getQuadrature().getRule();
for (std::size_t iq = 0; iq < quad.size(); ++iq) { for (std::size_t iq = 0; iq < quad.size(); ++iq) {
...@@ -137,7 +133,7 @@ namespace AMDiS ...@@ -137,7 +133,7 @@ namespace AMDiS
// The gradients of the shape functions on the reference element // The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients; std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients;
rowLocalBasis.evaluateJacobian(quadPos, rowReferenceGradients); rowLocalFE.localBasis().evaluateJacobian(quadPos, rowReferenceGradients);
// Compute the shape function gradients on the real element // Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size()); std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
...@@ -146,10 +142,10 @@ namespace AMDiS ...@@ -146,10 +142,10 @@ namespace AMDiS
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]); jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
std::vector<Dune::FieldVector<double,1> > colShapeValues; std::vector<Dune::FieldVector<double,1> > colShapeValues;
colLocalBasis.evaluateFunction(quadPos, colShapeValues); colLocalFE.localBasis().evaluateFunction(quadPos, colShapeValues);