1
// Copyright (C) 2008-2010 Kent-Andre Mardal and Garth N. Wells
3
// This file is part of DOLFIN.
5
// DOLFIN is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU Lesser General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
10
// DOLFIN is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public License
16
// along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
18
// Modified by Anders Logg 2011-2012
21
// Last changed: 2012-08-22
25
// Included here to avoid a C++ problem with some MPI implementations
26
#include <dolfin/common/MPI.h>
29
#include <Amesos_BaseSolver.h>
30
#include <Amesos_ConfigDefs.h>
31
#include <Amesos_Klu.h>
32
#include <Epetra_FECrsMatrix.h>
33
#include <Epetra_FEVector.h>
34
#include <Epetra_LinearProblem.h>
35
#include <Epetra_MultiVector.h>
37
#include <dolfin/common/MPI.h>
38
#include <dolfin/common/NoDeleter.h>
39
#include <dolfin/common/Timer.h>
40
#include "GenericLinearOperator.h"
41
#include "GenericVector.h"
42
#include "EpetraMatrix.h"
43
#include "EpetraVector.h"
45
#include "EpetraLUSolver.h"
47
using namespace dolfin;
49
//-----------------------------------------------------------------------------
50
std::vector<std::pair<std::string, std::string> >
51
EpetraLUSolver::methods()
53
static std::vector<std::pair<std::string, std::string> > m;
55
m.push_back(std::make_pair("default", "default LU solver"));
56
m.push_back(std::make_pair("umfpack", "UMFPACK (Unsymmetric MultiFrontal sparse LU factorization)"));
57
m.push_back(std::make_pair("mumps", "MUMPS (MUltifrontal Massively Parallel Sparse direct Solver)"));
58
m.push_back(std::make_pair("klu", "Trilinos KLU"));
62
//-----------------------------------------------------------------------------
63
std::string EpetraLUSolver::choose_method(std::string method) const
66
if (method == "default")
68
if (factory.Query("Amesos_Mumps"))
69
method = "Amesos_Mumps";
70
else if (factory.Query("Amesos_Umfpack"))
71
method = "Amesos_Umfpack";
72
else if (factory.Query("Amesos_Klu"))
73
method = "Amesos_Klu";
76
dolfin_error("EpetraLUSolver.cpp",
77
"choose default Epetra LU solver",
78
"No methods available");
81
else if (method == "umfpack")
82
method = "Amesos_Umfpack";
83
else if (method == "mumps")
84
method = "Amesos_mumps";
85
else if (method == "klu")
86
method = "Amesos_Klu";
89
dolfin_error("EpetraLUSolver.cpp",
90
"solve linear system",
91
"Unknown LU solver method \"%s\". "
92
"Use list_lu_solver_methods() to list available methods",
98
//-----------------------------------------------------------------------------
99
Parameters EpetraLUSolver::default_parameters()
101
Parameters p(LUSolver::default_parameters());
102
p.rename("epetra_lu_solver");
105
//-----------------------------------------------------------------------------
106
EpetraLUSolver::EpetraLUSolver(std::string method)
107
: symbolic_factorized(false),
108
numeric_factorized(false),
109
linear_problem(new Epetra_LinearProblem)
111
// Set default parameters
112
parameters = default_parameters();
115
_method = choose_method(method);
119
solver.reset(factory.Create(_method, *linear_problem));
121
// Check that solver was initialized correctly
124
dolfin_error("EpetraLUSolver.cpp",
125
"create Epetra LU solver",
126
"Epetra was not able to create linear solver \"%s\"",
130
//-----------------------------------------------------------------------------
131
EpetraLUSolver::EpetraLUSolver(std::shared_ptr<const GenericLinearOperator> A,
133
: symbolic_factorized(false),
134
numeric_factorized(false),
135
linear_problem(new Epetra_LinearProblem)
137
// Set default parameters
138
parameters = default_parameters();
141
_matA = as_type<const EpetraMatrix>(require_matrix(A));
142
dolfin_assert(_matA);
145
_method = choose_method(method);
149
solver.reset(factory.Create(_method, *linear_problem));
151
// Check that solver was initialized correctly
154
dolfin_error("EpetraLUSolver.cpp",
155
"create Epetra LU solver",
156
"Epetra was not able to create linear solver \"%s\"",
160
//-----------------------------------------------------------------------------
161
EpetraLUSolver::~EpetraLUSolver()
165
//-----------------------------------------------------------------------------
167
EpetraLUSolver::set_operator(std::shared_ptr<const GenericLinearOperator> A)
169
dolfin_assert(linear_problem);
171
_matA = as_type<const EpetraMatrix>(require_matrix(A));
172
dolfin_assert(_matA);
173
linear_problem->SetOperator(_matA->mat().get());
175
symbolic_factorized = false;
176
numeric_factorized = false;
178
//-----------------------------------------------------------------------------
179
const GenericLinearOperator& EpetraLUSolver::get_operator() const
183
dolfin_error("EpetraLUSolver.cpp",
184
"access operator for Epetra LU solver",
185
"Operator has not been set");
189
//-----------------------------------------------------------------------------
190
std::size_t EpetraLUSolver::solve(GenericVector& x, const GenericVector& b)
192
Timer timer("Epetra LU solver");
194
dolfin_assert(linear_problem);
195
dolfin_assert(solver);
198
if (parameters["report"] && dolfin::MPI::rank(MPI_COMM_WORLD) == 0)
200
if (solver->UseTranspose())
202
info("Solving linear system transposed of size %d x %d using Epetra LU solver (%s).",
203
_matA->size(0), _matA->size(1), _method.c_str());
207
info("Solving linear system of size %d x %d using Epetra LU solver (%s).",
208
_matA->size(0), _matA->size(1), _method.c_str());
213
EpetraVector& _x = as_type<EpetraVector>(x);
214
const EpetraVector& _b = as_type<const EpetraVector>(b);
216
// Get operator matrix
217
const Epetra_RowMatrix* A = linear_problem->GetMatrix();
220
dolfin_error("EpetraLUSolver.cpp",
221
"solve linear system using Epetra LU solver",
222
"Operator has not been set");
225
const std::size_t N = A->NumGlobalCols64();
228
dolfin_error("EpetraLUSolver.cpp",
229
"solve linear system using Epetra LU solver",
230
"Non-matching dimensions for linear system");
233
// Initialize solution vector
236
_matA->init_vector(x, 1);
240
// Set LHS and RHS vectors
241
linear_problem->SetRHS(_b.vec().get());
242
linear_problem->SetLHS(_x.vec().get());
244
// Get some parameters
245
const bool reuse_fact = parameters["reuse_factorization"];
246
const bool same_pattern = parameters["same_nonzero_pattern"];
248
// Perform symbolic factorization
249
if ( (reuse_fact || same_pattern) && !symbolic_factorized )
251
AMESOS_CHK_ERR(solver->SymbolicFactorization());
252
symbolic_factorized = true;
254
else if (!reuse_fact && !same_pattern)
256
AMESOS_CHK_ERR(solver->SymbolicFactorization());
257
symbolic_factorized = true;
260
// Perform numeric factorization
261
if (reuse_fact && !numeric_factorized)
263
AMESOS_CHK_ERR(solver->NumericFactorization());
264
numeric_factorized = true;
266
else if (!reuse_fact)
268
AMESOS_CHK_ERR(solver->NumericFactorization());
269
numeric_factorized = true;
273
AMESOS_CHK_ERR(solver->Solve());
275
// Update ghost values
276
_x.update_ghost_values();
280
//-----------------------------------------------------------------------------
281
std::size_t EpetraLUSolver::solve(const GenericLinearOperator& A,
283
const GenericVector& b)
285
return solve(as_type<const EpetraMatrix>(require_matrix(A)),
286
as_type<EpetraVector>(x),
287
as_type<const EpetraVector>(b));
289
//-----------------------------------------------------------------------------
290
std::size_t EpetraLUSolver::solve(const EpetraMatrix& A, EpetraVector& x,
291
const EpetraVector& b)
293
std::shared_ptr<const EpetraMatrix> Atmp(&A, NoDeleter());
297
//-----------------------------------------------------------------------------
298
std::size_t EpetraLUSolver::solve_transpose(GenericVector& x,
299
const GenericVector& b)
301
dolfin_assert(solver);
302
solver->SetUseTranspose(true);
303
std::size_t out = solve(x, b);
304
solver->SetUseTranspose(false);
307
//-----------------------------------------------------------------------------
308
std::size_t EpetraLUSolver::solve_transpose(const GenericLinearOperator& A,
310
const GenericVector& b)
312
dolfin_assert(solver);
313
solver->SetUseTranspose(true);
314
std::size_t out = solve(A, x, b);
315
solver->SetUseTranspose(false);
318
//-----------------------------------------------------------------------------
319
std::size_t EpetraLUSolver::solve_transpose(const EpetraMatrix& A,
321
const EpetraVector& b)
323
dolfin_assert(solver);
324
solver->SetUseTranspose(true);
325
std::size_t out = solve(A, x, b);
326
solver->SetUseTranspose(false);
329
//-----------------------------------------------------------------------------
330
std::string EpetraLUSolver::str(bool verbose) const
332
dolfin_not_implemented();
333
return std::string();
335
//-----------------------------------------------------------------------------