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
00030
00031
00032
00033
00034
00035
00036 #ifndef ABSTRACTFECABLEINTEGRALASSEMBLER_HPP_
00037 #define ABSTRACTFECABLEINTEGRALASSEMBLER_HPP_
00038
00039 #include "AbstractFeAssemblerCommon.hpp"
00040 #include "GaussianQuadratureRule.hpp"
00041 #include "PetscVecTools.hpp"
00042 #include "PetscMatTools.hpp"
00043
00050 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00051 class AbstractFeCableIntegralAssembler : public AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX,INTERPOLATION_LEVEL>
00052 {
00053 protected:
00055 static const unsigned CABLE_ELEMENT_DIM = 1;
00056
00058 static const unsigned NUM_CABLE_ELEMENT_NODES = 2;
00059
00061 MixedDimensionMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00062
00064 GaussianQuadratureRule<1>* mpCableQuadRule;
00065
00067 typedef LinearBasisFunction<1> CableBasisFunction;
00068
00083 void ComputeTransformedBasisFunctionDerivatives(const ChastePoint<CABLE_ELEMENT_DIM>& rPoint,
00084 const c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00085 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rReturnValue);
00086
00092 void DoAssemble();
00093
00116 virtual c_matrix<double,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES> ComputeCableMatrixTerm(
00117 c_vector<double, NUM_CABLE_ELEMENT_NODES>& rPhi,
00118 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rGradPhi,
00119 ChastePoint<SPACE_DIM>& rX,
00120 c_vector<double,PROBLEM_DIM>& rU,
00121 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00122 Element<CABLE_ELEMENT_DIM,SPACE_DIM>* pElement)
00123 {
00124
00125
00126 NEVER_REACHED;
00127 return zero_matrix<double>(PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES);
00128 }
00129
00150 virtual c_vector<double,PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES> ComputeCableVectorTerm(
00151 c_vector<double, NUM_CABLE_ELEMENT_NODES>& rPhi,
00152 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rGradPhi,
00153 ChastePoint<SPACE_DIM>& rX,
00154 c_vector<double,PROBLEM_DIM>& rU,
00155 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00156 Element<CABLE_ELEMENT_DIM,SPACE_DIM>* pElement)
00157 {
00158
00159
00160 NEVER_REACHED;
00161 return zero_vector<double>(PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES);
00162 }
00163
00178 virtual void AssembleOnCableElement(Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement,
00179 c_matrix<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES >& rAElem,
00180 c_vector<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES>& rBElem);
00181
00182
00190 virtual bool ElementAssemblyCriterion(Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement)
00191 {
00192 return true;
00193 }
00194
00195 public:
00196
00202 AbstractFeCableIntegralAssembler(MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00203
00207 virtual ~AbstractFeCableIntegralAssembler()
00208 {
00209 delete mpCableQuadRule;
00210 }
00211 };
00212
00213
00214
00215 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00216 AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AbstractFeCableIntegralAssembler(
00217 MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00218 : AbstractFeAssemblerCommon<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>(),
00219 mpMesh(pMesh)
00220 {
00221 assert(pMesh);
00222 assert(CAN_ASSEMBLE_VECTOR || CAN_ASSEMBLE_MATRIX);
00223
00224
00225
00226 mpCableQuadRule = new GaussianQuadratureRule<CABLE_ELEMENT_DIM>(2);
00227
00228
00229
00230 assert(INTERPOLATION_LEVEL!=NONLINEAR);
00231 }
00232
00233
00234 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00235 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::DoAssemble()
00236 {
00237 HeartEventHandler::EventType assemble_event;
00238 if (this->mAssembleMatrix)
00239 {
00240 assemble_event = HeartEventHandler::ASSEMBLE_SYSTEM;
00241 }
00242 else
00243 {
00244 assemble_event = HeartEventHandler::ASSEMBLE_RHS;
00245 }
00246
00247 if (this->mAssembleMatrix && this->mMatrixToAssemble==NULL)
00248 {
00249 EXCEPTION("Matrix to be assembled has not been set");
00250 }
00251 if (this->mAssembleVector && this->mVectorToAssemble==NULL)
00252 {
00253 EXCEPTION("Vector to be assembled has not been set");
00254 }
00255
00256
00257 HeartEventHandler::BeginEvent(assemble_event);
00258
00259
00260 if (this->mAssembleVector && this->mZeroVectorBeforeAssembly)
00261 {
00262 PetscVecTools::Zero(this->mVectorToAssemble);
00263 }
00264 if (this->mAssembleMatrix && this->mZeroMatrixBeforeAssembly)
00265 {
00266 PetscMatTools::Zero(this->mMatrixToAssemble);
00267 }
00268
00269 const size_t STENCIL_SIZE=PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES;
00270 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00271 c_vector<double, STENCIL_SIZE> b_elem;
00272
00273
00274 if (this->mAssembleMatrix || this->mAssembleVector)
00275 {
00276 for (typename MixedDimensionMesh<CABLE_ELEMENT_DIM, SPACE_DIM>::CableElementIterator iter = mpMesh->GetCableElementIteratorBegin();
00277 iter != mpMesh->GetCableElementIteratorEnd();
00278 ++iter)
00279 {
00280 Element<CABLE_ELEMENT_DIM, SPACE_DIM>& r_element = *(*iter);
00281
00282
00283 if ( r_element.GetOwnership() == true && ElementAssemblyCriterion(r_element)==true )
00284 {
00285 AssembleOnCableElement(r_element, a_elem, b_elem);
00286
00287 unsigned p_indices[STENCIL_SIZE];
00288 r_element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
00289
00290 if (this->mAssembleMatrix)
00291 {
00292 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mMatrixToAssemble, p_indices, a_elem);
00293 }
00294
00295 if (this->mAssembleVector)
00296 {
00297 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_elem);
00298 }
00299 }
00300 }
00301 }
00302
00303 HeartEventHandler::EndEvent(assemble_event);
00304 }
00305
00307
00309
00310 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00311 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::ComputeTransformedBasisFunctionDerivatives(
00312 const ChastePoint<CABLE_ELEMENT_DIM>& rPoint,
00313 const c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00314 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES>& rReturnValue)
00315 {
00316 static c_matrix<double, CABLE_ELEMENT_DIM, NUM_CABLE_ELEMENT_NODES> grad_phi;
00317
00318 LinearBasisFunction<CABLE_ELEMENT_DIM>::ComputeBasisFunctionDerivatives(rPoint, grad_phi);
00319 rReturnValue = prod(trans(rInverseJacobian), grad_phi);
00320 }
00321
00322 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00323 void AbstractFeCableIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AssembleOnCableElement(
00324 Element<CABLE_ELEMENT_DIM,SPACE_DIM>& rElement,
00325 c_matrix<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES >& rAElem,
00326 c_vector<double, PROBLEM_DIM*NUM_CABLE_ELEMENT_NODES>& rBElem)
00327 {
00333 c_matrix<double, SPACE_DIM, CABLE_ELEMENT_DIM> jacobian;
00334 c_matrix<double, CABLE_ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00335 double jacobian_determinant;
00336
00339
00341 rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian);
00342
00343 if (this->mAssembleMatrix)
00344 {
00345 rAElem.clear();
00346 }
00347
00348 if (this->mAssembleVector)
00349 {
00350 rBElem.clear();
00351 }
00352
00353 const unsigned num_nodes = rElement.GetNumNodes();
00354
00355
00356 c_vector<double, NUM_CABLE_ELEMENT_NODES> phi;
00357 c_matrix<double, SPACE_DIM, NUM_CABLE_ELEMENT_NODES> grad_phi;
00358
00359
00360 for (unsigned quad_index=0; quad_index < mpCableQuadRule->GetNumQuadPoints(); quad_index++)
00361 {
00362 const ChastePoint<CABLE_ELEMENT_DIM>& quad_point = mpCableQuadRule->rGetQuadPoint(quad_index);
00363
00364 CableBasisFunction::ComputeBasisFunctions(quad_point, phi);
00365
00366 if ( this->mAssembleMatrix || INTERPOLATION_LEVEL==NONLINEAR )
00367 {
00368 ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00369 }
00370
00371
00372
00373 ChastePoint<SPACE_DIM> x(0,0,0);
00374
00375 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00376 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00377
00378
00379 this->ResetInterpolatedQuantities();
00380
00381
00382 for (unsigned i=0; i<num_nodes; i++)
00383 {
00384 const Node<SPACE_DIM>* p_node = rElement.GetNode(i);
00385
00386 if (INTERPOLATION_LEVEL != CARDIAC)
00387 {
00388 const c_vector<double, SPACE_DIM>& r_node_loc = p_node->rGetLocation();
00389
00390 x.rGetLocation() += phi(i)*r_node_loc;
00391 }
00392
00393
00394 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00395 if (this->mCurrentSolutionOrGuessReplicated.GetSize() > 0)
00396 {
00397 for (unsigned index_of_unknown=0; index_of_unknown<(INTERPOLATION_LEVEL!=CARDIAC ? PROBLEM_DIM : 1); index_of_unknown++)
00398 {
00399
00400
00401
00402
00403
00404
00405
00406
00407 double u_at_node = this->GetCurrentSolutionOrGuessValue(node_global_index, index_of_unknown);
00408 u(index_of_unknown) += phi(i)*u_at_node;
00409
00411
00412
00413
00414
00415
00416
00417
00418 }
00419 }
00420
00421
00422 this->IncrementInterpolatedQuantities(phi(i), p_node);
00423 }
00424
00425 double wJ = jacobian_determinant * mpCableQuadRule->GetWeight(quad_index);
00426
00427
00428 if (this->mAssembleMatrix)
00429 {
00430 noalias(rAElem) += ComputeCableMatrixTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00431 }
00432
00433 if (this->mAssembleVector)
00434 {
00435 noalias(rBElem) += ComputeCableVectorTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00436 }
00437 }
00438 }
00439
00440 #endif