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 #include "BidomainAssembler.hpp"
00031 #include "PdeSimulationTime.hpp"
00032 #include "UblasIncludes.hpp"
00033 #include <boost/numeric/ublas/vector_proxy.hpp>
00034
00035 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00036 void BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::ResetInterpolatedQuantities()
00037 {
00038 mIionic = 0;
00039 mIIntracellularStimulus = 0;
00040 }
00041
00042
00043 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00044 void BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::IncrementInterpolatedQuantities(
00045 double phiI,
00046 const Node<SPACE_DIM>* pNode)
00047 {
00048 unsigned node_global_index = pNode->GetIndex();
00049
00050 mIionic += phiI * this->mpCardiacTissue->rGetIionicCacheReplicated()[ node_global_index ];
00051 mIIntracellularStimulus += phiI * this->mpCardiacTissue->rGetIntracellularStimulusCacheReplicated()[ node_global_index ];
00052 }
00053
00054 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00055 c_matrix<double,2*(ELEMENT_DIM+1),2*(ELEMENT_DIM+1)>
00056 BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::ComputeMatrixTerm(
00057 c_vector<double, ELEMENT_DIM+1> &rPhi,
00058 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> &rGradPhi,
00059 ChastePoint<SPACE_DIM> &rX,
00060 c_vector<double,2> &rU,
00061 c_matrix<double, 2, SPACE_DIM> &rGradU ,
00062 Element<ELEMENT_DIM,SPACE_DIM>* pElement)
00063 {
00064
00065 double Am = mpConfig->GetSurfaceAreaToVolumeRatio();
00066 double Cm = mpConfig->GetCapacitance();
00067
00068 const c_matrix<double, SPACE_DIM, SPACE_DIM>& sigma_i = this->mpCardiacTissue->rGetIntracellularConductivityTensor(pElement->GetIndex());
00069 const c_matrix<double, SPACE_DIM, SPACE_DIM>& sigma_e = this->mpCardiacTissue->rGetExtracellularConductivityTensor(pElement->GetIndex());
00070
00071
00072 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> temp = prod(sigma_i, rGradPhi);
00073 c_matrix<double, ELEMENT_DIM+1, ELEMENT_DIM+1> grad_phi_sigma_i_grad_phi =
00074 prod(trans(rGradPhi), temp);
00075
00076 c_matrix<double, ELEMENT_DIM+1, ELEMENT_DIM+1> basis_outer_prod =
00077 outer_prod(rPhi, rPhi);
00078
00079 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> temp2 = prod(sigma_e, rGradPhi);
00080 c_matrix<double, ELEMENT_DIM+1, ELEMENT_DIM+1> grad_phi_sigma_e_grad_phi =
00081 prod(trans(rGradPhi), temp2);
00082
00083
00084 c_matrix<double,2*(ELEMENT_DIM+1),2*(ELEMENT_DIM+1)> ret;
00085
00086
00087 matrix_slice<c_matrix<double, 2*ELEMENT_DIM+2, 2*ELEMENT_DIM+2> >
00088 slice00(ret, slice (0, 2, ELEMENT_DIM+1), slice (0, 2, ELEMENT_DIM+1));
00089 slice00 = (Am*Cm*PdeSimulationTime::GetPdeTimeStepInverse())*basis_outer_prod + grad_phi_sigma_i_grad_phi;
00090
00091
00092 matrix_slice<c_matrix<double, 2*ELEMENT_DIM+2, 2*ELEMENT_DIM+2> >
00093 slice10(ret, slice (1, 2, ELEMENT_DIM+1), slice (0, 2, ELEMENT_DIM+1));
00094 slice10 = grad_phi_sigma_i_grad_phi;
00095
00096
00097 matrix_slice<c_matrix<double, 2*ELEMENT_DIM+2, 2*ELEMENT_DIM+2> >
00098 slice01(ret, slice (0, 2, ELEMENT_DIM+1), slice (1, 2, ELEMENT_DIM+1));
00099 slice01 = grad_phi_sigma_i_grad_phi;
00100
00101
00102 matrix_slice<c_matrix<double, 2*ELEMENT_DIM+2, 2*ELEMENT_DIM+2> >
00103 slice11(ret, slice (1, 2, ELEMENT_DIM+1), slice (1, 2, ELEMENT_DIM+1));
00104 slice11 = grad_phi_sigma_i_grad_phi + grad_phi_sigma_e_grad_phi;
00105
00106 return ret;
00107 }
00108
00109
00110 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00111 c_vector<double,2*(ELEMENT_DIM+1)>
00112 BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::ComputeVectorTerm(
00113 c_vector<double, ELEMENT_DIM+1> &rPhi,
00114 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> &rGradPhi,
00115 ChastePoint<SPACE_DIM> &rX,
00116 c_vector<double,2> &u,
00117 c_matrix<double, 2, SPACE_DIM> &rGradU ,
00118 Element<ELEMENT_DIM,SPACE_DIM>* pElement)
00119 {
00120
00121 double Am = mpConfig->GetSurfaceAreaToVolumeRatio();
00122 double Cm = mpConfig->GetCapacitance();
00123
00124 c_vector<double,2*(ELEMENT_DIM+1)> ret;
00125
00126 vector_slice<c_vector<double, 2*(ELEMENT_DIM+1)> > slice_V (ret, slice (0, 2, ELEMENT_DIM+1));
00127 vector_slice<c_vector<double, 2*(ELEMENT_DIM+1)> > slice_Phi(ret, slice (1, 2, ELEMENT_DIM+1));
00128
00129
00130 noalias(slice_V) = (Am*Cm*u(0)*PdeSimulationTime::GetPdeTimeStepInverse() - Am*mIionic - mIIntracellularStimulus) * rPhi;
00131 noalias(slice_Phi) = zero_vector<double>(ELEMENT_DIM+1);
00132
00133 return ret;
00134 }
00135
00136
00137
00138 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00139 c_vector<double, 2*ELEMENT_DIM> BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::ComputeVectorSurfaceTerm(
00140 const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM> &rSurfaceElement,
00141 c_vector<double,ELEMENT_DIM> &rPhi,
00142 ChastePoint<SPACE_DIM> &rX)
00143 {
00144
00145 double sigma_i_times_grad_phi_i_dot_n = this->mpBoundaryConditions->GetNeumannBCValue(&rSurfaceElement, rX, 0);
00146 double sigma_e_times_grad_phi_e_dot_n = this->mpBoundaryConditions->GetNeumannBCValue(&rSurfaceElement, rX, 1);
00147
00148 c_vector<double, 2*ELEMENT_DIM> ret;
00149 for (unsigned i=0; i<ELEMENT_DIM; i++)
00150 {
00151 ret(2*i) = rPhi(i)*sigma_i_times_grad_phi_i_dot_n;
00152 ret(2*i+1) = rPhi(i)*(sigma_i_times_grad_phi_i_dot_n + sigma_e_times_grad_phi_e_dot_n);
00153 }
00154
00155 return ret;
00156 }
00157
00158
00159
00160 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00161 BidomainAssembler<ELEMENT_DIM,SPACE_DIM>::BidomainAssembler(
00162 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00163 BidomainTissue<SPACE_DIM>* pTissue,
00164 unsigned numQuadPoints)
00165 : AbstractCardiacFeObjectAssembler<ELEMENT_DIM,SPACE_DIM,2,true,true,CARDIAC>(pMesh,pTissue,numQuadPoints)
00166 {
00167 assert(pTissue != NULL);
00168 mpConfig = HeartConfig::Instance();
00169 }
00170
00171
00172
00174
00176
00177 template class BidomainAssembler<1,1>;
00178 template class BidomainAssembler<2,2>;
00179 template class BidomainAssembler<3,3>;