Hi all,

I have a code that works fine for one element, but won't compile for even 
one level of refinement (8 elements). It solves a small deformation problem 
of elastic compression of a cube of side length 1. The edges of the cube 
are parallel to the coordinate axes and three of its faces are on the 
coordinate planes. The code assumes that the Young's modulus, Poisson's 
ratio and the speed at which the "top" surface of the cube is moving are 
defined in a parameters.h file.

I have attached my code to this message. When I try to refine the mesh (say 
8 elements) I get the following message from the compiler 

--------------------------------------------------------
An error occurred in line <2014> of file 
</home/skunda/built-programs/dealii-9.2.0/install/include/deal.II/lac/sparse_matrix.h>
 
in function
    number& 
dealii::SparseMatrix<number>::operator()(dealii::SparseMatrix<number>::size_type,
 
dealii::SparseMatrix<number>::size_type) [with number = double; 
dealii::SparseMatrix<number>::size_type = unsigned int]
The violated condition was:
    cols->operator()(i, j) != SparsityPattern::invalid_entry
Additional information:
    You are trying to access the matrix entry with index <0,24>, but this 
entry does not exist in the sparsity pattern of this matrix.

The most common cause for this problem is that you used a method to build 
the sparsity pattern that did not (completely) take into account all of the 
entries you will later try to write into. An example would be building a 
sparsity pattern that does not include the entries you will write into due 
to constraints on degrees of freedom such as hanging nodes or periodic 
boundary conditions. In such cases, building the sparsity pattern will 
succeed, but you will get errors such as the current one at one point or 
other when trying to write into the entries of the matrix.

Stacktrace:
-----------
#0  ./main: dealii::SparseMatrix<double>::operator()(unsigned int, unsigned 
int)
#1  ./main: Problem<3>::assemble_system()
#2  ./main: Problem<3>::run()
#3  ./main: main
--------------------------------------------------------

I am using the following 4 lines to make the sparsity pattern and the 
system matrix

    DynamicSparsityPattern dsp(dof_handler.n_dofs(), dof_handler.n_dofs());
    DoFTools::make_sparsity_pattern(dof_handler, dsp);
    sparsity_pattern.copy_from(dsp);
    system_matrix.reinit(sparsity_pattern);

I cannot see the mistake I am making while building the sparsity pattern. 
Any help is appreciated.

Best Regards,
Sudip Kunda

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/dealii/4c5a4c57-8e43-4aae-b758-be2cca281ec4n%40googlegroups.com.
// Mesh generation
#include <deal.II/grid/grid_generator.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/dofs/dof_tools.h>

// Linear algebra
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/identity_matrix.h>

// Boundary conditions
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>

// Graphical output
#include <deal.II/numerics/data_out.h>

#include <iostream>

#include "parameters.h"

using namespace dealii;

template <int dim>
class VelocityBoundaryCondition : public Function<dim> {
    public:
    VelocityBoundaryCondition(
        const double current_time,
        const double speed);

    virtual void vector_value(const Point<dim> &p,
                              Vector<double> &values) const override;

    private:
    const double current_time;
    const double speed;
};

// The variables current_time and speed will be passed to the constructor for
// the velocity boundary conditions class by the top level class for the
// problem at the moment the interpolate_boundary_conditions function is called
template <int dim>
VelocityBoundaryCondition<dim>::VelocityBoundaryCondition(
    const double current_time,
    const double speed) : Function<dim>(dim)
    , current_time(current_time)
    , speed(speed)
{}

template <int dim>
void VelocityBoundaryCondition<dim>::vector_value(const Point<dim> &/*p*/,
                                             Vector<double> &values) const {
    // The variable name p has been commented out to avoid compiler warnings
    // about unused variables
    values = 0;
    values(2) = - speed * current_time;
}

template <int dim>
class Problem {
    public:
        Problem();
        void run();

    private: // functions
        void setup_system();
        void assemble_system();
        void solve_linear_system();
        void output_results();

    private: // variables
        // Meshing
        Triangulation<dim> triangulation;
        DoFHandler<dim> dof_handler;
        FESystem<dim> fe;
        QGauss<dim> quadrature_formula;

        // Time stepping
        double current_time;
        double delta_t;
        double total_time;
        double step_no;

        // Linear algebra
        Vector<double> system_rhs;
        Vector<double> solution;
        SparsityPattern sparsity_pattern;
        SparseMatrix<double> system_matrix;
        AffineConstraints<double> constraints;

        // Output
        std::ofstream text_output_file;
        DataOut<dim> data_out;
};

template <int dim>
Problem<dim>::Problem () : 
    dof_handler(triangulation),
    fe(FE_Q<dim>(1)^dim),
    quadrature_formula(fe.degree + 1),
    text_output_file("text_output_file.txt")
    {}

