Esempio n. 1
0
    void TestAssigningModifiersToACellModel() throw(Exception)
    {
        boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus());
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellShannon2004FromCellML* p_shannon = new CellShannon2004FromCellML(p_solver, p_stimulus);

        TS_ASSERT_EQUALS(p_shannon->HasModifier("Alan"), false);
        TS_ASSERT_THROWS_THIS(p_shannon->GetModifier("Alan"), "There is no modifier called Alan in this model.");


        // Default modifier shouldn't do anything to the value inputted to calc()
        TS_ASSERT_EQUALS(p_shannon->HasModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance"), true);
        TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(123,0),123,1e-9);

        // Make a new modifier
        boost::shared_ptr<AbstractModifier> p_new_modifier(new FixedModifier(-90.0));

        TS_ASSERT_THROWS_THIS(p_shannon->SetModifier("Alan",p_new_modifier), "There is no modifier called Alan in this model.");

        // Assign it to the Shannon model
        p_shannon->SetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance",p_new_modifier);

        // We should now get a new answer to this.
        TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(0,0),-90,1e-9);

        delete p_shannon;
    }
    //  Run normally up to stretch-time, then apply stretch and
    //  run until stretch-off-time, then return to stretch=1
    //  and run until 1000ms.
    void RunModelWithSacRecruitment(double stretch,
                                    double stretchStartTime,
                                    double stretchEndTime,
                                    std::string directory,
                                    std::string filePrefix,
                                    bool clearDir)
    {
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(
                -3 /*magnitude*/,
                3 /*duration*/,
                10.0 /*start time*/));
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);

        double time_step = 0.01;
        HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(time_step, time_step, 1.0);

        CML_noble_varghese_kohl_noble_1998_basic_with_sac   n98_with_sac(p_solver, p_stimulus);

        OutputFileHandler handler(directory,clearDir);
        out_stream p_file = handler.OpenOutputFile(filePrefix+".dat");
        *p_file << 0 << " " << n98_with_sac.GetVoltage() << "\n";

        double printing_dt = 1;
        TimeStepper stepper(0, stretchStartTime, printing_dt);

        while ( !stepper.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper.GetTime(), stepper.GetNextTime());
            stepper.AdvanceOneTimeStep();

            *p_file << stepper.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        n98_with_sac.SetStretch(stretch);

        TimeStepper stepper2(stepper.GetTime(), stretchEndTime, printing_dt);
        while ( !stepper2.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper2.GetTime(), stepper2.GetNextTime());
            stepper2.AdvanceOneTimeStep();

            *p_file << stepper2.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        n98_with_sac.SetStretch(1.0);

        TimeStepper stepper3(stepper2.GetTime(), 1000, printing_dt);
        while ( !stepper3.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper3.GetTime(), stepper3.GetNextTime());
            stepper3.AdvanceOneTimeStep();

            *p_file << stepper3.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        p_file->close();
    }
Esempio n. 3
0
    void TestOdeSolverForFox2002WithRegularStimulus(void) throw (Exception)
    {
        clock_t ck_start, ck_end;
        // Set stimulus
        double magnitude = -80.0;
        double duration  = 1.0 ;  // ms
        double start = 50.0; // ms
        double period = 500; // ms
        boost::shared_ptr<RegularStimulus> p_stimulus(new RegularStimulus(magnitude, duration, period, start));

        double end_time = 1000.0; //One second in milliseconds


        HeartConfig::Instance()->SetOdeTimeStep(0.002); // 0.005 leads to NaNs.

        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellFoxModel2002FromCellML fox_ode_system(p_solver, p_stimulus);

        // Solve and write to file
        ck_start = clock();
        RunOdeSolverWithIonicModel(&fox_ode_system,
                                   end_time,
                                   "FoxRegularStimLong",
                                   500);
        ck_end = clock();
        double forward = (double)(ck_end - ck_start)/CLOCKS_PER_SEC;

        CheckCellModelResults("FoxRegularStimLong");

        // Solve using Backward Euler
        HeartConfig::Instance()->SetOdeTimeStep(0.01);
        CellFoxModel2002FromCellMLBackwardEuler backward_system(p_solver, p_stimulus);
        ck_start = clock();
        RunOdeSolverWithIonicModel(&backward_system,
                                   end_time,
                                   "BackwardFoxRegularStimLong",
                                   100);
        ck_end = clock();
        double backward = (double)(ck_end - ck_start)/CLOCKS_PER_SEC;

        CompareCellModelResults("FoxRegularStimLong", "BackwardFoxRegularStimLong", 0.15);
        // Mainly for coverage, and to test consistency of GetIIonic
        TS_ASSERT_DELTA(fox_ode_system.GetIIonic(),
                        backward_system.GetIIonic(),
                        1e-6);

        std::cout << "Run times:\n\tForward: " << forward
                  << "\n\tBackward: " << backward
                  << std::endl;

    }
