void AbstractContinuumMechanicsSolver<DIM>::RemovePressureDummyValuesThroughLinearInterpolation()
{
    assert(mProblemDimension==DIM+1);

    // For quadratic triangles, node 3 is between nodes 1 and 2, node 4 is between 0 and 2, etc
    unsigned internal_nodes_2d[3] = {3,4,5};
    unsigned neighbouring_vertices_2d[3][2] = { {1,2}, {2,0}, {0,1} };

    // ordering for quadratic tetrahedra
    unsigned internal_nodes_3d[6] = {4,5,6,7,8,9};
    unsigned neighbouring_vertices_3d[6][2] = { {0,1}, {1,2}, {0,2}, {0,3}, {1,3}, {2,3} };

    unsigned num_internal_nodes_per_element = DIM==2 ? 3 : 6;

    // loop over elements, then loop over edges.
    for (typename AbstractTetrahedralMesh<DIM,DIM>::ElementIterator iter = mrQuadMesh.GetElementIteratorBegin();
            iter != mrQuadMesh.GetElementIteratorEnd();
            ++iter)
    {
        for(unsigned i=0; i<num_internal_nodes_per_element; i++)
        {
            unsigned global_index;
            double left_val;
            double right_val;

            if(DIM==2)
            {
                global_index = iter->GetNodeGlobalIndex( internal_nodes_2d[i] );
                unsigned vertex_0_global_index =iter->GetNodeGlobalIndex( neighbouring_vertices_2d[i][0] );
                unsigned vertex_1_global_index =iter->GetNodeGlobalIndex( neighbouring_vertices_2d[i][1] );
                left_val = mCurrentSolution[mProblemDimension*vertex_0_global_index + DIM];
                right_val = mCurrentSolution[mProblemDimension*vertex_1_global_index + DIM];
            }
            else
            {
                global_index = iter->GetNodeGlobalIndex( internal_nodes_3d[i] );
                unsigned vertex_0_global_index =iter->GetNodeGlobalIndex( neighbouring_vertices_3d[i][0] );
                unsigned vertex_1_global_index =iter->GetNodeGlobalIndex( neighbouring_vertices_3d[i][1] );
                left_val = mCurrentSolution[mProblemDimension*vertex_0_global_index + DIM];
                right_val = mCurrentSolution[mProblemDimension*vertex_1_global_index + DIM];
            }

            // this line assumes the internal node is midway between the two vertices
            mCurrentSolution[mProblemDimension*global_index + DIM] =  0.5 * (left_val + right_val);
        }
    }
}
void VtkNonlinearElasticitySolutionWriter<DIM>::Write()
{
    if (mpSolver->mOutputDirectory=="")
    {
        EXCEPTION("No output directory was given to the mechanics solver");
    }

#ifdef CHASTE_VTK
    VtkMeshWriter<DIM, DIM> mesh_writer(mpSolver->mOutputDirectory + "/vtk", "solution", true);

    // write the displacement
    std::vector<c_vector<double,DIM> > displacement(mpSolver->mrQuadMesh.GetNumNodes());
    std::vector<c_vector<double,DIM> >& r_spatial_solution = mpSolver->rGetSpatialSolution();
    for(unsigned i=0; i<mpSolver->mrQuadMesh.GetNumNodes(); i++)
    {
        for(unsigned j=0; j<DIM; j++)
        {
            displacement[i](j) = r_spatial_solution[i](j)- mpSolver->mrQuadMesh.GetNode(i)->rGetLocation()[j];
        }
    }
    mesh_writer.AddPointData("Displacement", displacement);

    // write pressures
    if (mpSolver->mCompressibilityType==INCOMPRESSIBLE)
    {
        mesh_writer.AddPointData("Pressure", mpSolver->rGetPressures());
    }

    // write the element attribute as cell data.
    std::vector<double> element_attribute;
    for(typename QuadraticMesh<DIM>::ElementIterator iter = mpSolver->mrQuadMesh.GetElementIteratorBegin();
        iter != mpSolver->mrQuadMesh.GetElementIteratorEnd();
        ++iter)
    {
        element_attribute.push_back(iter->GetAttribute());
    }
    mesh_writer.AddCellData("Attribute", element_attribute);

    // write strains if requested
    if (mWriteElementWiseStrains)
    {
        mTensorData.clear();
        mTensorData.resize(mpSolver->mrQuadMesh.GetNumElements());

        std::string name;
        switch(mElementWiseStrainType)
        {
            case DEFORMATION_GRADIENT_F:
            {
                name = "deformation_gradient_F";
                break;
            }
            case DEFORMATION_TENSOR_C:
            {
                name = "deformation_tensor_C";
                break;
            }
            case LAGRANGE_STRAIN_E:
            {
                name = "Lagrange_strain_E";
                break;
            }
            default:
            {
                NEVER_REACHED;
            }
        }

        for (typename AbstractTetrahedralMesh<DIM,DIM>::ElementIterator iter = mpSolver->mrQuadMesh.GetElementIteratorBegin();
             iter != mpSolver->mrQuadMesh.GetElementIteratorEnd();
             ++iter)
        {
            mpSolver->GetElementCentroidStrain(mElementWiseStrainType, *iter, mTensorData[iter->GetIndex()]);
        }

        mesh_writer.AddTensorCellData(name, mTensorData);
    }
//// Future..
//        if (mWriteNodeWiseStresses)
//        {
//            std::vector<c_matrix<double,DIM,DIM> > tensor_data;
//            // use recoverer
//            mesh_writer.AddTensorCellData("Stress_NAME_ME", tensor_data);
//        }

    // final write
    mesh_writer.WriteFilesUsingMesh(mpSolver->mrQuadMesh);
#endif // CHASTE_VTK
}
void ExtendedBidomainTissue<SPACE_DIM>::CreateExtracellularConductivityTensors()
{
    if (this->mpConfig->IsMeshProvided() && this->mpConfig->GetLoadMesh())
    {
        assert(this->mFibreFilePathNoExtension != "");
        switch (this->mpConfig->GetConductivityMedia())
        {
            case cp::media_type::Orthotropic:
            {
                mpExtracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;
                FileFinder ortho_file(this->mFibreFilePathNoExtension + ".ortho", RelativeTo::AbsoluteOrCwd);
                assert(ortho_file.Exists());
                mpExtracellularConductivityTensors->SetFibreOrientationFile(ortho_file);
                break;
            }

            case cp::media_type::Axisymmetric:
            {
                mpExtracellularConductivityTensors =  new AxisymmetricConductivityTensors<SPACE_DIM,SPACE_DIM>;
                FileFinder axi_file(this->mFibreFilePathNoExtension + ".axi", RelativeTo::AbsoluteOrCwd);
                assert(axi_file.Exists());
                mpExtracellularConductivityTensors->SetFibreOrientationFile(axi_file);
                break;
            }

            case cp::media_type::NoFibreOrientation:
                mpExtracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;
                break;

            default :
                NEVER_REACHED;
        }
    }
    else // no fibre orientation assumed
    {
        mpExtracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;
    }

    c_vector<double, SPACE_DIM> extra_conductivities;
    this->mpConfig->GetExtracellularConductivities(extra_conductivities);

    // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep
    // a pointer to it and we don't want it to go out of scope before Init() is called
    unsigned num_elements = this->mpMesh->GetNumElements();
    std::vector<c_vector<double, SPACE_DIM> > hetero_extra_conductivities;

    if (this->mpConfig->GetConductivityHeterogeneitiesProvided())
    {
        try
        {
            assert(hetero_extra_conductivities.size()==0);
            //initialise with the values of teh default conductivity tensor
            hetero_extra_conductivities.resize(num_elements, extra_conductivities);
        }
        catch(std::bad_alloc &badAlloc)
        {
#define COVERAGE_IGNORE
            std::cout << "Failed to allocate std::vector of size " << num_elements << std::endl;
            PetscTools::ReplicateException(true);
            throw badAlloc;
#undef COVERAGE_IGNORE
        }
        PetscTools::ReplicateException(false);

        std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > conductivities_heterogeneity_areas;
        std::vector< c_vector<double,3> > intra_h_conductivities;
        std::vector< c_vector<double,3> > extra_h_conductivities;
        HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
                                                                intra_h_conductivities,
                                                                extra_h_conductivities);
        unsigned local_element_index = 0;
        for (typename AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>::ElementIterator iter = (this->mpMesh)->GetElementIteratorBegin();
             iter != (this->mpMesh)->GetElementIteratorEnd();
             ++iter)
        {
            //unsigned element_index = iter->GetIndex();
            // if element centroid is contained in the region
            ChastePoint<SPACE_DIM> element_centroid(iter->CalculateCentroid());
            for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
            {
                // if element centroid is contained in the region
                if ( conductivities_heterogeneity_areas[region_index]->DoesContain( element_centroid ) )
                {
                    //We don't use ublas vector assignment here, because we might be getting a subvector of a 3-vector
                    for (unsigned i=0; i<SPACE_DIM; i++)
                    {
                        hetero_extra_conductivities[local_element_index][i] = extra_h_conductivities[region_index][i];
                    }
                }
            }
            local_element_index++;
        }

        mpExtracellularConductivityTensors->SetNonConstantConductivities(&hetero_extra_conductivities);
    }
    else
    {
        mpExtracellularConductivityTensors->SetConstantConductivities(extra_conductivities);
    }
    mpExtracellularConductivityTensors->Init(this->mpMesh);
}
void ExtendedBidomainTissue<SPACE_DIM>::CreateIntracellularConductivityTensorSecondCell()
{
    HeartEventHandler::BeginEvent(HeartEventHandler::READ_MESH);
    this->mpConfig = HeartConfig::Instance();
    mpIntracellularConductivityTensorsSecondCell = new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;

    // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep
    // a pointer to it and we don't want it to go out of scope before Init() is called
    unsigned num_elements = this->mpMesh->GetNumElements();
    std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities;

    c_vector<double, SPACE_DIM> intra_conductivities;
    this->mpConfig->GetIntracellularConductivities(intra_conductivities);//this one is used just for resizing

    if (this->mpConfig->GetConductivityHeterogeneitiesProvided())
    {
        try
        {
            assert(hetero_intra_conductivities.size()==0);
            hetero_intra_conductivities.resize(num_elements, intra_conductivities);
        }
        catch(std::bad_alloc &badAlloc)
        {
#define COVERAGE_IGNORE
            std::cout << "Failed to allocate std::vector of size " << num_elements << std::endl;
            PetscTools::ReplicateException(true);
            throw badAlloc;
#undef COVERAGE_IGNORE
        }
        PetscTools::ReplicateException(false);

        std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > conductivities_heterogeneity_areas;
        std::vector< c_vector<double,3> > intra_h_conductivities;
        std::vector< c_vector<double,3> > extra_h_conductivities;
        HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
                                                                intra_h_conductivities,
                                                                extra_h_conductivities);
        unsigned local_element_index = 0;
        for (typename AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>::ElementIterator it = this->mpMesh->GetElementIteratorBegin();
             it != this->mpMesh->GetElementIteratorEnd();
             ++it)
        {
            //unsigned element_index = it->GetIndex();
            // if element centroid is contained in the region
            ChastePoint<SPACE_DIM> element_centroid(it->CalculateCentroid());
            for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
            {
                if ( conductivities_heterogeneity_areas[region_index]->DoesContain(element_centroid) )
                {
                    //We don't use ublas vector assignment here, because we might be getting a subvector of a 3-vector
                    for (unsigned i=0; i<SPACE_DIM; i++)
                    {
                        hetero_intra_conductivities[local_element_index][i] = intra_h_conductivities[region_index][i];
                    }
                }
            }
            local_element_index++;
        }

        mpIntracellularConductivityTensorsSecondCell->SetNonConstantConductivities(&hetero_intra_conductivities);
    }
    else
    {
        mpIntracellularConductivityTensorsSecondCell->SetConstantConductivities(mIntracellularConductivitiesSecondCell);
    }

    mpIntracellularConductivityTensorsSecondCell->Init(this->mpMesh);
    HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
}
Example #5
0
std::vector<c_vector<unsigned, 5> > MutableMesh<ELEMENT_DIM, SPACE_DIM>::SplitLongEdges(double cutoffLength)
{
    assert(ELEMENT_DIM == 2);
    assert(SPACE_DIM == 3);

    std::vector<c_vector<unsigned, 5> > history;


    bool long_edge_exists = true;

    while(long_edge_exists)
    {
        std::set<std::pair<unsigned, unsigned> > long_edges;

        // Loop over elements to check for Long edges
        for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator elem_iter = this->GetElementIteratorBegin();
             elem_iter != this->GetElementIteratorEnd();
             ++elem_iter)
        {
            unsigned num_nodes = ELEMENT_DIM+1;

            // Loop over element vertices
            for (unsigned local_index=0; local_index<num_nodes; local_index++)
            {
                // Find locations of current node (node a) and anticlockwise node (node b)
                Node<SPACE_DIM>* p_node_a = elem_iter->GetNode(local_index);
                unsigned local_index_plus_one = (local_index+1)%num_nodes; /// \todo use iterators to tidy this up
                Node<SPACE_DIM>* p_node_b = elem_iter->GetNode(local_index_plus_one);

                // Find distance between nodes
                double distance_between_nodes = this->GetDistanceBetweenNodes(p_node_a->GetIndex(), p_node_b->GetIndex());

                if (distance_between_nodes > cutoffLength)
                {
                    if (p_node_a->GetIndex() < p_node_b->GetIndex())
                    {
                        std::pair<unsigned, unsigned> long_edge(p_node_a->GetIndex(),p_node_b->GetIndex());
                        long_edges.insert(long_edge);
                    }
                    else
                    {
                        std::pair<unsigned, unsigned> long_edge(p_node_b->GetIndex(),p_node_a->GetIndex());
                        long_edges.insert(long_edge);
                    }
                }
            }
        }

        if (long_edges.size() > 0) //Split the edges in decreasing order.
        {
            while (long_edges.size() > 0)
            {
                double longest_edge = 0.0;
                std::set<std::pair<unsigned, unsigned> >::iterator longest_edge_iter;

                //Find the longest edge in the set and split it
                for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = long_edges.begin();
                         edge_iter != long_edges.end();
                         ++edge_iter)
                {
                    unsigned node_a_global_index = edge_iter->first;
                    unsigned node_b_global_index = edge_iter->second;

                    double distance_between_nodes = this->GetDistanceBetweenNodes(node_a_global_index, node_b_global_index);

                    if (distance_between_nodes > longest_edge)
                    {
                        longest_edge = distance_between_nodes;
                        longest_edge_iter = edge_iter;
                    }
                }
                assert(longest_edge >0);

                c_vector<unsigned, 3> new_node_index = SplitEdge(this->GetNode(longest_edge_iter->first), this->GetNode(longest_edge_iter->second));

                c_vector<unsigned, 5> node_set;
                node_set(0) = new_node_index[0];
                node_set(1) = longest_edge_iter->first;
                node_set(2) = longest_edge_iter->second;
                node_set(3) = new_node_index[1];
                node_set(4) = new_node_index[2];
                history.push_back(node_set);

                // Delete pair from set
                long_edges.erase(*longest_edge_iter);
            }
        }
        else
        {
            long_edge_exists = false;
        }
    }

    return history;
}
double ElectrodesStimulusFactory<DIM>::ComputeElectrodeTotalFlux(AbstractChasteRegion<DIM>* pRegion, double stimulusMagnitude)
{
    GaussianQuadratureRule<DIM>* pQuadRule = new GaussianQuadratureRule<DIM>(2);

    //the basis functions
    c_vector<double, DIM+1> phi;

    double total_electrode_flux = 0.0;
    double ret;

    for (typename AbstractTetrahedralMesh<DIM,DIM>::NodeIterator node_iter=this->mpMesh->GetNodeIteratorBegin();
         node_iter != this->mpMesh->GetNodeIteratorEnd();
         ++node_iter)
    {
        if ( pRegion->DoesContain( (*node_iter).GetPoint() ) )
        {
            unsigned node_index = node_iter->GetIndex();
            assert(node_index < this->mpMesh->GetNumNodes());
            double contribution_of_this_node = 0.0;
            //loop over the elements where this node is contained
            for(std::set<unsigned>::iterator iter = this->mpMesh->GetNode(node_index)->rGetContainingElementIndices().begin();
                iter != this->mpMesh->GetNode(node_index)->rGetContainingElementIndices().end();
                ++iter)
            {
                Element<DIM,DIM>* p_element = this->mpMesh->GetElement(*iter);

                /*Determine jacobian for this element*/
                c_matrix<double, DIM, DIM> jacobian;
                c_matrix<double, DIM, DIM> inverse_jacobian;//unused here, but needed for the function below
                double jacobian_determinant;
                this->mpMesh->GetInverseJacobianForElement(p_element->GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);

                double contribution_of_this_element = 0.0;//...to this node
                 // loop over Gauss points
                for (unsigned quad_index=0; quad_index < pQuadRule->GetNumQuadPoints(); quad_index++)
                {
                    const ChastePoint<DIM>& quad_point = pQuadRule->rGetQuadPoint(quad_index);
                    BasisFunction::ComputeBasisFunctions(quad_point, phi);

                    double interpolated_stimulus = 0.0;
                    //loop over nodes in this element
                    for (unsigned node_index_in_element = 0; node_index_in_element < p_element->GetNumNodes(); node_index_in_element++)
                    {
                        //const Node<DIM>* p_node = p_element->GetNode(node_index_in_element);
                        assert(p_element->GetNumNodes() == DIM+1);
                        interpolated_stimulus += stimulusMagnitude*phi(node_index_in_element);
                        contribution_of_this_element += interpolated_stimulus * phi(node_index_in_element) * jacobian_determinant * pQuadRule->GetWeight(quad_index);
                    }

                }/*end of loop over gauss points*/
                contribution_of_this_node += contribution_of_this_element;

            }/*end of loop over elements where the node is contained*/
            total_electrode_flux += contribution_of_this_node;
        }/* end of if that checks if node is in the electrode*/
    }/* end of loop over nodes in the mesh*/
#ifndef NDEBUG
    int mpi_ret = MPI_Allreduce(&total_electrode_flux, &ret, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
    assert(mpi_ret == MPI_SUCCESS);
#else
    MPI_Allreduce(&total_electrode_flux, &ret, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
#endif

    //clear up memory
    delete pQuadRule;

    assert(ret < DBL_MAX);
    return ret;
}