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
00029 #ifndef ABSTRACTFECABLEINTEGRALASSEMBLER_HPP_
00030 #define ABSTRACTFECABLEINTEGRALASSEMBLER_HPP_
00031
00032 #include "AbstractFeAssemblerCommon.hpp"
00033 #include "GaussianQuadratureRule.hpp"
00034 #include "PetscVecTools.hpp"
00035 #include "PetscMatTools.hpp"
00036
00043 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00044 class AbstractFeCableIntegralAssembler : public AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX,INTERPOLATION_LEVEL>
00045 {
00046 protected:
00048 static const unsigned CABLE_ELEMENT_DIM = 1;
00049
00051 static const unsigned NUM_CABLE_ELEMENT_NODES = 2;
00052
00054 MixedDimensionMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00055
00057 GaussianQuadratureRule<1>* mpCableQuadRule;
00058
00060 typedef LinearBasisFunction<1> CableBasisFunction;
00061
00076 void ComputeTransformedBasisFunctionDerivatives(const ChastePoint<CABLE_ELEMENT_DIM>& rPoint,
00077 const c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00078 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rReturnValue);
00079
00085 void DoAssemble();
00086
00109 virtual c_matrix<double,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES> ComputeCableMatrixTerm(
00110 c_vector<double, NUM_CABLE_ELEMENT_NODES>& rPhi,
00111 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rGradPhi,
00112 ChastePoint<SPACE_DIM>& rX,
00113 c_vector<double,PROBLEM_DIM>& rU,
00114 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00115 Element<CABLE_ELEMENT_DIM,SPACE_DIM>* pElement)
00116 {
00117
00118
00119 NEVER_REACHED;
00120 return zero_matrix<double>(PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES);
00121 }
00122
00143 virtual c_vector<double,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES> ComputeCableVectorTerm(
00144 c_vector<double, NUM_CABLE_ELEMENT_NODES>& rPhi,
00145 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rGradPhi,
00146 ChastePoint<SPACE_DIM>& rX,
00147 c_vector<double,PROBLEM_DIM>& rU,
00148 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00149 Element<CABLE_ELEMENT_DIM,SPACE_DIM>* pElement)
00150 {
00151
00152
00153 NEVER_REACHED;
00154 return zero_vector<double>(PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES);
00155 }
00156
00171 virtual void AssembleOnCableElement(Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement,
00172 c_matrix<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES >& rAElem,
00173 c_vector<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES>& rBElem);
00174
00175
00183 virtual bool ElementAssemblyCriterion(Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement)
00184 {
00185 return true;
00186 }
00187
00188 public:
00189
00197 AbstractFeCableIntegralAssembler(MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>* pMesh, unsigned numQuadPoints=2);
00198
00202 virtual ~AbstractFeCableIntegralAssembler()
00203 {
00204 delete mpCableQuadRule;
00205 }
00206 };
00207
00208
00209
00210 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00211 AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AbstractFeCableIntegralAssembler(
00212 MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>* pMesh, unsigned numQuadPoints)
00213 : AbstractFeAssemblerCommon<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>(),
00214 mpMesh(pMesh)
00215 {
00216 assert(pMesh);
00217 assert(numQuadPoints > 0);
00218 assert(CAN_ASSEMBLE_VECTOR || CAN_ASSEMBLE_MATRIX);
00219
00220 mpCableQuadRule = new GaussianQuadratureRule<CABLE_ELEMENT_DIM>(numQuadPoints);
00221
00222
00223
00224 assert(INTERPOLATION_LEVEL!=NONLINEAR);
00225 }
00226
00227
00228 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00229 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::DoAssemble()
00230 {
00231 HeartEventHandler::EventType assemble_event;
00232 if (this->mAssembleMatrix)
00233 {
00234 assemble_event = HeartEventHandler::ASSEMBLE_SYSTEM;
00235 }
00236 else
00237 {
00238 assemble_event = HeartEventHandler::ASSEMBLE_RHS;
00239 }
00240
00241 if (this->mAssembleMatrix && this->mMatrixToAssemble==NULL)
00242 {
00243 EXCEPTION("Matrix to be assembled has not been set");
00244 }
00245 if (this->mAssembleVector && this->mVectorToAssemble==NULL)
00246 {
00247 EXCEPTION("Vector to be assembled has not been set");
00248 }
00249
00250
00251 HeartEventHandler::BeginEvent(assemble_event);
00252
00253
00254 if (this->mAssembleVector && this->mZeroVectorBeforeAssembly)
00255 {
00256 PetscVecTools::Zero(this->mVectorToAssemble);
00257 }
00258 if (this->mAssembleMatrix && this->mZeroMatrixBeforeAssembly)
00259 {
00260 PetscMatTools::Zero(this->mMatrixToAssemble);
00261 }
00262
00263 const size_t STENCIL_SIZE=PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES;
00264 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00265 c_vector<double, STENCIL_SIZE> b_elem;
00266
00267
00268 if (this->mAssembleMatrix || this->mAssembleVector)
00269 {
00270 for (typename MixedDimensionMesh<CABLE_ELEMENT_DIM, SPACE_DIM>::CableElementIterator iter = mpMesh->GetCableElementIteratorBegin();
00271 iter != mpMesh->GetCableElementIteratorEnd();
00272 ++iter)
00273 {
00274 Element<CABLE_ELEMENT_DIM, SPACE_DIM>& r_element = *(*iter);
00275
00276
00277 if ( r_element.GetOwnership() == true && ElementAssemblyCriterion(r_element)==true )
00278 {
00279 AssembleOnCableElement(r_element, a_elem, b_elem);
00280
00281 unsigned p_indices[STENCIL_SIZE];
00282 r_element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
00283
00284 if (this->mAssembleMatrix)
00285 {
00286 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mMatrixToAssemble, p_indices, a_elem);
00287 }
00288
00289 if (this->mAssembleVector)
00290 {
00291 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_elem);
00292 }
00293 }
00294 }
00295 }
00296
00297 HeartEventHandler::EndEvent(assemble_event);
00298 }
00299
00301
00303
00304 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00305 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::ComputeTransformedBasisFunctionDerivatives(
00306 const ChastePoint<CABLE_ELEMENT_DIM>& rPoint,
00307 const c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00308 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rReturnValue)
00309 {
00310 static c_matrix<double, CABLE_ELEMENT_DIM, NUM_CABLE_ELEMENT_NODES> grad_phi;
00311
00312 LinearBasisFunction<CABLE_ELEMENT_DIM>::ComputeBasisFunctionDerivatives(rPoint, grad_phi);
00313 rReturnValue = prod(trans(rInverseJacobian), grad_phi);
00314 }
00315
00316 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00317 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AssembleOnCableElement(
00318 Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement,
00319 c_matrix<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES >& rAElem,
00320 c_vector<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES>& rBElem)
00321 {
00327 c_matrix<double, SPACE_DIM, CABLE_ELEMENT_DIM> jacobian;
00328 c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00329 double jacobian_determinant;
00330
00333
00335 rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian);
00336
00337 if (this->mAssembleMatrix)
00338 {
00339 rAElem.clear();
00340 }
00341
00342 if (this->mAssembleVector)
00343 {
00344 rBElem.clear();
00345 }
00346
00347 const unsigned num_nodes = rElement.GetNumNodes();
00348
00349
00350 c_vector<double, NUM_CABLE_ELEMENT_NODES> phi;
00351 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES> grad_phi;
00352
00353
00354 for (unsigned quad_index=0; quad_index < mpCableQuadRule->GetNumQuadPoints(); quad_index++)
00355 {
00356 const ChastePoint<CABLE_ELEMENT_DIM>& quad_point = mpCableQuadRule->rGetQuadPoint(quad_index);
00357
00358 CableBasisFunction::ComputeBasisFunctions(quad_point, phi);
00359
00360 if ( this->mAssembleMatrix || INTERPOLATION_LEVEL==NONLINEAR )
00361 {
00362 ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00363 }
00364
00365
00366
00367 ChastePoint<SPACE_DIM> x(0,0,0);
00368
00369 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00370 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00371
00372
00373 this->ResetInterpolatedQuantities();
00374
00375
00376 for (unsigned i=0; i<num_nodes; i++)
00377 {
00378 const Node<SPACE_DIM>* p_node = rElement.GetNode(i);
00379
00380 if (INTERPOLATION_LEVEL != CARDIAC)
00381 {
00382 const c_vector<double, SPACE_DIM>& r_node_loc = p_node->rGetLocation();
00383
00384 x.rGetLocation() += phi(i)*r_node_loc;
00385 }
00386
00387
00388 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00389 if (this->mCurrentSolutionOrGuessReplicated.GetSize() > 0)
00390 {
00391 for (unsigned index_of_unknown=0; index_of_unknown<(INTERPOLATION_LEVEL!=CARDIAC ? PROBLEM_DIM : 1); index_of_unknown++)
00392 {
00393
00394
00395
00396
00397
00398
00399
00400
00401 double u_at_node = this->GetCurrentSolutionOrGuessValue(node_global_index, index_of_unknown);
00402 u(index_of_unknown) += phi(i)*u_at_node;
00403
00405
00406
00407
00408
00409
00410
00411
00412 }
00413 }
00414
00415
00416 IncrementInterpolatedQuantities(phi(i), p_node);
00417 }
00418
00419 double wJ = jacobian_determinant * mpCableQuadRule->GetWeight(quad_index);
00420
00421
00422 if (this->mAssembleMatrix)
00423 {
00424 noalias(rAElem) += ComputeCableMatrixTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00425 }
00426
00427 if (this->mAssembleVector)
00428 {
00429 noalias(rBElem) += ComputeCableVectorTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00430 }
00431 }
00432 }
00433
00434 #endif