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 #include "PseudoEcgCalculator.hpp"
00030 #include "HeartConfig.hpp"
00031 #include "PetscTools.hpp"
00032 #include "Version.hpp"
00033 #include <iostream>
00034
00035 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00036 double PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> ::GetIntegrand(ChastePoint<SPACE_DIM>& rX,
00037 c_vector<double,PROBLEM_DIM>& rU,
00038 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU)
00039 {
00040 c_vector<double,SPACE_DIM> r_vector = rX.rGetLocation()- mProbeElectrode.rGetLocation();
00041 double norm_r = norm_2(r_vector);
00042 if (norm_r <= DBL_EPSILON)
00043 {
00044 EXCEPTION("Probe is on a mesh Gauss point.");
00045 }
00046 c_vector<double,SPACE_DIM> grad_one_over_r = - (r_vector)*SmallPow( (1/norm_r) , 3);
00047 matrix_row<c_matrix<double, PROBLEM_DIM, SPACE_DIM> > grad_u_row(rGradU, 0);
00048 double integrand = inner_prod(grad_u_row, grad_one_over_r);
00049
00050 return -mDiffusionCoefficient*integrand;
00051 }
00052
00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00054 PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::PseudoEcgCalculator(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00055 const ChastePoint<SPACE_DIM>& rProbeElectrode,
00056 std::string directory,
00057 std::string hdf5File,
00058 std::string variableName,
00059 bool makeAbsolute)
00060 : mrMesh(rMesh),
00061 mProbeElectrode(rProbeElectrode),
00062 mVariableName(variableName)
00063
00064 {
00065
00066 mpDataReader = new Hdf5DataReader(directory, hdf5File, makeAbsolute);
00067 mNumberOfNodes = mpDataReader->GetNumberOfRows();
00068 mNumTimeSteps = mpDataReader->GetVariableOverTime(mVariableName, 0u).size();
00069 mDiffusionCoefficient = 1.0;
00070
00071 assert(mNumberOfNodes == mrMesh.GetNumNodes());
00072 }
00073
00074 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00075 PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::~PseudoEcgCalculator()
00076 {
00077 delete mpDataReader;
00078 }
00079
00080 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00081 void PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetDiffusionCoefficient(double diffusionCoefficient)
00082 {
00083 assert(diffusionCoefficient>=0);
00084 mDiffusionCoefficient = diffusionCoefficient;
00085 }
00086
00087 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00088 double PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::ComputePseudoEcgAtOneTimeStep (unsigned timeStep)
00089 {
00090 Vec solution_at_one_time_step = PetscTools::CreateVec(mNumberOfNodes);
00091 mpDataReader->GetVariableOverNodes(solution_at_one_time_step, mVariableName , timeStep);
00092
00093 double pseudo_ecg_at_one_timestep;
00094 try
00095 {
00096 pseudo_ecg_at_one_timestep = Calculate(mrMesh, solution_at_one_time_step);
00097 }
00098 catch (Exception &e)
00099 {
00100 VecDestroy(solution_at_one_time_step);
00101 throw e;
00102 }
00103 VecDestroy(solution_at_one_time_step);
00104 return pseudo_ecg_at_one_timestep;
00105 }
00106
00107 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00108 void PseudoEcgCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::WritePseudoEcg ()
00109 {
00110 std::stringstream stream;
00111 stream << "PseudoEcgFromElectrodeAt" << "_" << mProbeElectrode.GetWithDefault(0)
00112 << "_" << mProbeElectrode.GetWithDefault(1)
00113 << "_" << mProbeElectrode.GetWithDefault(2) << ".dat";
00114 OutputFileHandler output_file_handler(HeartConfig::Instance()->GetOutputDirectory() + "/output", false);
00115 out_stream p_file=out_stream(NULL);
00116 if (PetscTools::AmMaster())
00117 {
00118 p_file = output_file_handler.OpenOutputFile(stream.str());
00119 }
00120 for (unsigned i = 0; i < mNumTimeSteps; i++)
00121 {
00122 double pseudo_ecg_at_one_timestep = ComputePseudoEcgAtOneTimeStep(i);
00123 if (PetscTools::AmMaster())
00124 {
00125 *p_file << pseudo_ecg_at_one_timestep << "\n";
00126 }
00127 }
00128 if (PetscTools::AmMaster())
00129 {
00130
00131 std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
00132 *p_file << comment;
00133 p_file->close();
00134 }
00135 }
00137
00139
00140 template class PseudoEcgCalculator<1,1,1>;
00141 template class PseudoEcgCalculator<1,2,1>;
00142 template class PseudoEcgCalculator<1,3,1>;
00143 template class PseudoEcgCalculator<2,2,1>;
00144
00145 template class PseudoEcgCalculator<3,3,1>;
00146