Commit 30debe8f authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

several changes in integrate routines of DOFVectors

parent 63c967c1
...@@ -8,8 +8,8 @@ SET(SOURCE_DIR ${AMDIS_SOURCE_DIR}/src) ...@@ -8,8 +8,8 @@ SET(SOURCE_DIR ${AMDIS_SOURCE_DIR}/src)
#TODO: use the cmake build type #TODO: use the cmake build type
SET(MTL_INCLUDE_DIR ${LIB_DIR}/mtl4/ CACHE PATH "mtl4 directory") SET(MTL_INCLUDE_DIR ${LIB_DIR}/mtl4/ CACHE PATH "mtl4 directory")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -Wall -DDEBUG=0") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -Wall -Wno-unused-but-set-variable -DDEBUG=0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -DDEBUG=1 -O0") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wno-unused-but-set-variable -DDEBUG=1 -O0")
if(NOT CurrentRevision) if(NOT CurrentRevision)
find_package(Subversion) find_package(Subversion)
if(Subversion_FOUND) if(Subversion_FOUND)
......
...@@ -714,193 +714,6 @@ namespace AMDiS { ...@@ -714,193 +714,6 @@ namespace AMDiS {
} }
double integrate(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct)
{
if (vec1.getFeSpace()->getMesh() == vec2.getFeSpace()->getMesh())
return intSingleMesh(vec1, vec2, fct);
else
return intDualMesh(vec1, vec2, fct);
}
double intSingleMesh(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct)
{
FUNCNAME("intDualmesh()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(),
2 * vec1.getFeSpace()->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<double> qp1(fastQuad->getNumPoints());
mtl::dense_vector<double> qp2(fastQuad->getNumPoints());
double value = 0.0;
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(vec1.getFeSpace()->getMesh(), -1, traverseFlag);
while (elInfo) {
vec1.getVecAtQPs(elInfo, quad, fastQuad, qp1);
vec2.getVecAtQPs(elInfo, quad, fastQuad, qp2);
double tmp = 0.0;
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++)
tmp += fastQuad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]);
value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double localValue = value;
MPI::COMM_WORLD.Allreduce(&localValue, &value, 1, MPI_DOUBLE, MPI_SUM);
#endif
return value;
}
double intDualMesh(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct)
{
FUNCNAME("intDualmesh()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(),
2 * vec1.getFeSpace()->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<double> qp1(fastQuad->getNumPoints());
mtl::dense_vector<double> qp2(fastQuad->getNumPoints());
double value = 0.0;
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
DualTraverse dualTraverse;
DualElInfo dualElInfo;
bool cont = dualTraverse.traverseFirst(vec1.getFeSpace()->getMesh(),
vec2.getFeSpace()->getMesh(),
-1, -1, traverseFlag, traverseFlag,
dualElInfo);
while (cont) {
vec1.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp1);
vec2.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp2);
double tmp = 0.0;
for (int iq = 0; iq < quad->getNumPoints(); iq++)
tmp += quad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]);
value += tmp * dualElInfo.smallElInfo->getDet();
cont = dualTraverse.traverseNext(dualElInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double localValue = value;
MPI::COMM_WORLD.Allreduce(&localValue, &value, 1, MPI_DOUBLE, MPI_SUM);
#endif
return value;
}
double integrate(const DOFVector<double> &vec,
AbstractFunction<double, WorldVector<double> > *fct)
{
FUNCNAME("integrate()");
TEST_EXIT(fct)("No function defined!\n");
const FiniteElemSpace *feSpace = vec.getFeSpace();
Mesh *mesh = feSpace->getMesh();
int deg = std::max(fct->getDegree(), 2 * feSpace->getBasisFcts()->getDegree());
Quadrature* quad = Quadrature::provideQuadrature(mesh->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(feSpace->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<double> qp(fastQuad->getNumPoints());
WorldVector<double> coords;
double value = 0.0;
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag);
while (elInfo) {
vec.getVecAtQPs(elInfo, quad, fastQuad, qp);
double tmp = 0.0;
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) {
elInfo->coordToWorld(fastQuad->getLambda(iq), coords);
tmp += fastQuad->getWeight(iq) * (qp[iq] * (*fct)(coords));
}
value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double localValue = value;
MPI::COMM_WORLD.Allreduce(&localValue, &value, 1, MPI_DOUBLE, MPI_SUM);
#endif
return value;
}
double integrate(const FiniteElemSpace* feSpace,
AbstractFunction<double, WorldVector<double> > *fct)
{
FUNCNAME("integrate()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(), feSpace->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(feSpace->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(feSpace->getBasisFcts(), *quad, INIT_PHI);
WorldVector<double> coords;
double value = 0.0;
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(feSpace->getMesh(), -1, traverseFlag);
while (elInfo) {
double tmp = 0.0;
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) {
elInfo->coordToWorld(fastQuad->getLambda(iq), coords);
tmp += fastQuad->getWeight(iq) * (*fct)(coords);
}
value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double localValue = value;
MPI::COMM_WORLD.Allreduce(&localValue, &value, 1, MPI_DOUBLE, MPI_SUM);
#endif
return value;
}
double integrateGeneral(const std::vector<DOFVector<double>*> &vecs, double integrateGeneral(const std::vector<DOFVector<double>*> &vecs,
AbstractFunction<double, std::vector<double> > *fct) AbstractFunction<double, std::vector<double> > *fct)
{ {
......
...@@ -873,45 +873,88 @@ namespace AMDiS { ...@@ -873,45 +873,88 @@ namespace AMDiS {
std::vector<DOFVector<double>*> *transform(DOFVector<typename GradientType<T>::type> *vec, std::vector<DOFVector<double>*> *transform(DOFVector<typename GradientType<T>::type> *vec,
std::vector<DOFVector<double>*> *res); std::vector<DOFVector<double>*> *res);
/// Computes the integral: \f$ \int f(\vec{x})\,\text{d}\vec{x}\f$
template<typename TOut>
TOut integrate_Coords(const FiniteElemSpace* feSpace,
AbstractFunction<TOut, WorldVector<double> > *fct);
template<typename TOut>
TOut integrate(const FiniteElemSpace* feSpace,
AbstractFunction<TOut, WorldVector<double> > *fct)
{
return integrate_Coords(feSpace, fct);
}
/// Computes the integral: \f$ \int f(v(\vec{x}))\,\text{d}\vec{x}\f$
template<typename TOut, typename T>
TOut integrate_Vec(const DOFVector<T> &vec,
AbstractFunction<TOut, T> *fct);
template<typename TOut, typename T>
TOut integrate(const DOFVector<T> &vec,
AbstractFunction<TOut, T> *fct)
{
return integrate_Vec(vec, fct);
}
/** \brief /** \brief
* Computes the integral of a function that includes two different DOFVectors. This * Computes the integral of a function that includes two different DOFVectors:
* function works also for the case that the DOFVectors are defined on two different * \f$ \int f(v(\vec{x}), w(\vec{x}))\,\text{d}\vec{x}\f$
* This function works also for the case that the DOFVectors are defined on two different
* meshes. * meshes.
*/ */
double integrate(const DOFVector<double> &vec1, template<typename TOut, typename T1, typename T2>
const DOFVector<double> &vec2, TOut integrate_Vec2(const DOFVector<T1> &vec1,
BinaryAbstractFunction<double, double, double> *fct); const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct);
template<typename TOut, typename T1, typename T2>
TOut integrate(const DOFVector<T1> &vec1,
const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct)
{
return integrate_Vec2(vec1, vec2, fct);
}
/// Computes the integral of a function with two DOFVectors defined on the same mesh. /// Computes the integral of a function with two DOFVectors defined on the same mesh.
double intSingleMesh(const DOFVector<double> &vec1, template<typename TOut, typename T1, typename T2>
const DOFVector<double> &vec2, TOut int_Vec2_SingleMesh(const DOFVector<T1> &vec1,
BinaryAbstractFunction<double, double, double> *fct); const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct);
/// Computes the integral of a function with two DOFVectors defined on different meshes. /// Computes the integral of a function with two DOFVectors defined on different meshes.
double intDualMesh(const DOFVector<double> &vec1, template<typename TOut, typename T1, typename T2>
const DOFVector<double> &vec2, TOut int_Vec2_DualMesh(const DOFVector<T1> &vec1,
BinaryAbstractFunction<double, double, double> *fct); const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct);
double integrate(const DOFVector<double> &vec, /// Computes the integral: \f$ \int v(\vec{x}) f(\vec{x})\,\text{d}\vec{x}\f$
AbstractFunction<double, WorldVector<double> > *fct); template<typename T1, typename T2>
typename ProductType<T1,T2>::type integrate_VecTimesCoords(const DOFVector<T1> &vec,
AbstractFunction<T2, WorldVector<double> > *fct);
double integrate(const FiniteElemSpace* feSpace, /// Computes the integral: \f$ \int f(v(\vec{x}), \vec{x})\,\text{d}\vec{x}\f$
AbstractFunction<double, WorldVector<double> > *fct); template<typename TOut, typename T>
TOut integrate_VecAndCoords(const DOFVector<T> &vec,
BinaryAbstractFunction<TOut, T, WorldVector<double> > *fct);
template<typename TOut, typename T>
TOut integrate_VecAndCoords(const DOFVector<T> &vec,
BinaryAbstractFunction<TOut, T, WorldVector<double> > *fct)
{
return integrate(vec, fct);
}
/// Computes the integral: \f$ \int f(\{v_i(\vec{x})\}_i)\,\text{d}\vec{x}\f$
double integrateGeneral(const std::vector<DOFVector<double>*> &vecs, double integrateGeneral(const std::vector<DOFVector<double>*> &vecs,
AbstractFunction<double, std::vector<double> > *fct); AbstractFunction<double, std::vector<double> > *fct);
/// Computes the integral: \f$ \int f(\{v_i(\vec{x})\}_i,\{\nabla w_i(\vec{x})\}_i)\,\text{d}\vec{x}\f$
double integrateGeneralGradient(const std::vector<DOFVector<double>*> &vecs, double integrateGeneralGradient(const std::vector<DOFVector<double>*> &vecs,
const std::vector<DOFVector<double>*> &grds, const std::vector<DOFVector<double>*> &grds,
BinaryAbstractFunction<double, std::vector<double>, std::vector<WorldVector<double> > > *fct); BinaryAbstractFunction<double, std::vector<double>, std::vector<WorldVector<double> > > *fct);
template<typename T>
T integrate_VecAndCoords(const DOFVector<double> &vec,
BinaryAbstractFunction<T, double, WorldVector<double> > *fct);
template<typename T1, typename T2>
T2 integrate_Vec(const DOFVector<T1> &vec,
AbstractFunction<T2, T1> *fct);
} }
#include "DOFVector.hh" #include "DOFVector.hh"
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
#include "Operator.h" #include "Operator.h"
#include "Initfile.h" #include "Initfile.h"
#include "Traverse.h" #include "Traverse.h"
#include "DualTraverse.h"
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
#include "MpiHelper.h"
#endif
// Defining the interface for MTL4 // Defining the interface for MTL4
namespace mtl { namespace mtl {
...@@ -516,7 +521,7 @@ namespace AMDiS { ...@@ -516,7 +521,7 @@ namespace AMDiS {
FastQuadrature *quadFast = FastQuadrature *quadFast =
FastQuadrature::provideFastQuadrature(this->feSpace->getBasisFcts(), *q, INIT_PHI); FastQuadrature::provideFastQuadrature(this->feSpace->getBasisFcts(), *q, INIT_PHI);
double result = 0.0; T result; nullify(result);
int nPoints = quadFast->getNumPoints(); int nPoints = quadFast->getNumPoints();
mtl::dense_vector<T> uh_vec(nPoints); mtl::dense_vector<T> uh_vec(nPoints);
TraverseStack stack; TraverseStack stack;
...@@ -524,7 +529,7 @@ namespace AMDiS { ...@@ -524,7 +529,7 @@ namespace AMDiS {
Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET); Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET);
while (elInfo) { while (elInfo) {
double det = elInfo->getDet(); double det = elInfo->getDet();
double normT = 0.0; T normT; nullify(normT);
this->getVecAtQPs(elInfo, NULL, quadFast, uh_vec); this->getVecAtQPs(elInfo, NULL, quadFast, uh_vec);
for (int iq = 0; iq < nPoints; iq++) for (int iq = 0; iq < nPoints; iq++)
normT += quadFast->getWeight(iq) * (uh_vec[iq]); normT += quadFast->getWeight(iq) * (uh_vec[iq]);
...@@ -534,18 +539,58 @@ namespace AMDiS { ...@@ -534,18 +539,58 @@ namespace AMDiS {
} }
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double localResult = result; mpi::globalAdd(result);
MPI::COMM_WORLD.Allreduce(&localResult, &result, 1, MPI_DOUBLE, MPI_SUM);
#endif #endif
return result; return result;
} }
template<typename T>
T integrate_VecAndCoords(const DOFVector<double> &vec, template<typename TOut>
BinaryAbstractFunction<T, double, WorldVector<double> > *fct) TOut integrate_Coords(const FiniteElemSpace* feSpace,
AbstractFunction<TOut, WorldVector<double> > *fct)
{ {
FUNCNAME("integrate_VecAndCoords()"); FUNCNAME("integrate_Coords()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(), feSpace->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(feSpace->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(feSpace->getBasisFcts(), *quad, INIT_PHI);
WorldVector<double> coords;
TOut value; nullify(value);
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(feSpace->getMesh(), -1, traverseFlag);
while (elInfo) {
TOut tmp; nullify(tmp);
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) {
elInfo->coordToWorld(fastQuad->getLambda(iq), coords);
tmp += fastQuad->getWeight(iq) * (*fct)(coords);
}
value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
mpi::globalAdd(value);
#endif
return value;
}
template<typename TOut, typename T>
TOut integrate_Vec(const DOFVector<T> &vec,
AbstractFunction<TOut, T> *fct)
{
FUNCNAME("integrate_Vec()");
TEST_EXIT(fct)("No function defined!\n"); TEST_EXIT(fct)("No function defined!\n");
...@@ -556,39 +601,184 @@ namespace AMDiS { ...@@ -556,39 +601,184 @@ namespace AMDiS {
FastQuadrature *fastQuad = FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(vec.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); FastQuadrature::provideFastQuadrature(vec.getFeSpace()->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<double> qp(fastQuad->getNumPoints()); mtl::dense_vector<T> qp(fastQuad->getNumPoints());
WorldVector<double> coordsAtQP;
T value; TOut value; nullify(value);
nullify(value);
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(vec.getFeSpace()->getMesh(), -1, traverseFlag); ElInfo *elInfo = stack.traverseFirst(vec.getFeSpace()->getMesh(), -1, traverseFlag);
while (elInfo) { while (elInfo) {
vec.getVecAtQPs(elInfo, quad, fastQuad, qp); vec.getVecAtQPs(elInfo, quad, fastQuad, qp);
T tmp; TOut tmp; nullify(tmp);
nullify(tmp);
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) { for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) {
elInfo->coordToWorld(fastQuad->getLambda(iq), coordsAtQP); tmp += fastQuad->getWeight(iq) * (*fct)(qp[iq]);
tmp += fastQuad->getWeight(iq) * (*fct)(qp[iq], coordsAtQP);
} }
value += tmp * elInfo->getDet(); value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
} }
// #ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
// double localValue = value; mpi::globalAdd(value);
// MPI::COMM_WORLD.Allreduce(&localValue, &value, 1, MPI_DOUBLE, MPI_SUM); #endif
// #endif
return value; return value;
} }
template<typename TOut, typename T1, typename T2>
TOut integrate_Vec2(const DOFVector<T1> &vec1,
const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct)
{
if (vec1.getFeSpace()->getMesh() == vec2.getFeSpace()->getMesh())
return int_Vec2_SingleMesh(vec1, vec2, fct);
else
return int_Vec2_DualMesh(vec1, vec2, fct);
}
template<typename TOut, typename T1, typename T2>
TOut int_Vec2_SingleMesh(const DOFVector<T1> &vec1,
const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct)
{
FUNCNAME("intDualmesh()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(),
2 * vec1.getFeSpace()->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<T1> qp1(fastQuad->getNumPoints());
mtl::dense_vector<T2> qp2(fastQuad->getNumPoints());
TOut value; nullify(value);
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(vec1.getFeSpace()->getMesh(), -1, traverseFlag);
while (elInfo) {
vec1.getVecAtQPs(elInfo, quad, fastQuad, qp1);
vec2.getVecAtQPs(elInfo, quad, fastQuad, qp2);
TOut tmp; nullify(tmp);
for (int iq = 0; iq < fastQuad->getNumPoints(); iq++)
tmp += fastQuad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]);
value += tmp * elInfo->getDet();
elInfo = stack.traverseNext(elInfo);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
mpi::globalAdd(value);
#endif
return value;
}
template<typename TOut, typename T1, typename T2>
TOut int_Vec2_DualMesh(const DOFVector<T1> &vec1,
const DOFVector<T2> &vec2,
BinaryAbstractFunction<TOut, T1, T2> *fct)
{
FUNCNAME("intDualmesh()");
TEST_EXIT(fct)("No function defined!\n");
int deg = std::max(fct->getDegree(),
2 * vec1.getFeSpace()->getBasisFcts()->getDegree());
Quadrature* quad =
Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg);
FastQuadrature *fastQuad =
FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI);
mtl::dense_vector<T1> qp1(fastQuad->getNumPoints());
mtl::dense_vector<T2> qp2(fastQuad->getNumPoints());
TOut value; nullify(value);
Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET;
DualTraverse dualTraverse;
DualElInfo dualElInfo;
bool cont = dualTraverse.traverseFirst(vec1.getFeSpace()->getMesh(),
vec2.getFeSpace()->getMesh(),
-1, -1, traverseFlag, traverseFlag,
dualElInfo);
while (cont) {
vec1.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp1);
vec2.</