From 2d8a6968f878f0fb90abbcfd83caf549b98073b5 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Wed, 26 May 2010 08:29:11 +0000
Subject: [PATCH] Added new functions for integrating abstract function with
 two DOFVectors.

---
 AMDiS/src/AMDiS.h      |  3 +-
 AMDiS/src/AMDiS_fwd.h  | 13 ++++++
 AMDiS/src/DOFVector.cc | 92 ++++++++++++++++++++++++++++++++++++++++++
 AMDiS/src/DOFVector.h  | 20 +++++++++
 4 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h
index a39c5a0a..2d9d4949 100644
--- a/AMDiS/src/AMDiS.h
+++ b/AMDiS/src/AMDiS.h
@@ -1,6 +1,6 @@
 #ifndef AMDIS_H
 #define AMDIS_H
-#include "MathFunctions.h"
+
 #include "AbstractFunction.h"
 #include "AdaptInfo.h"
 #include "AdaptInstationary.h"
@@ -49,6 +49,7 @@
 #include "MacroElement.h"
 #include "MacroWriter.h"
 #include "Marker.h"
+#include "MathFunctions.h"
 #include "MatrixVector.h"
 #include "Mesh.h"
 #include "MeshStructure.h"
diff --git a/AMDiS/src/AMDiS_fwd.h b/AMDiS/src/AMDiS_fwd.h
index 272c8904..686225f7 100644
--- a/AMDiS/src/AMDiS_fwd.h
+++ b/AMDiS/src/AMDiS_fwd.h
@@ -101,6 +101,19 @@ namespace AMDiS {
   struct AtomicBoundary;
 
   template<typename ReturnType, typename ArgumentType> class AbstractFunction;
+  template<typename ReturnType, 
+	   typename ArgumentType1, 
+	   typename ArgumentType2>                     class BinaryAbstractFunction;
+  template<typename ReturnType, 
+	   typename ArgumentType1, 
+	   typename ArgumentType2,
+	   typename ArgumentType3>                     class TertiaryAbstractFunction;
+  template<typename ReturnType, 
+	   typename ArgumentType1, 
+	   typename ArgumentType2, 
+	   typename ArgumentType3,
+	   typename ArgumentType4>                     class QuartAbstractFunction;
+
   template<typename T>                                 class DOFIndexed;
   template<typename T>                                 class DOFVectorBase;
   template<typename T>                                 class DOFVector;
diff --git a/AMDiS/src/DOFVector.cc b/AMDiS/src/DOFVector.cc
index cb978648..ab89835f 100644
--- a/AMDiS/src/DOFVector.cc
+++ b/AMDiS/src/DOFVector.cc
@@ -865,5 +865,97 @@ 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 = 2 * vec1.getFESpace()->getBasisFcts()->getDegree();
+    Quadrature* quad = 
+      Quadrature::provideQuadrature(vec1.getFESpace()->getMesh()->getDim(), deg);
+    FastQuadrature *fastQuad =
+      FastQuadrature::provideFastQuadrature(vec1.getFESpace()->getBasisFcts(), *quad, INIT_PHI);
+
+    std::vector<double> qp1(fastQuad->getNumPoints());
+    std::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) {
+      double det = elInfo->getDet();
+      double tmp = 0.0;      
+      vec1.getVecAtQPs(elInfo, quad, fastQuad, &(qp1[0]));
+      vec2.getVecAtQPs(elInfo, quad, fastQuad, &(qp2[0]));      
+      for (int iq = 0; iq < fastQuad->getNumPoints(); iq++)
+ 	tmp += fastQuad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]);
+      
+      value += tmp * det;
+      
+      elInfo = stack.traverseNext(elInfo);
+    }
+
+    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 = 2 * vec1.getFESpace()->getBasisFcts()->getDegree();
+    Quadrature* quad = 
+      Quadrature::provideQuadrature(vec1.getFESpace()->getMesh()->getDim(), deg);
+    FastQuadrature *fastQuad =
+      FastQuadrature::provideFastQuadrature(vec1.getFESpace()->getBasisFcts(), *quad, INIT_PHI);
+
+    std::vector<double> qp1(fastQuad->getNumPoints());
+    std::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) {
+      double det = dualElInfo.smallElInfo->getDet();
+      double tmp = 0.0;      
+      vec1.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo,
+		       quad, fastQuad, &(qp1[0]));
+      vec2.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo,
+		       quad, fastQuad, &(qp2[0]));      
+      for (int iq = 0; iq < fastQuad->getNumPoints(); iq++)
+ 	tmp += fastQuad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]);
+      
+      value += tmp * det;
+      
+      cont = dualTraverse.traverseNext(dualElInfo);
+    }
+
+    return value;
+  }
+
 }
 
diff --git a/AMDiS/src/DOFVector.h b/AMDiS/src/DOFVector.h
index 4ba37da1..d8716809 100644
--- a/AMDiS/src/DOFVector.h
+++ b/AMDiS/src/DOFVector.h
@@ -789,6 +789,26 @@ namespace AMDiS {
 
   WorldVector<DOFVector<double>*> *transform(DOFVector<WorldVector<double> > *vec,
 					     WorldVector<DOFVector<double>*> *result);
+
+  /** \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
+   * meshes.
+   */
+  double integrate(const DOFVector<double> &vec1,
+		   const DOFVector<double> &vec2,
+		   BinaryAbstractFunction<double, double, double> *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);
+
+  /// 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);
+
 }
 
 #include "DOFVector.hh"
-- 
GitLab