VoltageInterpolaterOntoMechanicsMesh<DIM>::VoltageInterpolaterOntoMechanicsMesh(
                                     TetrahedralMesh<DIM,DIM>& rElectricsMesh,
                                     QuadraticMesh<DIM>& rMechanicsMesh,
                                     std::vector<std::string>& rVariableNames,
                                     std::string directory,
                                     std::string inputFileNamePrefix)
{
    // Read the data from the HDF5 file
    Hdf5DataReader reader(directory,inputFileNamePrefix);

    unsigned num_timesteps = reader.GetUnlimitedDimensionValues().size();

    // set up the elements and weights for the coarse nodes in the fine mesh
    FineCoarseMeshPair<DIM> mesh_pair(rElectricsMesh, rMechanicsMesh);
    mesh_pair.SetUpBoxesOnFineMesh();
    mesh_pair.ComputeFineElementsAndWeightsForCoarseNodes(true);
    assert(mesh_pair.rGetElementsAndWeights().size()==rMechanicsMesh.GetNumNodes());

    // create and setup a writer
    Hdf5DataWriter* p_writer = new Hdf5DataWriter(*rMechanicsMesh.GetDistributedVectorFactory(),
                                                  directory,
                                                  "voltage_mechanics_mesh",
                                                  false, //don't clean
                                                  false);

    std::vector<int> columns_id;
    for (unsigned var_index = 0; var_index < rVariableNames.size(); var_index++)
    {
        std::string var_name = rVariableNames[var_index];
        columns_id.push_back( p_writer->DefineVariable(var_name,"mV") );
    }

    p_writer->DefineUnlimitedDimension("Time","msecs", num_timesteps);
    p_writer->DefineFixedDimension( rMechanicsMesh.GetNumNodes() );
    p_writer->EndDefineMode();

    assert(columns_id.size() == rVariableNames.size());

    // set up a vector to read into
    DistributedVectorFactory factory(rElectricsMesh.GetNumNodes());
    Vec voltage = factory.CreateVec();
    std::vector<double> interpolated_voltages(rMechanicsMesh.GetNumNodes());
    Vec voltage_coarse = NULL;

    for(unsigned time_step=0; time_step<num_timesteps; time_step++)
    {
        for (unsigned var_index = 0; var_index < rVariableNames.size(); var_index++)
        {
            std::string var_name = rVariableNames[var_index];
            // read
            reader.GetVariableOverNodes(voltage, var_name, time_step);
            ReplicatableVector voltage_repl(voltage);

            // interpolate
            for(unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++)
            {
                double interpolated_voltage = 0;

                Element<DIM,DIM>& element = *(rElectricsMesh.GetElement(mesh_pair.rGetElementsAndWeights()[i].ElementNum));
                for(unsigned node_index = 0; node_index<element.GetNumNodes(); node_index++)
                {
                    unsigned global_node_index = element.GetNodeGlobalIndex(node_index);
                    interpolated_voltage += voltage_repl[global_node_index]*mesh_pair.rGetElementsAndWeights()[i].Weights(node_index);
                }

                interpolated_voltages[i] = interpolated_voltage;
            }

            if(voltage_coarse!=NULL)
            {
                PetscTools::Destroy(voltage_coarse);
            }
            voltage_coarse = PetscTools::CreateVec(interpolated_voltages);
            // write
            p_writer->PutVector(columns_id[var_index], voltage_coarse);
        }
        p_writer->PutUnlimitedVariable(time_step);
        p_writer->AdvanceAlongUnlimitedDimension();
    }

    if(voltage_coarse!=NULL)
    {
        PetscTools::Destroy(voltage);
        PetscTools::Destroy(voltage_coarse);
    }

    // delete to flush
    delete p_writer;

    // Convert the new data to CMGUI format.
    // alter the directory in HeartConfig as that is where Hdf5ToCmguiConverter decides
    // where to output
    std::string config_directory = HeartConfig::Instance()->GetOutputDirectory();
    HeartConfig::Instance()->SetOutputDirectory(directory);
    Hdf5ToCmguiConverter<DIM,DIM> converter(FileFinder(directory, RelativeTo::ChasteTestOutput),
                                            "voltage_mechanics_mesh",
                                            &rMechanicsMesh,
                                            false);
    HeartConfig::Instance()->SetOutputDirectory(config_directory);
}
    /* == Mechano-electric feedback, and alternative boundary conditions ==
     *
     * Let us now run a simulation with mechano-electric feedback (MEF), and with different boundary conditions.
     */
    void TestWithMef() throw(Exception)
    {
        /* If we want to use MEF, where the stretch (in the fibre-direction) couples back to the cell
         * model and is used in stretch-activated channels (SACs), we can't just let Chaste convert
         * from cellml to C++ code as usual (see electro-physiology tutorials on how cell model files
         * are autogenerated from CellML during compilation), since these files don't use stretch and don't
         * have SACs. We have to use pycml to create a cell model class for us, rename and save it, and
         * manually add the SAC current.
         *
         * There is one example of this already in the code-base, which we will use it the following
         * simulation. It is the Noble 98 model, with a SAC added that depends linearly on stretches (>1).
         * It is found in the file !NobleVargheseKohlNoble1998WithSac.hpp, and is called
         * `CML_noble_varghese_kohl_noble_1998_basic_with_sac`.
         *
         * To add a SAC current to (or otherwise alter) your favourite cell model, you have to do the following.
         * Auto-generate the C++ code, by running the following on the cellml file:
         * `./python/ConvertCellModel.py heart/src/odes/cellml/LuoRudy1991.cellml`
         * (see [wiki:ChasteGuides/CodeGenerationFromCellML#Usingthehelperscript ChasteGuides/CodeGenerationFromCellML#Usingthehelperscript]
         *  if you want further documentation on this script).
         *
         * Copy and rename the resultant .hpp and .cpp files (which can be found in the same folder as the
         * input cellml). For example, rename everything to `LuoRudy1991WithSac`. Then alter the class
         * to overload the method `AbstractCardiacCell::SetStretch(double stretch)` to store the stretch,
         * and then implement the SAC in the `GetIIonic()` method.  `CML_noble_varghese_kohl_noble_1998_basic_with_sac`
         * provides an example of the changes that need to be made.
         *
         * Let us create a cell factory returning these Noble98 SAC cells, but with no stimulus - the
         * SAC switching on will lead be to activation.
         */
        ZeroStimulusCellFactory<CML_noble_varghese_kohl_noble_1998_basic_with_sac, 2> cell_factory;

        /* Construct two meshes are before, in 2D */
        TetrahedralMesh<2,2> electrics_mesh;
        electrics_mesh.ConstructRegularSlabMesh(0.01/*stepsize*/, 0.1/*length*/, 0.1/*width*/, 0.1/*depth*/);

        QuadraticMesh<2> mechanics_mesh;
        mechanics_mesh.ConstructRegularSlabMesh(0.02, 0.1, 0.1, 0.1 /*as above with a different stepsize*/);

        /* Collect the fixed nodes. This time we directly specify the new locations. We say the
         * nodes on X=0 are to be fixed, setting the deformed x=0, but leaving y to be free
         * (sliding boundary conditions). This functionality is described in more detail in the
         * solid mechanics tutorials.
         */
        std::vector<unsigned> fixed_nodes;
        std::vector<c_vector<double,2> > fixed_node_locations;

        fixed_nodes.push_back(0);
        fixed_node_locations.push_back(zero_vector<double>(2));

        for(unsigned i=1; i<mechanics_mesh.GetNumNodes(); i++)
        {
            double X = mechanics_mesh.GetNode(i)->rGetLocation()[0];
            if(fabs(X) < 1e-6) // ie, if X==0
            {
                c_vector<double,2> new_position;
                new_position(0) = 0.0;
                new_position(1) = ElectroMechanicsProblemDefinition<2>::FREE;

                fixed_nodes.push_back(i);
                fixed_node_locations.push_back(new_position);
            }
        }

        /* Now specify tractions on the top and bottom surfaces. For full descriptions of how
         * to apply tractions see the solid mechanics tutorials. Here, we collect the boundary
         * elements on the bottom and top surfaces, and apply inward tractions - this will have the
         * effect of stretching the tissue in the X-direction.
         */
        std::vector<BoundaryElement<1,2>*> boundary_elems;
        std::vector<c_vector<double,2> > tractions;

        c_vector<double,2> traction;

        for (TetrahedralMesh<2,2>::BoundaryElementIterator iter = mechanics_mesh.GetBoundaryElementIteratorBegin();
             iter != mechanics_mesh.GetBoundaryElementIteratorEnd();
             ++iter)
        {
            if (fabs((*iter)->CalculateCentroid()[1] - 0.0) < 1e-6) // if Y=0
            {
                BoundaryElement<1,2>* p_element = *iter;
                boundary_elems.push_back(p_element);

                traction(0) =  0.0; // kPa, since the contraction model and material law use kPa for stiffnesses
                traction(1) =  1.0; // kPa, since the contraction model and material law use kPa for stiffnesses
                tractions.push_back(traction);
            }
            if (fabs((*iter)->CalculateCentroid()[1] - 0.1) < 1e-6) // if Y=0.1
            {
                BoundaryElement<1,2>* p_element = *iter;
                boundary_elems.push_back(p_element);

                traction(0) =  0.0;
                traction(1) = -1.0;
                tractions.push_back(traction);
            }
        }

        /* Now set up the problem. We will use a compressible approach. */
        ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh);
        problem_defn.SetContractionModel(KERCHOFFS2003,0.01/*contraction model ODE timestep*/);
        problem_defn.SetUseDefaultCardiacMaterialLaw(INCOMPRESSIBLE);
        problem_defn.SetMechanicsSolveTimestep(1.0);
        /* Set the fixed node and traction info. */
        problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations);
        problem_defn.SetTractionBoundaryConditions(boundary_elems, tractions);

        /* Now say that the deformation should affect the electro-physiology */
        problem_defn.SetDeformationAffectsElectrophysiology(false /*deformation affects conductivity*/, true /*deformation affects cell models*/);

        /* Set the end time, create the problem, and solve */
        HeartConfig::Instance()->SetSimulationDuration(50.0);

        CardiacElectroMechanicsProblem<2,1> problem(INCOMPRESSIBLE,
                                                    MONODOMAIN,
                                                    &electrics_mesh,
                                                    &mechanics_mesh,
                                                    &cell_factory,
                                                    &problem_defn,
                                                    "TestCardiacElectroMechanicsWithMef");
        problem.Solve();

        /* Nothing exciting happens in the simulation as it is currently written. To get some interesting occurring,
         * alter the SAC conductance in the cell model from 0.035 to 0.35 (micro-Siemens).
         * (look for the line `const double g_sac = 0.035` in `NobleVargheseKohlNoble1998WithSac.hpp`).
         *
         * Rerun and visualise as usual, using Cmgui. By visualising the voltage on the deforming mesh, you can see that the
         * voltage gradually increases due to the SAC, since the tissue is stretched, until the threshold is reached
         * and activation occurs.
         *
         * For MEF simulations, we may want to visualise the electrical results on the electrics mesh using
         * Meshalyzer, for example to more easily visualise action potentials. This isn't (and currently
         * can't be) created by `CardiacElectroMechanicsProblem`. We can use a converter as follows
         * to post-process:
         */
        FileFinder test_output_folder("TestCardiacElectroMechanicsWithMef/electrics", RelativeTo::ChasteTestOutput);
        Hdf5ToMeshalyzerConverter<2,2> converter(test_output_folder, "voltage",
                                                 &electrics_mesh, false,
                                                 HeartConfig::Instance()->GetVisualizerOutputPrecision());

        /* Some other notes. If you want to apply time-dependent traction boundary conditions, this is possible by
         * specifying the traction in functional form - see solid mechanics tutorials. Similarly, more natural
         * 'pressure acting on the deformed body' boundary conditions are possible - see below tutorial.
         *
         * '''Robustness:''' Sometimes the nonlinear solver doesn't converge, and will give an error. This can be due to either
         * a non-physical (or not very physical) situation, or just because the current guess is quite far
         * from the solution and the solver can't find the solution (this can occur in nonlinear elasticity
         * problems if the loading is large, for example). Current work in progress is on making the solver
         * more robust, and also on parallelising the solver. One option when a solve fails is to decrease the
         * mechanics timestep.
         */

        /* Ignore the following, it is just to check nothing has changed. */
        Hdf5DataReader reader("TestCardiacElectroMechanicsWithMef/electrics", "voltage");
        unsigned num_timesteps = reader.GetUnlimitedDimensionValues().size();
        Vec voltage = PetscTools::CreateVec(electrics_mesh.GetNumNodes());
        reader.GetVariableOverNodes(voltage, "V", num_timesteps-1);
        ReplicatableVector voltage_repl(voltage);
        for(unsigned i=0; i<voltage_repl.GetSize(); i++)
        {
            TS_ASSERT_DELTA(voltage_repl[i], -81.9080, 1e-3);
        }
        PetscTools::Destroy(voltage);
    }
    // this method loads the output file from the previous method and computes the activation
    // time (defined as the time V becomes positive) for each node.
    void ConvertToActivationMap(double h, double dt, bool useSvi)
    {
        //TetrahedralMesh<3,3> mesh1;
        //double h1=0.01;    // 0.01, 0.02, 0.05
        //mesh1.ConstructRegularSlabMesh(h1, 2.0, 0.7, 0.3);
        //MeshalyzerMeshWriter<3,3> writer("Mesh0.01", "mesh01");
        //writer.WriteFilesUsingMesh(mesh1);

        TetrahedralMesh<3,3> mesh;
        double printing_dt=0.1;
        mesh.ConstructRegularSlabMesh(h, 2.0, 0.7, 0.3);

        std::stringstream input_dir;
        input_dir << "Benchmark" << "_h" << h << "_dt" << dt;
        Hdf5DataReader reader(input_dir.str(),"results");

        unsigned num_timesteps = reader.GetUnlimitedDimensionValues().size();
        DistributedVectorFactory factory(mesh.GetNumNodes());
        Vec voltage = factory.CreateVec();


        std::vector<double> activation_times(mesh.GetNumNodes(), -1.0);
        std::vector<double> last_negative_voltage(mesh.GetNumNodes(), 1.0);
        for(unsigned timestep=0; timestep<num_timesteps; timestep++)
        {
            reader.GetVariableOverNodes(voltage, "V", timestep);
            ReplicatableVector voltage_repl(voltage);

            for(unsigned i=0; i<mesh.GetNumNodes(); i++)
            {
                double V = voltage_repl[i];
                if(V > 0 && activation_times[i] < 0.0)
                {
                    double old = last_negative_voltage[i];
                    assert(old < 0);
                    activation_times[i] = (timestep-V/(V-old))*printing_dt;
                }
                else if (V<=0)
                {
                    last_negative_voltage[i]=V;
                }
            }
        }

        OutputFileHandler handler("ActivationMaps", false);
        if (PetscTools::AmMaster() == false)
        {
            return;
        }
        //Only master proceeds to write


        c_vector<double, 3> top_corner;
        top_corner[0] = 2.0;
        top_corner[1] = 0.7;
        top_corner[2] = 0.3;
        c_vector<double, 3> unit_diagonal = top_corner/norm_2(top_corner);

        std::stringstream output_file1;
        output_file1 << "diagonal" << "_h" << h << "_dt" << dt;
        if (useSvi)
        {
            output_file1 << "_svi.dat";
        }
        else
        {
            output_file1 << "_ici.dat";
        }
        out_stream p_diag_file = handler.OpenOutputFile(output_file1.str());

        for(unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            c_vector<double, 3> position =  mesh.GetNode(i)->rGetLocation();
            c_vector<double, 3>  projected_diagonal = unit_diagonal*inner_prod(unit_diagonal, position);
            double off_diagonal = norm_2(position - projected_diagonal);

            if (off_diagonal < h/3)
            {
                double distance = norm_2(position);
                (*p_diag_file) << distance<<"\t"<< activation_times[i]<<"\t"<<off_diagonal<<"\n";
                if( fabs(position[0]-2.0) < 1e-8)
                {
                    std::cout << "h, dt = " << h << ", " << dt << "\n\t";
                    std::cout << "activation_times[" << i << "] = " << activation_times[i] << "\n";
                }
            }
        }
        p_diag_file->close();

        std::stringstream output_file;
        output_file << "activation" << "_h" << h << "_dt" << dt << ".dat";
        out_stream p_file = handler.OpenOutputFile(output_file.str());

        for(unsigned i=0; i<activation_times.size(); i++)
        {
            *p_file << activation_times[i] << "\n";
        }
        p_file->close();

        for(unsigned i=0; i<activation_times.size(); i++)
        {
            if(activation_times[i] < 0.0)
            {
                std::cout << "\n\n\n**Some nodes unactivated**\n\n\n";
                output_file << "__error";
                out_stream p_file2 = handler.OpenOutputFile(output_file.str());
                p_file2->close();
                return;
            }
        }
    }