Esempio n. 4
0
    void TestAccessingParametersWithoutModifiers() throw(Exception)
    {
        boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus());
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellShannon2004FromCellML* p_shannon = new CellShannon2004FromCellML(p_solver, p_stimulus);

        // We should now have all of the following methods available as an alternative to using 'modifiers'
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_fast_sodium_current_conductance"),16.0,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_L_type_calcium_current_conductance"),5.4e-4,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_rapid_delayed_rectifier_potassium_current_conductance"),0.03,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_slow_delayed_rectifier_potassium_current_conductance"),0.07,1e-5);

        delete p_shannon;
     }
    void TestArchiving(void) throw(Exception)
    {
        //Archive
        OutputFileHandler handler("archive", false);
        handler.SetArchiveDirectory();
        std::string archive_filename =  ArchiveLocationInfo::GetProcessUniqueFilePath("GI.arch");

        // Save
        {

            boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(0.0,1.0,0.5));
            boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
            double time_step = 0.01;
            HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(time_step, time_step, time_step);

            // icc and smc
            AbstractCardiacCell* const p_smc = new CorriasBuistSMCModified(p_solver, p_stimulus);
            AbstractCardiacCell* const p_icc = new CorriasBuistICCModified(p_solver, p_stimulus);

            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            output_arch <<  p_smc;
            output_arch <<  p_icc;

            delete p_smc;
            delete p_icc;
        }
        // Load
        {
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            AbstractCardiacCell* p_smc;
            AbstractCardiacCell* p_icc;
            input_arch >> p_smc;
            input_arch >> p_icc;

            TS_ASSERT_EQUALS( p_smc->GetNumberOfStateVariables(), 14U );
            TS_ASSERT_EQUALS( p_icc->GetNumberOfStateVariables(), 18U );

            delete p_smc;
            delete p_icc;
        }
     }
    void GenerateCells() throw (Exception)
    {
        // Do the conversions preserving generated sources
        CellMLToSharedLibraryConverter converter(true);
        std::string dirname = "TestGeneralizedRushLarsen";
        std::string model = "LuoRudy1991";
        boost::shared_ptr<AbstractIvpOdeSolver> p_solver;
        boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus());

        std::vector<std::string> args;
        args.push_back("--grl1");

        { // No opt
            // Copy CellML file into output dir
            OutputFileHandler handler(dirname + "/normal");
            FileFinder cellml_file("heart/src/odes/cellml/" + model + ".cellml", RelativeTo::ChasteSourceRoot);
            FileFinder copied_file = handler.CopyFileTo(cellml_file);

            // Create options file & convert
            converter.CreateOptionsFile(handler, model, args);
            DynamicCellModelLoaderPtr p_loader = converter.Convert(copied_file);
            mpGeneralizedRushLarsenCell = dynamic_cast<AbstractCardiacCell*>(p_loader->CreateCell(p_solver, p_stimulus));
        }
    }
 boost::shared_ptr<AbstractStimulusFunction> CreateStimulusForNode(Node<2>* pNode)
 {
     boost::shared_ptr<SimpleStimulus> p_stimulus ( new SimpleStimulus(-428000, 1.0, 0.1) );
     return p_stimulus;
 }
    void TestHHModelAtSingularities()
    {
        /*
        * Set stimulus
        */
        double magnitude_stimulus = 0.0;  // uA/cm2
        double duration_stimulus = 0.;  // ms
        double start_stimulus = 0.0;   // ms
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(
                magnitude_stimulus,
                duration_stimulus,
                start_stimulus));

        boost::shared_ptr<AbstractIvpOdeSolver> p_solver; // We don't actually need a solver

        CellHodgkinHuxley1952FromCellML hh52_ode_system(p_solver, p_stimulus);

        double v_singularity[2];
        v_singularity[0]=-65;
        v_singularity[1]=-50;

        for (int i=0; i<2; i++)
        {

            std::vector<double> yleft;

            //mVariableNames.push_back("V");
            //mVariableUnits.push_back("mV");
            yleft.push_back(v_singularity[i]+0.1);

            //mVariableNames.push_back("n");
            //mVariableUnits.push_back("");
            yleft.push_back(0.325);

            //mVariableNames.push_back("h");
            //mVariableUnits.push_back("");
            yleft.push_back(0.6);

            //mVariableNames.push_back("m");
            //mVariableUnits.push_back("");
            yleft.push_back(0.05);


            std::vector<double> rhsleft(yleft.size());
            hh52_ode_system.EvaluateYDerivatives (0.0, yleft, rhsleft);

            std::vector<double> yright;

            //mVariableNames.push_back("V");
            //mVariableUnits.push_back("mV");
            yright.push_back(v_singularity[i]-0.1);

            //mVariableNames.push_back("n");
            //mVariableUnits.push_back("");
            yright.push_back(0.325);

            //mVariableNames.push_back("h");
            //mVariableUnits.push_back("");
            yright.push_back(0.6);

            //mVariableNames.push_back("m");
            //mVariableUnits.push_back("");
            yright.push_back(0.05);

            std::vector<double> rhsright(yright.size());
            hh52_ode_system.EvaluateYDerivatives (0.0, yright, rhsright);


            std::vector<double> y_at_singularity;

            //mVariableNames.push_back("V");
            //mVariableUnits.push_back("mV");
            y_at_singularity.push_back(v_singularity[i]);

            //mVariableNames.push_back("n");
            //mVariableUnits.push_back("");
            y_at_singularity.push_back(0.325);

            //mVariableNames.push_back("h");
            //mVariableUnits.push_back("");
            y_at_singularity.push_back(0.6);

            //mVariableNames.push_back("m");
            //mVariableUnits.push_back("");
            y_at_singularity.push_back(0.05);

            std::vector<double> rhs_at_singularity(y_at_singularity.size());
            hh52_ode_system.EvaluateYDerivatives (0.0, y_at_singularity, rhs_at_singularity);

            for (int j=0; j<4; j++)
            {
                //std::cout << j << "\t" << rhsright[j] << "\t" << rhsleft[j] << "\t" << rhs_at_singularity[j] << std::endl;
                TS_ASSERT_DELTA((rhsright[j]+rhsleft[j])/2, rhs_at_singularity[j], 0.1);
            }
        }
    }
    void TestTimingsWithAndWithoutJacobian() throw (Exception)
    {
#ifdef CHASTE_CVODE
        // Set up a default solver and a stimulus
        boost::shared_ptr<AbstractIvpOdeSolver> p_solver;
        boost::shared_ptr<AbstractStimulusFunction> p_stimulus(new RegularStimulus(-25,5,1000,1));
        double simulation_duration = 10000; // This increased to 1e6 to give the timings shown on #1795.
        double max_time_step = 1.0;

        for (unsigned i=0; i<10; i++)
        {
            boost::shared_ptr<CvodeAdaptor> p_cvode_adaptor(new CvodeAdaptor()); // moving this outside the loop causes seg-faults!
            p_cvode_adaptor->SetTolerances(1e-5, 1e-7); // Match AbstractCvodeCell
            boost::shared_ptr<AbstractCardiacCell> p_cell_cvode_adaptor;
            boost::shared_ptr<AbstractCvodeCell> p_cell_cvode;
            switch (i)
            {
                case 0:
                {
                    // Fox model
                    p_cell_cvode_adaptor.reset(new CellFoxModel2002FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellFoxModel2002FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 1:
                {
                    // Shannon model
                    p_cell_cvode_adaptor.reset(new CellShannon2004FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellShannon2004FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 2:
                {
                    // HH1952 model
                    p_cell_cvode_adaptor.reset(new CellHodgkinHuxley1952FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellHodgkinHuxley1952FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 3:
                {
                    // Luo Rudy model
                    p_cell_cvode_adaptor.reset(new CellLuoRudy1991FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellLuoRudy1991FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 4:
                {
                    // Mahajan model
                    p_cell_cvode_adaptor.reset(new CellMahajan2008FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellMahajan2008FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 5:
                {
                    // Maleckar model
                    p_cell_cvode_adaptor.reset(new CellMaleckar2008FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellMaleckar2008FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 6:
                {
                    // FaberRudy2000 model
                    p_cell_cvode_adaptor.reset(new CellFaberRudy2000FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellFaberRudy2000FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 7:
                {
                    // DiFrancescoNoble1985 model
                    p_cell_cvode_adaptor.reset(new CellDiFrancescoNoble1985FromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellDiFrancescoNoble1985FromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 8:
                {
                    // NobleVargheseKohlNoble1998a model
                    p_cell_cvode_adaptor.reset(new CellNobleVargheseKohlNoble1998aFromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellNobleVargheseKohlNoble1998aFromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                case 9:
                {
                    // TenTusscher2006Epi model
                    p_cell_cvode_adaptor.reset(new CellTenTusscher2006EpiFromCellML(p_cvode_adaptor,p_stimulus));
                    p_cell_cvode.reset(new CellTenTusscher2006EpiFromCellMLCvode(p_solver,p_stimulus));
                    break;
                }
                default:
                    EXCEPTION("No model");
            }

            std::cout << p_cell_cvode_adaptor->GetSystemName() << ": " << p_cell_cvode_adaptor->GetNumberOfStateVariables() << " ODEs.\n";

            // A standard CVODE adaptor solve
            p_cvode_adaptor->SetMaxSteps(0xffffffff);
            p_cell_cvode_adaptor->SetTimestep(max_time_step);

            Timer::Reset();
            p_cell_cvode_adaptor->SolveAndUpdateState(0, simulation_duration);
            Timer::Print(" 1. CVODE adaptor (numeric Jacobian)");

            // A standard native CVODE solve
            p_cell_cvode->SetMaxSteps(0xffffffff);
            p_cell_cvode->SetMaxTimestep(max_time_step);
            p_cell_cvode->ForceUseOfNumericalJacobian(true);
            TS_ASSERT(!p_cell_cvode->GetUseAnalyticJacobian());

            Timer::Reset();
            p_cell_cvode->SolveAndUpdateState(0, simulation_duration);
            Timer::Print(" 2. CVODE native with Numeric Jacobian");

            // A jacobian native CVODE solve
            p_cell_cvode->ResetToInitialConditions();
            p_cell_cvode->ForceUseOfNumericalJacobian(false);
            TS_ASSERT(p_cell_cvode->GetUseAnalyticJacobian());

            Timer::Reset();
            p_cell_cvode->SolveAndUpdateState(0, simulation_duration);
            Timer::Print(" 3. CVODE native with Analytic Jacobian");
        }
#else
        std::cout << "CVODE is not installed or Chaste hostconfig is not using it." << std::endl;
#endif
    }
    void TestLuoRudyGeneralizedRushLarsenMethod2()
    {
        EXIT_IF_PARALLEL;
        HeartConfig::Instance()->SetOdeTimeStep(0.01);
        GenerateCells2();

        // Check the models really use Rush-Larsen
        TS_ASSERT_EQUALS(Warnings::Instance()->GetNumWarnings(), 0u);

        // Normal Luo-Rudy for comparison
        boost::shared_ptr<HeunIvpOdeSolver> p_heun_solver(new HeunIvpOdeSolver());
        CellLuoRudy1991FromCellML reference_model(p_heun_solver, mpGeneralizedRushLarsenCell->GetStimulusFunction());

        // Check GetIIonic is identical
        TS_ASSERT_DELTA(mpGeneralizedRushLarsenCell->GetIIonic(), reference_model.GetIIonic(), 1e-12);

        // Test non-stimulated cell (using ComputeExceptVoltage)
        mpGeneralizedRushLarsenCell->ComputeExceptVoltage(0.0, 1.0);
        reference_model.ComputeExceptVoltage(0.0, 1.0);

        TS_ASSERT_EQUALS(mpGeneralizedRushLarsenCell->GetNumberOfStateVariables(),
                         reference_model.GetNumberOfStateVariables());
        for (unsigned i=0; i<reference_model.GetNumberOfStateVariables(); i++)
        {
            TS_ASSERT_DELTA(mpGeneralizedRushLarsenCell->rGetStateVariables()[i],
                            reference_model.rGetStateVariables()[i], 1e-6);
        }
        // Test stimulated cell (using Compute)
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(-25.5, 1.99, 0.0));
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        mpGeneralizedRushLarsenCell->SetStimulusFunction(p_stimulus);
        OdeSolution solutions_GRL2 = mpGeneralizedRushLarsenCell->Compute(0.0, 1.0, 0.01);
        TS_ASSERT_EQUALS(solutions_GRL2.GetNumberOfTimeSteps(), 100u);

        reference_model.ResetToInitialConditions();
        reference_model.SetStimulusFunction(p_stimulus);
        OdeSolution solutions_ref = reference_model.Compute(0.0, 1.0, 0.01);

        for (unsigned i=0; i<reference_model.GetNumberOfStateVariables(); i++)
        {
            TS_ASSERT_DELTA(solutions_GRL2.rGetSolutions().back()[i],
                            solutions_ref.rGetSolutions().back()[i], 1e-2);
        }

        //Compare LuoRudy solution with general GRL2 solver solution (should match)
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        boost::shared_ptr<ZeroStimulus> p_stimulus_zero(new ZeroStimulus());
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        mpGeneralizedRushLarsenCell->SetStimulusFunction(p_stimulus_zero);
        mpGeneralizedRushLarsenCell->SetTimestep(1e-3);
        mpGeneralizedRushLarsenCell->SetVoltage(-30);
        OdeSolution solutions_GRL2_stimulated_cell_order2 = mpGeneralizedRushLarsenCell->Compute(0.0, 1e-3);

        boost::shared_ptr<GRL2IvpOdeSolver> p_grl2_solver(new GRL2IvpOdeSolver());
        CellLuoRudy1991FromCellML reference_model_grl2(p_grl2_solver, mpGeneralizedRushLarsenCell->GetStimulusFunction());

        // Compare with general GRL2 method
        reference_model_grl2.ResetToInitialConditions();
        reference_model_grl2.SetStimulusFunction(p_stimulus_zero);
        reference_model_grl2.SetTimestep(1e-3);
        reference_model_grl2.SetVoltage(-30);
        OdeSolution ref_solution_grl2 = reference_model_grl2.Compute(0.0, 1e-3);

        for (unsigned i=0; i<reference_model_grl2.GetNumberOfStateVariables(); i++)
        {
            double error1 = solutions_GRL2_stimulated_cell_order2.rGetSolutions().back()[i] - ref_solution_grl2.rGetSolutions().back()[i];
            TS_ASSERT_DELTA(fabs(error1),0,5e-7);
        }

        // Free memory
        delete mpGeneralizedRushLarsenCell;
//        delete mpGeneralizedRushLarsenCellOpt;
    }
    void TestLuoRudyGeneralizedRushLarsenMethod()
    {
        EXIT_IF_PARALLEL;
        HeartConfig::Instance()->SetOdeTimeStep(0.01);
        GenerateCells();

        // Check the models really use Rush-Larsen
        TS_ASSERT_EQUALS(Warnings::Instance()->GetNumWarnings(), 0u);

        // Some coverage
        AbstractGeneralizedRushLarsenCardiacCell* p_grl_cell = dynamic_cast<AbstractGeneralizedRushLarsenCardiacCell*>(mpGeneralizedRushLarsenCell);
        TS_ASSERT(p_grl_cell);
        TS_ASSERT(!p_grl_cell->HasAnalyticJacobian());
        TS_ASSERT(!p_grl_cell->GetUseAnalyticJacobian());
        TS_ASSERT_THROWS_THIS(p_grl_cell->ForceUseOfNumericalJacobian(false),
                              "Using analytic Jacobian terms for generalised Rush-Larsen is not yet supported.");
        TS_ASSERT_THROWS_NOTHING(p_grl_cell->ForceUseOfNumericalJacobian(true));

        // Normal Luo-Rudy for comparison
        boost::shared_ptr<HeunIvpOdeSolver> p_heun_solver(new HeunIvpOdeSolver());
        CellLuoRudy1991FromCellML reference_model(p_heun_solver, mpGeneralizedRushLarsenCell->GetStimulusFunction());

        // Check GetIIonic is identical
        TS_ASSERT_DELTA(mpGeneralizedRushLarsenCell->GetIIonic(), reference_model.GetIIonic(), 1e-12);

        // Test non-stimulated cell (using ComputeExceptVoltage)
        mpGeneralizedRushLarsenCell->ComputeExceptVoltage(0.0, 1.0);
        reference_model.ComputeExceptVoltage(0.0, 1.0);

        TS_ASSERT_EQUALS(mpGeneralizedRushLarsenCell->GetNumberOfStateVariables(),
                         reference_model.GetNumberOfStateVariables());
        for (unsigned i=0; i<reference_model.GetNumberOfStateVariables(); i++)
        {
            TS_ASSERT_DELTA(mpGeneralizedRushLarsenCell->rGetStateVariables()[i],
                            reference_model.rGetStateVariables()[i], 1e-6);
        }

        // Test stimulated cell (using Compute)
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(-25.5, 1.99, 0.0));
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        mpGeneralizedRushLarsenCell->SetStimulusFunction(p_stimulus);
        OdeSolution solutions_GRL1 = mpGeneralizedRushLarsenCell->Compute(0.0, 1.0, 0.01);
        TS_ASSERT_EQUALS(solutions_GRL1.GetNumberOfTimeSteps(), 100u);

        reference_model.ResetToInitialConditions();
        reference_model.SetStimulusFunction(p_stimulus);
        OdeSolution solutions_ref = reference_model.Compute(0.0, 1.0, 0.01);

        for (unsigned i=0; i<reference_model.GetNumberOfStateVariables(); i++)
        {
            TS_ASSERT_DELTA(solutions_GRL1.rGetSolutions().back()[i],
                            solutions_ref.rGetSolutions().back()[i], 1e-2);
        }

        //Compare LuoRudy solution with general GRL1 solver solution (should match)
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        boost::shared_ptr<ZeroStimulus> p_stimulus_zero(new ZeroStimulus());
        mpGeneralizedRushLarsenCell->SetStimulusFunction(p_stimulus_zero);
        mpGeneralizedRushLarsenCell->SetTimestep(1e-3);
        mpGeneralizedRushLarsenCell->SetVoltage(-30);
        OdeSolution solutions_GRL1_stimulated_cell_order1 = mpGeneralizedRushLarsenCell->Compute(0.0, 1e-3);

        // Compare with SolveAndUpdateState for coverage
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        mpGeneralizedRushLarsenCell->SetVoltage(-30);
        mpGeneralizedRushLarsenCell->SolveAndUpdateState(0.0, 1e-3);
        for (unsigned i=0; i<mpGeneralizedRushLarsenCell->GetNumberOfStateVariables(); i++)
        {
            TS_ASSERT_DELTA(mpGeneralizedRushLarsenCell->rGetStateVariables()[i],
                            solutions_GRL1_stimulated_cell_order1.rGetSolutions().back()[i], 1e-12);
        }

        // Compare with general GRL1 method
        boost::shared_ptr<GRL1IvpOdeSolver> p_grl1_solver(new GRL1IvpOdeSolver());
        CellLuoRudy1991FromCellML reference_model_grl1(p_grl1_solver, mpGeneralizedRushLarsenCell->GetStimulusFunction());
        reference_model_grl1.ResetToInitialConditions();
        reference_model_grl1.SetStimulusFunction(p_stimulus_zero);
        reference_model_grl1.SetTimestep(1e-3);
        reference_model_grl1.SetVoltage(-30);
        OdeSolution ref_solution_grl1 = reference_model_grl1.Compute(0.0, 1e-3);

        for (unsigned i=0; i<reference_model_grl1.GetNumberOfStateVariables(); i++)
        {
            double error1 = solutions_GRL1_stimulated_cell_order1.rGetSolutions().back()[i] - ref_solution_grl1.rGetSolutions().back()[i];
            TS_ASSERT_DELTA(fabs(error1),0,5e-7);
        }

        // Test order of convergence (first-order method)

        // Get two solutions with halved stepsize
        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        reference_model_grl1.SetStimulusFunction(p_stimulus_zero);
        reference_model_grl1.SetVoltage(-30);
        mpGeneralizedRushLarsenCell->SetTimestep(0.002);
        solutions_GRL1_stimulated_cell_order1 = mpGeneralizedRushLarsenCell->Compute(0.0, 1.0);

        mpGeneralizedRushLarsenCell->ResetToInitialConditions();
        reference_model_grl1.SetStimulusFunction(p_stimulus_zero);
        reference_model_grl1.SetVoltage(-30);
        mpGeneralizedRushLarsenCell->SetTimestep(0.001);
        OdeSolution solutions_GRL1_stimulated_cell_order2 = mpGeneralizedRushLarsenCell->Compute(0.0, 1.0);

        // Get accurate solution to be used as reference solution
        //boost::shared_ptr<HeunIvpOdeSolver> p_heun_solver(new HeunIvpOdeSolver());
        reference_model.SetStimulusFunction(p_stimulus_zero);
        reference_model.SetVoltage(-30);
        reference_model.ResetToInitialConditions();
        reference_model.SetTimestep(1e-6);
        OdeSolution ref_solution = reference_model.Compute(0.0, 1.0);

        for (unsigned i=0; i<reference_model.GetNumberOfStateVariables(); i++)
        {
            double error1 = solutions_GRL1_stimulated_cell_order1.rGetSolutions().back()[i] - ref_solution.rGetSolutions().back()[i];
            double error2 = solutions_GRL1_stimulated_cell_order2.rGetSolutions().back()[i] - ref_solution.rGetSolutions().back()[i];
            TS_ASSERT_DELTA(error1/error2, 2, 0.1);
        }

        // Free memory
        delete mpGeneralizedRushLarsenCell;
//        delete mpGeneralizedRushLarsenCellOpt;
    }
Esempio n. 12
0
    void TestScaleFactorsMaleckar(void) throw (Exception)
    {
        double end_time =500;
        boost::shared_ptr<RegularStimulus> p_stimulus(new RegularStimulus(-5.6,
                                                                          6,
                                                                          1000,
                                                                          4.0));

        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver); //define the solver
        HeartConfig::Instance()->SetOdeTimeStep(0.001);
        CellMaleckar2008FromCellML atrial_ode_system(p_solver, p_stimulus);

        const std::string control_file = "control";
        const std::string first_set_file = "first_scale_factor_set";
        const std::string second_set_file = "second_scale_factor_set";
        const std::string AZD_file = "AZD_scale_factor_set";

        OdeSolution control_solution;
        OdeSolution first_scale_factor_set_solution;
        OdeSolution second_scale_factor_set_solution;
        OdeSolution AZD_scale_factor_set_solution;

        double time_step=0.001;
        double sampling_time=0.001;
        std::vector<double> state_variables= atrial_ode_system.GetInitialConditions();

        //default values
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        control_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        control_solution.WriteToFile("TestIonicModels",
                              control_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //now apply the first scale factor set, decreases outward currents
        atrial_ode_system.SetParameter("ScaleFactorGks",0.8);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",0.9);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",0.7);
        atrial_ode_system.SetParameter("ScaleFactorGK1",0.6);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        state_variables= atrial_ode_system.GetInitialConditions();
        first_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        first_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              first_set_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //now apply the secondscale factor set, this one increases inward currents
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.5);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",2.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.6);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        state_variables= atrial_ode_system.GetInitialConditions();
        second_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        second_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              second_set_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //check the AZD scale factor (vs control)
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",5.0);

        AZD_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        AZD_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              AZD_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/


        ColumnDataReader data_reader1("TestIonicModels", control_file);
        std::vector<double> voltages1 = GetVoltages(data_reader1);
        ColumnDataReader data_reader2("TestIonicModels", first_set_file);
        std::vector<double> voltages2 = GetVoltages(data_reader2);
        ColumnDataReader data_reader3("TestIonicModels", second_set_file);
        std::vector<double> voltages3 = GetVoltages(data_reader3);
        ColumnDataReader data_reader4("TestIonicModels", AZD_file);
        std::vector<double> voltages4 = GetVoltages(data_reader4);

        TS_ASSERT_EQUALS(voltages1.size(), voltages2.size());
        TS_ASSERT_EQUALS(voltages2.size(), voltages3.size());
        TS_ASSERT_EQUALS(voltages3.size(), voltages4.size());

        //create the times vector
        std::vector<double> times;
        double k =0;
        for (unsigned i=0; i<voltages2.size(); i++)
        {
          times.push_back(k);
          k=k+0.1;
        }

        CellProperties cell_properties_control(voltages1, times);
        CellProperties cell_properties_first(voltages2, times);
        CellProperties cell_properties_second(voltages3, times);
        CellProperties cell_properties_AZD(voltages4, times);

        double control_APD = cell_properties_control.GetLastActionPotentialDuration(90);
        double first_APD = cell_properties_first.GetLastActionPotentialDuration(90);
        double second_APD = cell_properties_second.GetLastActionPotentialDuration(90);
        double AZD_APD = cell_properties_AZD.GetLastActionPotentialDuration(90);

        //test that the aps are actually longer than control (all interventions were meant to have that effect except the last one)
        TS_ASSERT_LESS_THAN(control_APD, first_APD);
        TS_ASSERT_LESS_THAN(control_APD, second_APD);
        TS_ASSERT_LESS_THAN(AZD_APD, control_APD);

        //leave some hardcoded value for testing
        TS_ASSERT_DELTA(control_APD, 206.1278, 0.1);
        TS_ASSERT_DELTA(first_APD, 403.8293, 0.1);
        TS_ASSERT_DELTA(second_APD, 320.0195, 0.1);
        TS_ASSERT_DELTA(AZD_APD , 187.8073, 0.1);
    }
Esempio n. 13
0
    /**
     * Here we test that the scale factors for the TT model do what they are expected to
     * We check that they modify APD in a way that is expected.
     */
    void TestScaleFactorsForTT06(void)
    {
        double simulation_end=500;/*end time, in milliseconds for this model*/

        // Set the stimulus, the following values are appropriate for single cell simulations of this model.
        double magnitude = -38.0;   // pA/pF
        double duration = 1.0;  // ms
        double start = 100;   // ms
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(magnitude,
                                                                        duration,
                                                                        start));
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver); //define the solver
        HeartConfig::Instance()->SetOdeTimeStep(0.001);// with Forward Euler, this must be as small as 0.001.


        const std::string control_file = "TT_epi";
        const std::string mid_file = "TT_mid";
        const std::string endo_file = "TT_endo";
        const std::string LQT_file = "TT_LQT";

        CellTenTusscher2006EpiFromCellML TT_model_epi(p_solver, p_stimulus);

        TT_model_epi.SetParameter("ScaleFactorIto", 1.0);
        TT_model_epi.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_epi.SetParameter("ScaleFactorGks", 1.0);
        //run the model
        RunOdeSolverWithIonicModel(&TT_model_epi,
                                   simulation_end,
                                   control_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_mid(p_solver, p_stimulus);
        TT_model_mid.SetParameter("ScaleFactorIto", 1.0);
        TT_model_mid.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_mid.SetParameter("ScaleFactorGks", 0.25);

        RunOdeSolverWithIonicModel(&TT_model_mid,
                                   simulation_end,
                                   mid_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_endo(p_solver, p_stimulus);
        TT_model_endo.SetParameter("ScaleFactorIto", 0.165);
        TT_model_endo.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_endo.SetParameter("ScaleFactorGks", 0.66);

        RunOdeSolverWithIonicModel(&TT_model_endo,
                                   simulation_end,
                                   endo_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_LQT(p_solver, p_stimulus);
        TT_model_LQT.SetParameter("ScaleFactorIto", 1.0);
        TT_model_LQT.SetParameter("ScaleFactorGkr", 0.0);
        TT_model_LQT.SetParameter("ScaleFactorGks", 1.0);

        RunOdeSolverWithIonicModel(&TT_model_LQT,
                                   simulation_end,
                                   LQT_file,
                                   100,
                                   false);

        ColumnDataReader data_reader1("TestIonicModels", control_file);
        std::vector<double> voltages1 = GetVoltages(data_reader1);
        ColumnDataReader data_reader2("TestIonicModels", mid_file);
        std::vector<double> voltages2 = GetVoltages(data_reader2);
        ColumnDataReader data_reader3("TestIonicModels", endo_file);
        std::vector<double> voltages3 = GetVoltages(data_reader3);
        ColumnDataReader data_reader4("TestIonicModels", LQT_file);
        std::vector<double> voltages4 = GetVoltages(data_reader4);

        TS_ASSERT_EQUALS(voltages1.size(), voltages2.size());
        TS_ASSERT_EQUALS(voltages2.size(), voltages3.size());
        TS_ASSERT_EQUALS(voltages3.size(), voltages4.size());

        //create the times vector
        std::vector<double> times;
        double k =0;
        for (unsigned i=0; i<voltages2.size(); i++)
        {
          times.push_back(k);
          k=k+0.1;
        }

        CellProperties  cell_properties_control(voltages1, times);
        CellProperties  cell_properties_mid(voltages2, times);
        CellProperties  cell_properties_endo(voltages3, times);
        CellProperties  cell_properties_LQT(voltages4, times);

        double control_APD = cell_properties_control.GetLastActionPotentialDuration(90);
        double mid_APD = cell_properties_mid.GetLastActionPotentialDuration(90);
        double endo_APD = cell_properties_endo.GetLastActionPotentialDuration(90);
        double LQT_APD = cell_properties_LQT.GetLastActionPotentialDuration(90);

        TS_ASSERT_DELTA(control_APD, 300.4789, 0.1);
        TS_ASSERT_DELTA(mid_APD, 392.1871, 0.1);
        TS_ASSERT_DELTA(endo_APD, 329.2048, 0.1);
        TS_ASSERT_DELTA(LQT_APD , 347.8374, 0.1);
     }
Esempio n. 14
0
    /**
     *  Here we test the scale factors methiods for the mahajan model.
     *  The idea is to set the scale factors for the 3 different cell types (epi, mid and endo)
     *  and check that the rsulting APD makes sense if compared to experiemntal results
     */
    void TestScaleFactorsForMahajanModel(void) throw(Exception)
    {
        double end_time=300;
        double time_step=0.01;
        double sampling_time=time_step;

        // Set stimulus
        double magnitude_stimulus = -70.0;   // pA/pF
        double duration_stimulus = 1.0;  // ms
        double start_stimulus = 10.0;   // ms
        double period=1000;//here, this is ms
        boost::shared_ptr<RegularStimulus> p_stimulus(new RegularStimulus(magnitude_stimulus,
                                                                          duration_stimulus,
                                                                          period,
                                                                          start_stimulus));

        boost::shared_ptr<EulerIvpOdeSolver> p_forward_solver(new EulerIvpOdeSolver); //define the solver

        CellMahajan2008FromCellML forward_model(p_forward_solver, p_stimulus);
        boost::shared_ptr<BackwardEulerIvpOdeSolver> p_backward_solver(new BackwardEulerIvpOdeSolver(
                                    forward_model.GetNumberOfStateVariables()));

        CellMahajan2008FromCellML epicardial_model(p_backward_solver, p_stimulus);
        CellMahajan2008FromCellML endocardial_model(p_backward_solver, p_stimulus);
        CellMahajan2008FromCellML midmyocardial_model(p_backward_solver, p_stimulus);

        epicardial_model.SetParameter("ScaleFactorGks",1.0);
        epicardial_model.SetParameter("ScaleFactorIto",1.0);
        epicardial_model.SetParameter("ScaleFactorGkr",1.0);

        midmyocardial_model.SetParameter("ScaleFactorGks",0.09);
        midmyocardial_model.SetParameter("ScaleFactorIto",1.0);
        midmyocardial_model.SetParameter("ScaleFactorGkr",1.0);

        endocardial_model.SetParameter("ScaleFactorGks",0.86);
        endocardial_model.SetParameter("ScaleFactorIto",0.2);
        endocardial_model.SetParameter("ScaleFactorGkr",1.0);

        std::vector<double> state_variables_epi = epicardial_model.GetInitialConditions();
        std::vector<double> state_variables_endo = endocardial_model.GetInitialConditions();
        std::vector<double> state_variables_mid = midmyocardial_model.GetInitialConditions();

        const std::string mahajan_epi_file = "Mahajan_epi";
        const std::string mahajan_mid_file = "Mahajan_mid";
        const std::string mahajan_endo_file = "Mahajan_endo";

        // Solve and write to file

        OdeSolution epi_solution;
        epi_solution = p_backward_solver->Solve(&epicardial_model, state_variables_epi, 0, end_time, time_step, sampling_time);

        epi_solution.WriteToFile("TestIonicModels",
                                 mahajan_epi_file,
                                 "ms",//time units
                                 100,//steps per row
                                 false);/*true cleans the directory*/

        OdeSolution mid_solution;
        mid_solution = p_backward_solver->Solve(&midmyocardial_model, state_variables_mid, 0, end_time, time_step, sampling_time);

        mid_solution.WriteToFile("TestIonicModels",
                                 mahajan_mid_file,
                                 "ms",//time units
                                 100,//steps per row
                                 false);/*true cleans the directory*/

        OdeSolution endo_solution;
        endo_solution = p_backward_solver->Solve(&endocardial_model, state_variables_endo, 0, end_time, time_step, sampling_time);

        endo_solution.WriteToFile("TestIonicModels",
                                  mahajan_endo_file,
                                  "ms",//time units
                                  100,//steps per row
                                  false);/*true cleans the directory*/


        ColumnDataReader data_reader_epi("TestIonicModels", mahajan_epi_file);
        ColumnDataReader data_reader_mid("TestIonicModels", mahajan_mid_file);
        ColumnDataReader data_reader_endo("TestIonicModels", mahajan_endo_file);

        std::vector<double> times = data_reader_epi.GetValues("Time");
        std::vector<double> v_endo = data_reader_endo.GetValues("membrane_voltage");
        std::vector<double> v_epi = data_reader_epi.GetValues("membrane_voltage");
        std::vector<double> v_mid = data_reader_mid.GetValues("membrane_voltage");

        CellProperties  cell_properties_endo(v_endo, times);
        CellProperties  cell_properties_epi(v_epi, times);
        CellProperties  cell_properties_mid(v_mid, times);

        double epi_APD = cell_properties_epi.GetLastActionPotentialDuration(90);
        double endo_APD = cell_properties_endo.GetLastActionPotentialDuration(90);
        double mid_APD = cell_properties_mid.GetLastActionPotentialDuration(90);

        // Check that percentage increase from epi to mid and endo (roughly*) matches results
        // from McIntosh et al. Card Res, 45:397-409. 200 (Figure 1 and 2)
        // *this is cardiac modelling after all...
        TS_ASSERT_DELTA((mid_APD-epi_APD)*100/epi_APD, 48.6, 2); // new values because gtos and gtof were the wrong way round (in Mahajan paper - they copied and pasted from Shannon wrong!)
        TS_ASSERT_DELTA((endo_APD-epi_APD)*100/epi_APD, 15.7, 2); // ""
    }