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 "AbstractTetrahedralMesh.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:
00054
00056 ReplicatableVector mSolutionReplicated;
00057
00065 virtual double GetIntegrand(ChastePoint<SPACE_DIM>& rX,
00066 c_vector<double,PROBLEM_DIM>& rU,
00067 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU)=0;
00068
00074 double CalculateOnElement(Element<ELEMENT_DIM,SPACE_DIM>& rElement);
00075
00076 public:
00077
00081 virtual ~AbstractFunctionalCalculator()
00082 {
00083 }
00084
00095 double Calculate(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>& rMesh, Vec solution);
00096
00097 };
00098
00099
00101
00103
00104
00105 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00106 double AbstractFunctionalCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::CalculateOnElement(Element<ELEMENT_DIM, SPACE_DIM>& rElement)
00107 {
00108 double result_on_element = 0;
00109
00110 GaussianQuadratureRule<ELEMENT_DIM> quad_rule(2);
00111
00114 double jacobian_determinant;
00115 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00116 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00117 rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian);
00118
00119 const unsigned num_nodes = rElement.GetNumNodes();
00120
00121
00122 for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++)
00123 {
00124 const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00125
00126 c_vector<double, ELEMENT_DIM+1> phi;
00127 LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(quad_point, phi);
00128 c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi;
00129 LinearBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00130
00131
00132 ChastePoint<SPACE_DIM> x(0,0,0);
00133 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00134 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00135
00136 for (unsigned i=0; i<num_nodes; i++)
00137 {
00138 const c_vector<double, SPACE_DIM>& r_node_loc = rElement.GetNode(i)->rGetLocation();
00139
00140
00141 x.rGetLocation() += phi(i)*r_node_loc;
00142
00143
00144 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00145 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00146 {
00147
00148
00149
00150 unsigned index_into_vec = PROBLEM_DIM*node_global_index + index_of_unknown;
00151
00152 double u_at_node = mSolutionReplicated[index_into_vec];
00153 u(index_of_unknown) += phi(i)*u_at_node;
00154 for (unsigned j=0; j<SPACE_DIM; j++)
00155 {
00156 grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node;
00157 }
00158 }
00159 }
00160
00161 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00162 result_on_element += GetIntegrand(x, u, grad_u) * wJ;
00163 }
00164
00165 return result_on_element;
00166 }
00167
00168 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00169 double AbstractFunctionalCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::Calculate(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>& rMesh, Vec solution)
00170 {
00171 assert(solution);
00172 mSolutionReplicated.ReplicatePetscVector(solution);
00173 if (mSolutionReplicated.GetSize() != rMesh.GetNumNodes() * PROBLEM_DIM)
00174 {
00175 EXCEPTION("The solution size does not match the mesh");
00176 }
00177
00178 double local_result = 0;
00179
00180 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = rMesh.GetElementIteratorBegin();
00181 iter != rMesh.GetElementIteratorEnd();
00182 ++iter)
00183 {
00184 if (rMesh.CalculateDesignatedOwnershipOfElement((*iter).GetIndex()) == true)
00185 {
00186 local_result += CalculateOnElement(*iter);
00187 }
00188 }
00189
00190 double final_result;
00191 MPI_Allreduce(&local_result, &final_result, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
00192 return final_result;
00193 }
00194
00195 #endif