template <int dim>
void Problem<dim>::run () {
    setup_system();

    current_time = 1e-3;
    assemble_system();
    solve_linear_system();
    output_results();
}

template <int dim>
void Problem<dim>::setup_system () {
    std::cout << "-- Setting up\n" << std::endl;

    // Generate mesh
    GridGenerator::hyper_cube(triangulation);
    /*triangulation.refine_global(1);*/
    dof_handler.distribute_dofs(fe);

    // Generate linear algebra objets
    solution.reinit(dof_handler.n_dofs());
    system_rhs.reinit(dof_handler.n_dofs());

    DynamicSparsityPattern dsp(dof_handler.n_dofs(), dof_handler.n_dofs());
    DoFTools::make_sparsity_pattern(dof_handler, dsp);
    sparsity_pattern.copy_from(dsp);
    system_matrix.reinit(sparsity_pattern);

    // Set boundary indices. The following boundary indexing assumes that the
    // domain is a cube of edge length 1 with sides parallel to and on the 3
    // coordinate planes.

    for (const auto &cell : triangulation.active_cell_iterators()) {
        for (const auto &face : cell->face_iterators()) {
            if (face->at_boundary()) {
                const Point<dim> face_center = face->center();

                // Face on the yz plane
                if(face_center[0] == 0) face->set_boundary_id(0);

                // Face opposite the yz plane
                if(face_center[0] == 1) face->set_boundary_id(1);

                // Face on the xz plane
                if(face_center[1] == 0) face->set_boundary_id(2);

                // Face opposite the xz plane
                if(face_center[1] == 1) face->set_boundary_id(3);

                // Face on the xy plane
                if(face_center[2] == 0) face->set_boundary_id(4);

                // Face opposite the xy plane
                if(face_center[2] == 1) face->set_boundary_id(5);

            }
        }
    }

    std::cout << "No of cells : " << triangulation.n_active_cells() << std::endl;
    std::cout << "No of vertices : " << triangulation.n_vertices() << std::endl;
    std::cout << "No of dofs : " << dof_handler.n_dofs() << std::endl;
    std::cout << "FE system dealii name : " << fe.get_name() << std::endl;

    std::cout << "\n-- Set up complete" << std::endl;
}

