1
// Copyright (C) 2008 Anders Logg.
2
// Licensed under the GNU LGPL Version 2.1.
4
// First added: 2008-05-15
5
// Last changed: 2008-05-15
7
#include <dolfin/common/Array.h>
8
#include "LinearAlgebraFactory.h"
9
#include "GenericMatrix.h"
10
#include "GenericVector.h"
11
#include "SparsityPattern.h"
12
#include "SingularSolver.h"
14
using namespace dolfin;
16
//-----------------------------------------------------------------------------
17
SingularSolver::SingularSolver(SolverType solver_type,
18
PreconditionerType pc_type)
19
: Parametrized(), linear_solver(solver_type, pc_type), B(0), y(0), c(0)
21
// Set parameters for linear solver
22
linear_solver.set("parent", *this);
24
//-----------------------------------------------------------------------------
25
SingularSolver::~SingularSolver()
31
//-----------------------------------------------------------------------------
32
dolfin::uint SingularSolver::solve(const GenericMatrix& A,
33
GenericVector& x, const GenericVector& b)
35
message("Solving singular system...");
37
// Initialize data structures for extended system
40
// Create extended system
43
// Solve extended system
44
const uint num_iterations = linear_solver.solve(*B, *y, *c);
47
x.init(y->size() - 1);
48
real* vals = new real[y->size()];
53
return num_iterations;
55
//-----------------------------------------------------------------------------
56
dolfin::uint SingularSolver::solve(const GenericMatrix& A,
57
GenericVector& x, const GenericVector& b,
58
const GenericMatrix& M)
60
message("Solving singular system...");
62
// Initialize data structures for extended system
65
// Create extended system
68
// Solve extended system
69
const uint num_iterations = linear_solver.solve(*B, *y, *c);
72
x.init(y->size() - 1);
73
real* vals = new real[y->size()];
78
return num_iterations;
80
//-----------------------------------------------------------------------------
81
void SingularSolver::init(const GenericMatrix& A)
83
// Check size of system
84
if (A.size(0) != A.size(1))
85
error("Matrix must be square.");
87
error("Matrix size must be non-zero.");
90
const uint N = A.size(0);
92
// Check if we have already initialized system
93
if (B && B->size(0) == N + 1 && B->size(1) == N + 1)
96
cout << "Initializing" << endl;
98
// Delete any old data
103
// Create sparsity pattern for B
104
SparsityPattern s(N + 1, N + 1);
106
// Copy sparsity pattern for A and last column
109
for (uint i = 0; i < N; i++)
112
A.getrow(i, columns, dummy);
114
// Copy columns to array
115
const uint num_cols = columns.size() + 1;
116
uint* cols = new uint[num_cols];
117
for (uint j = 0; j < columns.size(); j++)
118
cols[j] = columns[j];
121
cols[num_cols - 1] = N;
123
// Insert into sparsity pattern
124
s.insert(1, &i, num_cols, cols);
126
// Delete temporary array
131
const uint num_cols = N;
132
uint* cols = new uint[num_cols];
133
for (uint j = 0; j < num_cols; j++)
136
s.insert(1, &row, num_cols, cols);
139
// Create matrix and vector
140
B = A.factory().createMatrix();
141
y = A.factory().createVector();
142
c = A.factory().createVector();
147
//-----------------------------------------------------------------------------
148
void SingularSolver::create(const GenericMatrix& A, const GenericVector& b,
149
const GenericMatrix* M)
157
// Copy rows from A into B
158
const uint N = A.size(0);
161
for (uint i = 0; i < N; i++)
163
A.getrow(i, columns, values);
164
B->setrow(i, columns, values);
167
// Compute lumped mass matrix
172
GenericVector* ones = A.factory().createVector();
173
GenericVector* z = A.factory().createVector();
178
for (uint i = 0; i < N; i++)
188
for (uint i = 0; i < N; i++)
196
B->setrow(N, columns, values);
199
for (uint i = 0; i < N; i++)
200
B->set(&values[i], 1, &i, 1, &N);
202
// Copy values from b into c
203
real* vals = new real[N + 1];
213
//-----------------------------------------------------------------------------