Hello everyone,
I am trying to recast a current FullMatrix<double> as a SparseMatrix<double> in order to add this matrix to another SparseMatrix<double>.
I have tried something like this:
SparseMatrix<double> Mat_Sparse;
Mat_Sparse.copy_from(Mat_Full);
Mat_Sparse_2.add(1.,Mat_Sparse);
When doing so I receive the following error:
An error occurred in line <195> of file <dealii-9.1.1/include/deal.II/lac/sparse_matrix.templates.h> in function
dealii::SparseMatrix<Number>& dealii::SparseMatrix<number>::operator=(double) [with number = double]
The violated condition was:
cols != nullptr
Additional information:
(none)
How should I amend this recasting?
Thank you!
error: no match for ‘operator+’ (operand types are ‘const dealii::SparseMatrix<double>’ and ‘dealii::SparseMatrix<double>’)
or
error: no matching function for call to ‘dealii::SparseMatrix<double>::add(double, dealii::SparseMatrix<double>&) const’
I have not added the 'const' qualifier to my definitions of either of my sparse matrices.
DynamicSparsityPattern c_sparsity(dof_handler.n_dofs(), dof_handler.n_dofs());
DoFTools::make_sparsity_pattern(dof_handler, c_sparsity, affine_constraints, true);
which I have used throughout my code with no problems.
The FullMatrix, Mat1, that I form comes from the outer product of vec1 and vec2 both of size dof_handler.n_dofs.
I create a Sparse Matrix, Mat2 that i initialize with the sparsity pattern written above. I am not seeing why Mat1 of size dof_handler.n_dofs X dof_handler.n_dofs does not fit into a sparsity pattern that's defined as DynamicSparsityPattern c_sparsity(dof_handler.n_dofs(), dof_handler.n_dofs());
I am indeed getting an error that there are not enough entries in the SparseMatrix, Mat2.
Thank you!
I have copied some code below.
I was hoping to take the outer product which is formed in a FullMatrix, called Kronecker_matrix below, multiply it by a coefficient, and add a matrix to it called nonlinear_part_full. This entire operation I have tried to put into a Sparse matrix, called Nonlinear_part, because I need to add this term to linear_part which is Sparse. I have done this simply because it was the only way I could make the addition between linear_part (Sparse) and nonlinear_part_full (FullMatrix) work all while trying to make the code as efficient as possible.
template <int dim>
void TimeStep<dim>::prepare()
{
std::cout << "TimeStep<dim>::prepare()" << std::endl;
const auto &offline_data = *p_offline_data;
linear_part.reinit(offline_data.sparsity_pattern);
auto &M_c = offline_data.mass_matrix;
auto &S_c = offline_data.stiffness_matrix;
linear_part.copy_from(M_c);
linear_part.add((1. - theta) * kappa, S_c);
linear_part_inverse.initialize(linear_part);
nonlinear_part.reinit(offline_data.sparsity_pattern);
auto &X = offline_data.inner_product_matrix;
nonlinear_part.copy_from(X);
}
template <int dim>
void TimeStep<dim>::step(Vector<double> &old_solution,double new_t)
{
const auto &offline_data = *p_offline_data;
const auto &coefficients = *offline_data.p_coefficients;
const auto &affine_constraints = offline_data.affine_constraints;
auto &manufactured = *p_manufactured;
const auto lam = coefficients.lam;
std::cout<<"lambda in Time step = "<<lam<<std::endl;
const auto M_c = linear_operator(offline_data.mass_matrix);
const auto S_c = linear_operator(offline_data.stiffness_matrix);
const auto M_u = linear_operator(offline_data.mass_matrix_unconstrained);
const auto S_u = linear_operator(offline_data.stiffness_matrix_unconstrained);
const auto X = linear_operator(offline_data.inner_product_matrix);
GrowingVectorMemory<Vector<double>> vector_memory;
typename VectorMemory<Vector<double>>::Pointer p_new_solution(vector_memory);
auto &new_solution = *p_new_solution;
new_solution = old_solution;
apply_boundary_values(offline_data, coefficients, new_t, new_solution, old_solution);
for (unsigned int m = 0; m < nonlinear_solver_limit; ++m) { Vector<double> residual = M_u * (new_solution - old_solution)
+ kappa * (1. - theta) * S_u * new_solution + theta * kappa * S_u * old_solution - kappa * (1.- theta) * lam * new_solution.norm_sqr() * new_solution - kappa * theta * lam * old_solution.norm_sqr() * old_solution;
affine_constraints.set_zero(residual);
if (residual.linfty_norm() < nonlinear_solver_tol)
break;
double old_solution_normsq = -old_solution.norm_sqr();
const unsigned int k = old_solution.size();
FullMatrix<double>Kronecker_matrix(k,k);
for(unsigned int i=0; i<k; ++i)
for(unsigned int j=0; j<k; ++j)
Kronecker_matrix(i,j) = old_solution[i]*old_solution[j];
FullMatrix<double>nonlinear_part_full;
nonlinear_part_full.copy_from(nonlinear_part);
double nonlinear_part_coef = - kappa * (1.- theta) * lam * old_solution_normsq;
double Kronecker_matrix_coef = -2.* lam * kappa * (1- theta);
nonlinear_part_full *= nonlinear_part_coef; // -k(1- theta) lambda |Psi|^2*X
Kronecker_matrix *= Kronecker_matrix_coef; //(-2.* lam * kappa * (1- theta)* Kronecker_matrix)
nonlinear_part_full.add(1.,Kronecker_matrix); //-k(1- theta) lambda |Psi|^2*X - 2k(1-theta)lambda Kronecker_matrix
SparseMatrix<double> Nonlinear_part;
Nonlinear_part.reinit(offline_data.sparsity_pattern);
Nonlinear_part.copy_from(nonlinear_part_full);
linear_part.add(1., Nonlinear_part);
auto system_matrix = linear_operator(linear_part);
SolverControl solver_control(linear_solver_limit, linear_solver_tol);
SolverGMRES<> solver(solver_control);
auto system_matrix_inverse = inverse_operator(system_matrix, solver, linear_part_inverse);
Vector<double> update = system_matrix_inverse * (-1. * residual);
affine_constraints.set_zero(update);
new_solution += update;
error: no matching function for call to ‘dealii::FullMatrix<double>::add(double, const dealii::SparseMatrix<double>&)’
linear_part.add((1. - theta) * kappa, S_c);
error: no matching function for call to ‘dealii::FullMatrix<double>::add(std::vector<unsigned int>&, dealii::FullMatrix<double>&)’
mass_matrix_unconstrained.add(local_dof_indices, cell_mass_matrix);
Alternatively if I try:
mass_matrix_unconstrained = mass_matrix_unconstrained + local_dof_indices*cell_mass_matrix;
I receive.
error: no match for ‘operator*’ (operand types are ‘std::vector<unsigned int>’ and ‘dealii::FullMatrix<double>’)
mass_matrix_unconstrained = mass_matrix_unconstrained + local_dof_indices * cell_mass_matrix;
I thought maybe this is a type error, i.e. I can't multiply a vector of int by a matrix of double but I can't seem to be able to convert the vector without error either.
Thank you,
Nikki
Ok thank you that has resolved most of the adding issue. I am still receiving the following error. It reads to me that there's still an error on the 'FullMatrix::add()' function. I have verified that they are all gone however. What else should I be looking for?
An error occurred in line <1335> of file </home/u7/nholtzer/dealii-9.1.1/include/deal.II/lac/full_matrix.h> in function
void dealii::FullMatrix< <template-parameter-1-1> >::add(dealii::FullMatrix< <template-parameter-1-1> >::size_type, dealii::FullMatrix< <template-parameter-1-1> >::size_type, const index_type*, const number2*, bool, bool) [with number2 = double; index_type = unsigned int; number = double; dealii::FullMatrix< <template-parameter-1-1> >::size_type = long unsigned int]
The violated condition was:
static_cast<typename ::dealii::internal::argument_type<void( typename std::common_type<decltype(row), decltype(this->m())>::type)>:: type>(row) < static_cast<typename ::dealii::internal::argument_type<void( typename std::common_type<decltype(row), decltype(this->m())>::type)>:: type>(this->m())
Additional information:
Index 0 is not in the half-open range [0,0). In the current case, this half-open range is in fact empty, suggesting that you are accessing an element of an empty collection such as a vector that has not been set to the correct size.
Stacktrace:
-----------
#0 /home/u7/nholtzer/dealii-9.1.1/lib/libdeal_II.g.so.9.1.1: void dealii::FullMatrix<double>::add<double, unsigned int>(unsigned long, unsigned long, unsigned int const*, double const*, bool, bool)
#1 /home/u7/nholtzer/dealii-9.1.1/lib/libdeal_II.g.so.9.1.1: void dealii::AffineConstraints<double>::distribute_local_to_global<dealii::FullMatrix<double>, dealii::Vector<double> >(dealii::FullMatrix<double> const&, dealii::Vector<double> const&, std::vector<unsigned int, std::allocator<unsigned int> > const&, dealii::FullMatrix<double>&, dealii::Vector<double>&, bool, std::integral_constant<bool, false>) const
#2 ./gravwave: void dealii::AffineConstraints<double>::distribute_local_to_global<dealii::FullMatrix<double> >(dealii::FullMatrix<double> const&, std::vector<unsigned int, std::allocator<unsigned int> > const&, dealii::FullMatrix<double>&) const
#3 ./gravwave: OfflineData<1>::assemble()
#4 ./gravwave: OfflineData<1>::prepare()
#5 ./gravwave: main
affine_constraints.distribute_local_to_global(cell_nodal_mass_matrix, local_dof_indices, nodal_mass_matrix);
I have verified that cell_nodal_mass_matrix is indeed the same size as nodal_mass_matrix.
cell_nodal_mass_matrix is initialized as:
FullMatrix<double> cell_nodal_mass_matrix(dofs_per_cell, dofs_per_cell);
and nodal_mass_matrix has the same dimensions.
local_dof_indices seem to be the problem. I see that on dealii 's website that as long as cell_nodal_mass_matrix and local_dof_indices have the same number of elements this should work.
I have defined local_dof_indices in the following way:
std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
fe_values.reinit(cell);
cell->get_dof_indices(local_dof_indices);
The number of elements are:
cell_nodal_mass_matrix: 136
local_dof_indices: 24
How would I resolve this?
Thank you,
Nikki
for (unsigned int m = 0; m < nonlinear_solver_limit; ++m) {
Vector<double> residual = M_u * (new_solution - old_solution) + kappa * (1. - theta) * S_u * new_solution + theta * kappa * S_u * old_solution - kappa * (1.- theta) * lam * new_solution.norm_sqr() * new_solution - kappa * theta * lam * old_solution.norm_sqr() * old_solution;
affine_constraints.set_zero(residual);
if (residual.linfty_norm() < nonlinear_solver_tol)
break;
double new_solution_normsq = -new_solution.norm_sqr();
const unsigned int k = new_solution.size();
FullMatrix<double>Kronecker_matrix(k,k);
for(unsigned int i=0; i<k; ++i)
for(unsigned int j=0; j<k; ++j)
Kronecker_matrix(i,j) = new_solution[i]*new_solution[j];
FullMatrix<double>nonlinear_part_full;
nonlinear_part_full.copy_from(nonlinear_part);
FullMatrix<double>nonlinear_part_inverse;
double nonlinear_part_coef = - kappa * (1.- theta) * lam * new_solution_normsq;
double Kronecker_matrix_coef = -2.* lam * kappa * (1- theta);
nonlinear_part_full *= nonlinear_part_coef; // -k(1- theta) lambda |Psi|^2*X
Kronecker_matrix *= Kronecker_matrix_coef; //(-2.* lam * kappa * (1- theta)* Kronecker_matrix)
for(unsigned int i=0; i<dofs_per_cell; ++i)
for(unsigned int j=0; j<dofs_per_cell; ++j)
nonlinear_part_full(i,j) += Kronecker_matrix(i,j);
for(unsigned int i=0; i<dofs_per_cell; ++i)
for(unsigned int j=0; j<dofs_per_cell; ++j)
nonlinear_part_full(i,j) += linear_part(i,j);
auto system_matrix = linear_operator(nonlinear_part_full);
SolverControl solver_control(linear_solver_limit, linear_solver_tol);
SolverGMRES<> solver(solver_control);
auto system_matrix_inverse = inverse_operator(system_matrix, solver, nonlinear_part_inverse);
Vector<double> update = system_matrix_inverse * (-1. * residual);
The error I'm receiving is:
An error occurred in line <179> of file </home/u7/nholtzer/dealii-9.1.1/include/deal.II/lac/full_matrix.templates.h> in function
void dealii::FullMatrix<number>::vmult(dealii::Vector<OtherNumber>&, const dealii::Vector<OtherNumber>&, bool) const [with number2 = double; number = double]
The violated condition was:
!this->empty()
Additional information:
(none)