00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef ABSTRACTFUNCTIONALCALCULATOR_HPP_
00029 #define ABSTRACTFUNCTIONALCALCULATOR_HPP_
00030
00031 #include "LinearBasisFunction.hpp"
00032 #include "GaussianQuadratureRule.hpp"
00033 #include "TetrahedralMesh.hpp"
00034 #include "GaussianQuadratureRule.hpp"
00035 #include "ReplicatableVector.hpp"
00036
00037
00050 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00051 class AbstractFunctionalCalculator
00052 {
00053 private:
00055 ReplicatableVector mSolutionReplicated;
00056
00058 virtual double GetIntegrand(ChastePoint<SPACE_DIM> &rX,
00059 c_vector<double,PROBLEM_DIM> &rU,
00060 c_matrix<double,PROBLEM_DIM,SPACE_DIM> &rGradU)=0;
00061
00063 double CalculateOnElement(Element<ELEMENT_DIM,SPACE_DIM>& rElement)
00064 {
00065 double result_on_element = 0;
00066
00067 GaussianQuadratureRule<ELEMENT_DIM> quad_rule(2);
00068
00072 double jacobian_determinant;
00073 c_matrix<double, SPACE_DIM, SPACE_DIM> jacobian, inverse_jacobian;
00074 rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian);
00075
00076 const unsigned num_nodes = rElement.GetNumNodes();
00077
00078
00079 for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++)
00080 {
00081 const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00082
00083 c_vector<double, ELEMENT_DIM+1> phi;
00084 LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(quad_point, phi);
00085 c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi;
00086 LinearBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00087
00088
00089 ChastePoint<SPACE_DIM> x(0,0,0);
00090 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00091 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00092
00093 for (unsigned i=0; i<num_nodes; i++)
00094 {
00095 const c_vector<double, SPACE_DIM>& r_node_loc = rElement.GetNode(i)->rGetLocation();
00096
00097
00098 x.rGetLocation() += phi(i)*r_node_loc;
00099
00100
00101 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00102 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00103 {
00104
00105
00106
00107 unsigned index_into_vec = PROBLEM_DIM*node_global_index + index_of_unknown;
00108
00109 double u_at_node = mSolutionReplicated[index_into_vec];
00110 u(index_of_unknown) += phi(i)*u_at_node;
00111 for (unsigned j=0; j<SPACE_DIM; j++)
00112 {
00113 grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node;
00114 }
00115 }
00116 }
00117
00118 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00119 result_on_element += GetIntegrand(x, u, grad_u) * wJ;
00120 }
00121
00122 return result_on_element;
00123 }
00124
00125
00126 public:
00127 virtual ~AbstractFunctionalCalculator()
00128 {
00129 }
00130
00134 double Calculate(TetrahedralMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00135 Vec solution)
00136 {
00137 assert(solution);
00138 mSolutionReplicated.ReplicatePetscVector(solution);
00139 if (mSolutionReplicated.size() != rMesh.GetNumNodes() * PROBLEM_DIM)
00140 {
00141 EXCEPTION("The solution size does not match the mesh");
00142 }
00143
00144 double result = 0;
00145
00146 for (typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator
00147 iter = rMesh.GetElementIteratorBegin();
00148 iter != rMesh.GetElementIteratorEnd();
00149 ++iter)
00150 {
00154
00155 {
00156 result += CalculateOnElement(**iter);
00157 }
00158 }
00159
00161
00162
00163
00164
00165 return result;
00166 }
00167 };
00168
00169 #endif