template <int dim>
void Problem<dim>::assemble_system () {

    std::cout << "\n-- Assembling system\n" << std::endl;

    FEValues<dim> fe_values(fe,
                            quadrature_formula,
                            update_values |
                            update_gradients |
                            update_quadrature_points |
                            update_JxW_values);

    unsigned int n_quadrature_points = fe_values.n_quadrature_points;

    // Constitutive model computation begin -------------
    
    // Declare and compute the Kronecker delta tensor
    Tensor<2, dim> kronecker_delta; 
    kronecker_delta = 0;
    kronecker_delta[0][0] = 1;
    kronecker_delta[1][1] = 1;
    kronecker_delta[2][2] = 1;

    // Compute the Lamè parameters. E and nu are in the parameters.h file.
    double lambda = (E * nu) / ((1 + nu) * (1 - 2 * nu));
    double mu     = E / (2 * (1 + nu));

    // Calculate the tangent modulus for hyperelasticity
    Tensor<4, dim> tangent_modulus;
    for(unsigned int i = 0; i < dim; i++) {
        for(unsigned int j = 0; j < dim; j++) {
            for(unsigned int k = 0; k < dim; k++) {
                for(unsigned int l = 0; l < dim; l++) {
                    tangent_modulus[i][j][k][l] = 
                        lambda * kronecker_delta[i][j] * kronecker_delta[k][l]
                        +
                        mu * (kronecker_delta[i][k] * kronecker_delta[j][l] +
                              kronecker_delta[i][l] * kronecker_delta[j][k]);
                }
            }
        }
    }

    // Constitutive model computation end --------------

    const unsigned int dofs_per_cell = fe.n_dofs_per_cell();

    FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
    Vector<double> cell_rhs(dofs_per_cell);

    // types::global_dof_index is an unsigned int of 32 bits in most cases. So
    // the following is an array of integers
    std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);

    // Loop over all the cells of the triangulation
    for (const auto &cell : dof_handler.active_cell_iterators()) {

        // Initialize the fe_values object with values relevant to the current cell
        fe_values.reinit(cell);

        // Initialize the cell matrix and the right hand side vector with zeros
        cell_matrix = 0; 
        cell_rhs = 0;

        for (unsigned int i = 0; i < dofs_per_cell; i++) {

            const unsigned int ci = fe_values
                                    .get_fe()
                                    .system_to_component_index(i)
                                    .first;

            for (unsigned int j = 0; j < dofs_per_cell; j++) {

                const unsigned int cj = fe_values
                                        .get_fe()
                                        .system_to_component_index(j)
                                        .first;

                // Quadrature loop for current cell
                for (unsigned int q = 0; q < n_quadrature_points; q++) {
                    for (unsigned int di = 0; di < dim; di++) {
                        for (unsigned int dj = 0; dj < dim; dj++) {
                            cell_matrix(i, j) +=
                                fe_values.shape_grad(i, q)[di] *
                                tangent_modulus[ci][di][cj][dj] *
                                fe_values.shape_grad(j, q)[dj] *
                                fe_values.JxW(q);
                        }
                    }
                } // End of quadrature loop
            } // End of j loop
        } // End of i loop


        // Distribute local contributions to global system
        cell->get_dof_indices(local_dof_indices);
        constraints.distribute_local_to_global(
                    cell_matrix,
                    cell_rhs,
                    local_dof_indices,
                    system_matrix,
                    system_rhs);

    } // End of loop over all cells

    // Start applying boundary conditions

    // Create an object that will hold the values of the boundary conditions
    std::map<types::global_dof_index, double> boundary_values;

    // The following are three arrays of boolean values that tell the
    // interpolate_boundary_values function which component to apply the
    // boundary values to.
    const FEValuesExtractors::Scalar x_component(0);
    const FEValuesExtractors::Scalar y_component(1);
    const FEValuesExtractors::Scalar z_component(2);

    // The face on the yz plane has boundary indicator of 0 and must be kept
    // from moving in the x direction
    VectorTools::interpolate_boundary_values(
                            dof_handler,
                            0,
                            Functions::ZeroFunction<dim>(dim),
                            boundary_values,
                            fe.component_mask(x_component));

    // The face on the xz plane has boundary indicator of 2 and must be kept
    // from moving in the y direction
    VectorTools::interpolate_boundary_values(
                            dof_handler,
                            2,
                            Functions::ZeroFunction<dim>(dim),
                            boundary_values,
                            fe.component_mask(y_component));

    // The face on the xy plane has boundary indicator of 4 and must be kept
    // from moving in the z direction
    VectorTools::interpolate_boundary_values(
                            dof_handler,
                            4,
                            Functions::ZeroFunction<dim>(dim),
                            boundary_values,
                            fe.component_mask(z_component));

    std::cout << "Current time : " << current_time << std::endl;

    // The face opposite the xy plane has boundary indicator of 5. This is
    // where the velocity boundary condition must be applied.
    VectorTools::interpolate_boundary_values(
                            dof_handler,
                            5,
                            VelocityBoundaryCondition<dim>(current_time, z1_speed),
                            boundary_values,
                            fe.component_mask(z_component));

    /*std::cout << "Before applying boundary conditions" << std::endl;*/
    for (unsigned int i = 0; i < dof_handler.n_dofs(); i++) {
        for (unsigned int j = 0; j < dof_handler.n_dofs(); j++) {
            text_output_file << system_matrix(i, j) << " ";
        } text_output_file << std::endl;
    }
    /*    std::cout << solution(i) << " " << system_rhs(i) << std::endl;*/

    // Apply the boundary values created above
    MatrixTools::apply_boundary_values(
                            boundary_values,
                            system_matrix,
                            solution,
                            system_rhs,
                            false);

    /*std::cout << "After applying boundary conditions" << std::endl;*/
    /*for (unsigned int i = 0; i < dof_handler.n_dofs(); i++)*/
    /*    std::cout << system_matrix(i, i) << std::endl;*/
    /*    std::cout << solution(i) << " " << system_rhs(i) << std::endl;*/

    std::cout << "\n-- Assembly complete" << std::endl;
}

template <int dim>
void Problem<dim>::solve_linear_system () {

    // The solver will do a maximum of 1000 iterations before giving up
    SolverControl solver_control(1000, 1e-6);
    SolverCG<Vector<double>> solver_cg(solver_control);
    solver_cg.solve(system_matrix,
                    solution,
                    system_rhs,
                    IdentityMatrix(solution.size()));

    std::cout << "\n-- " << solver_control.last_step()
        << " iterations needed to obtain convergence."
        << std::endl;
}

template <int dim>
void Problem<dim>::output_results () {
    
    std::ofstream output_file("solution.vtu");
    
    data_out.attach_dof_handler(dof_handler);

    std::vector<std::string> solution_names;

    solution_names.emplace_back("x_displacement");
    solution_names.emplace_back("y_displacement");
    solution_names.emplace_back("z_displacement");

    data_out.add_data_vector(solution, solution_names);

    data_out.build_patches();;
    data_out.write_vtu (output_file);

    std::cout << "\nResults written" << std::endl;
}

int main() {

    std::cout << "\n---- Simulation started\n" << std::endl;

    // Create the problem
    Problem<3> problem;

    // Solve the problem
    problem.run();

    std::cout << "\n---- Simulation ended" << std::endl;

    return 0;

}

Reply via email to