From 30debe8f18725a439c472a7858a4ab6392e71d0f Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Fri, 24 Feb 2012 23:13:34 +0000 Subject: [PATCH] several changes in integrate routines of DOFVectors --- AMDiS/CMakeLists.txt | 4 +- AMDiS/src/DOFVector.cc | 187 ------------------------ AMDiS/src/DOFVector.h | 93 ++++++++---- AMDiS/src/DOFVector.hh | 258 ++++++++++++++++++++++++++++----- AMDiS/src/FixVec.h | 26 ++++ AMDiS/src/parallel/MpiHelper.h | 15 ++ 6 files changed, 335 insertions(+), 248 deletions(-) diff --git a/AMDiS/CMakeLists.txt b/AMDiS/CMakeLists.txt index 9ebae66d..1f795cf0 100644 --- a/AMDiS/CMakeLists.txt +++ b/AMDiS/CMakeLists.txt @@ -8,8 +8,8 @@ SET(SOURCE_DIR ${AMDIS_SOURCE_DIR}/src) #TODO: use the cmake build type 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_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -DDEBUG=1 -O0") +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 -Wno-unused-but-set-variable -DDEBUG=1 -O0") if(NOT CurrentRevision) find_package(Subversion) if(Subversion_FOUND) diff --git a/AMDiS/src/DOFVector.cc b/AMDiS/src/DOFVector.cc index 9de37947..3eaf62de 100644 --- a/AMDiS/src/DOFVector.cc +++ b/AMDiS/src/DOFVector.cc @@ -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, AbstractFunction<double, std::vector<double> > *fct) { diff --git a/AMDiS/src/DOFVector.h b/AMDiS/src/DOFVector.h index 4b29a429..56e219db 100644 --- a/AMDiS/src/DOFVector.h +++ b/AMDiS/src/DOFVector.h @@ -872,46 +872,89 @@ namespace AMDiS { template<typename T> std::vector<DOFVector<double>*> *transform(DOFVector<typename GradientType<T>::type> *vec, 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 - * Computes the integral of a function that includes two different DOFVectors. This - * function works also for the case that the DOFVectors are defined on two different + * Computes the integral of a function that includes two different DOFVectors: + * \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. */ - double integrate(const DOFVector<double> &vec1, - const DOFVector<double> &vec2, - BinaryAbstractFunction<double, double, double> *fct); - + template<typename TOut, typename T1, typename T2> + TOut integrate_Vec2(const DOFVector<T1> &vec1, + 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. - double intSingleMesh(const DOFVector<double> &vec1, - const DOFVector<double> &vec2, - BinaryAbstractFunction<double, double, double> *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); /// Computes the integral of a function with two DOFVectors defined on different meshes. - double intDualMesh(const DOFVector<double> &vec1, - const DOFVector<double> &vec2, - BinaryAbstractFunction<double, double, double> *fct); - - double integrate(const DOFVector<double> &vec, - AbstractFunction<double, WorldVector<double> > *fct); - - double integrate(const FiniteElemSpace* feSpace, - AbstractFunction<double, WorldVector<double> > *fct); + template<typename TOut, typename T1, typename T2> + TOut int_Vec2_DualMesh(const DOFVector<T1> &vec1, + const DOFVector<T2> &vec2, + BinaryAbstractFunction<TOut, T1, T2> *fct); + + /// Computes the integral: \f$ \int v(\vec{x}) f(\vec{x})\,\text{d}\vec{x}\f$ + template<typename T1, typename T2> + typename ProductType<T1,T2>::type integrate_VecTimesCoords(const DOFVector<T1> &vec, + AbstractFunction<T2, WorldVector<double> > *fct); + + /// Computes the integral: \f$ \int f(v(\vec{x}), \vec{x})\,\text{d}\vec{x}\f$ + 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, 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, const std::vector<DOFVector<double>*> &grds, 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" diff --git a/AMDiS/src/DOFVector.hh b/AMDiS/src/DOFVector.hh index 9091a4dc..c81f285f 100644 --- a/AMDiS/src/DOFVector.hh +++ b/AMDiS/src/DOFVector.hh @@ -34,6 +34,11 @@ #include "Operator.h" #include "Initfile.h" #include "Traverse.h" +#include "DualTraverse.h" + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS +#include "MpiHelper.h" +#endif // Defining the interface for MTL4 namespace mtl { @@ -516,7 +521,7 @@ namespace AMDiS { FastQuadrature *quadFast = FastQuadrature::provideFastQuadrature(this->feSpace->getBasisFcts(), *q, INIT_PHI); - double result = 0.0; + T result; nullify(result); int nPoints = quadFast->getNumPoints(); mtl::dense_vector<T> uh_vec(nPoints); TraverseStack stack; @@ -524,7 +529,7 @@ namespace AMDiS { Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET); while (elInfo) { double det = elInfo->getDet(); - double normT = 0.0; + T normT; nullify(normT); this->getVecAtQPs(elInfo, NULL, quadFast, uh_vec); for (int iq = 0; iq < nPoints; iq++) normT += quadFast->getWeight(iq) * (uh_vec[iq]); @@ -534,18 +539,58 @@ namespace AMDiS { } #ifdef HAVE_PARALLEL_DOMAIN_AMDIS - double localResult = result; - MPI::COMM_WORLD.Allreduce(&localResult, &result, 1, MPI_DOUBLE, MPI_SUM); + mpi::globalAdd(result); #endif return result; } - template<typename T> - T integrate_VecAndCoords(const DOFVector<double> &vec, - BinaryAbstractFunction<T, double, WorldVector<double> > *fct) + + template<typename TOut> + 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"); @@ -556,39 +601,184 @@ namespace AMDiS { FastQuadrature *fastQuad = FastQuadrature::provideFastQuadrature(vec.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); - mtl::dense_vector<double> qp(fastQuad->getNumPoints()); - WorldVector<double> coordsAtQP; + mtl::dense_vector<T> qp(fastQuad->getNumPoints()); + + TOut value; nullify(value); - T value; - nullify(value); - Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(vec.getFeSpace()->getMesh(), -1, traverseFlag); while (elInfo) { vec.getVecAtQPs(elInfo, quad, fastQuad, qp); - T tmp; - nullify(tmp); + TOut tmp; nullify(tmp); for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) { - elInfo->coordToWorld(fastQuad->getLambda(iq), coordsAtQP); - tmp += fastQuad->getWeight(iq) * (*fct)(qp[iq], coordsAtQP); + tmp += fastQuad->getWeight(iq) * (*fct)(qp[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 +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + mpi::globalAdd(value); +#endif 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.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp2); + + TOut tmp; nullify(tmp); + 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 + mpi::globalAdd(value); +#endif + + return value; + } + + template<typename T1, typename T2> - T2 integrate_Vec(const DOFVector<T1> &vec, - AbstractFunction<T2, T1> *fct) + typename ProductType<T1,T2>::type integrate_VecTimesCoords(const DOFVector<T1> &vec, + AbstractFunction<T2, WorldVector<double> > *fct) + { + FUNCNAME("integrate_VecTimesCoords()"); + + TEST_EXIT(fct)("No function defined!\n"); + + typedef typename ProductType<T1,T2>::type TOut; + + 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<T1> qp(fastQuad->getNumPoints()); + 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(mesh, -1, traverseFlag); + while (elInfo) { + vec.getVecAtQPs(elInfo, quad, fastQuad, qp); + + TOut tmp; nullify(tmp); + 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 + mpi::globalAdd(value); +#endif + + return value; + } + + + template<typename TOut, typename T> + TOut integrate_VecAndCoords(const DOFVector<T> &vec, + BinaryAbstractFunction<T, T, WorldVector<double> > *fct) { FUNCNAME("integrate_VecAndCoords()"); @@ -601,33 +791,33 @@ namespace AMDiS { FastQuadrature *fastQuad = FastQuadrature::provideFastQuadrature(vec.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); - mtl::dense_vector<T1> qp(fastQuad->getNumPoints()); - - T2 value; - nullify(value); + mtl::dense_vector<T> qp(fastQuad->getNumPoints()); + WorldVector<double> coordsAtQP; + TOut value; nullify(value); + Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(vec.getFeSpace()->getMesh(), -1, traverseFlag); while (elInfo) { vec.getVecAtQPs(elInfo, quad, fastQuad, qp); - T2 tmp; - nullify(tmp); + TOut tmp; nullify(tmp); for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) { - tmp += fastQuad->getWeight(iq) * (*fct)(qp[iq]); + elInfo->coordToWorld(fastQuad->getLambda(iq), coordsAtQP); + tmp += fastQuad->getWeight(iq) * (*fct)(qp[iq], coordsAtQP); } 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 +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + mpi::globalAdd(value); +#endif return value; } + template<typename T> double DOFVector<T>::L1Norm(Quadrature* q) const diff --git a/AMDiS/src/FixVec.h b/AMDiS/src/FixVec.h index d8395de5..33c6e873 100644 --- a/AMDiS/src/FixVec.h +++ b/AMDiS/src/FixVec.h @@ -645,7 +645,33 @@ namespace AMDiS { } }; + /// defines of wich type the product T1*T2 is + template<typename T1, typename T2> + struct ProductType + { + typedef T1 type; + }; + + // scalar times vector + template<typename T1> + struct ProductType<T1, WorldVector<T1> > + { + typedef WorldVector<typename ProductType<T1,T1>::type > type; + }; + // vector times scalar + template<typename T1> + struct ProductType<WorldVector<T1>, T1> + { + typedef WorldVector<typename ProductType<T1,T1>::type > type; + }; + + // vector times vector + template<typename T1, typename T2> + struct ProductType<WorldVector<T1>, WorldVector<T2> > + { + typedef typename ProductType<T1,T2>::type type; + }; } diff --git a/AMDiS/src/parallel/MpiHelper.h b/AMDiS/src/parallel/MpiHelper.h index 9c5e88a1..81fb5ddd 100644 --- a/AMDiS/src/parallel/MpiHelper.h +++ b/AMDiS/src/parallel/MpiHelper.h @@ -35,15 +35,30 @@ namespace AMDiS { void globalAdd(double &value); void globalAdd(int &value); + + template<typename T> + void globalAdd(T &value) { + WARNING("Unknown type for globalAdd. Can not sum up the values of all processors!\n"); + } void globalMin(double &value); void globalMin(int &value); + template<typename T> + void globalMin(T &value) { + WARNING("Unknown type for globalMin. Can not determine minimal value of all processors!\n"); + } + void globalMax(double &value); void globalMax(int &value); + template<typename T> + void globalMax(T &value) { + WARNING("Unknown type for globalMax. Can not determine maximal value of all processors!\n"); + } + inline void startRand() { srand(time(NULL) * (MPI::COMM_WORLD.Get_rank() + 1)); -- GitLab