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