File: custom_adapter.cpp

package info (click to toggle)
amgcl 1.4.4-1
  • links: PTS, VCS
  • area: contrib
  • in suites: sid
  • size: 5,676 kB
  • sloc: cpp: 34,043; python: 747; pascal: 258; f90: 196; makefile: 20
file content (145 lines) | stat: -rw-r--r-- 3,829 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <iostream>
#include <vector>
#include <map>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/make_solver.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/coarsening/smoothed_aggregation.hpp>
#include <amgcl/coarsening/aggregation.hpp>
#include <amgcl/relaxation/spai0.hpp>
#include <amgcl/solver/cg.hpp>
#include <amgcl/profiler.hpp>

class sparse_matrix {
    public:
        typedef std::map<int, double> sparse_row;

        sparse_matrix(int n, int m) : _n(n), _m(m), _rows(n) { }

        int nrows() const { return _n; }
        int ncols() const { return _m; }

        // Get a value at row i and column j
        double operator()(int i, int j) const {
            sparse_row::const_iterator elem = _rows[i].find(j);
            return elem == _rows[i].end() ? 0.0 : elem->second;
        }

        // Get reference to a value at row i and column j
        double& operator()(int i, int j) { return _rows[i][j]; }

        // Access the whole row
        const sparse_row& operator[](int i) const { return _rows[i]; }
    private:
        int _n, _m;
        std::vector<sparse_row> _rows;
};

namespace amgcl {
namespace backend {

// Let AMGCL know the value type of our matrix:
template <> struct value_type<sparse_matrix> {
    typedef double type;
};

// Let AMGCL know the size of our matrix:
template<> struct rows_impl<sparse_matrix> {
    static int get(const sparse_matrix &A) { return A.nrows(); }
};

template<> struct cols_impl<sparse_matrix> {
    static int get(const sparse_matrix &A) { return A.ncols(); }
};

template<> struct nonzeros_impl<sparse_matrix> {
    static int get(const sparse_matrix &A) {
        int n = A.nrows(), nnz = 0;
        for(int i = 0; i < n; ++i)
            nnz += A[i].size();
        return nnz;
    }
};

// Allow AMGCL to iterate over the rows of our matrix:
template<> struct row_iterator<sparse_matrix> {
    struct iterator {
        sparse_matrix::sparse_row::const_iterator _it, _end;

        iterator(const sparse_matrix &A, int row)
            : _it(A[row].begin()), _end(A[row].end()) { }

        // Check if we are at the end of the row.
        operator bool() const {
            return _it != _end;
        }

        // Advance to the next nonzero element.
        iterator& operator++() {
            ++_it;
            return *this;
        }

        // Column number of the current nonzero element.
        int col() const { return _it->first; }

        // Value of the current nonzero element.
        double value() const { return _it->second; }
    };

    typedef iterator type;
};

template<> struct row_begin_impl<sparse_matrix> {
    typedef row_iterator<sparse_matrix>::type iterator;
    static iterator get(const sparse_matrix &A, int row) {
        return iterator(A, row);
    }
};

} // namespace backend


profiler<> prof;
} // namespace amgcl

using amgcl::prof;

int main() {
    // Discretize a 1D Poisson problem
    const int n = 10000;

    auto t_total = prof.scoped_tic("total");
    sparse_matrix A(n, n);
    for(int i = 0; i < n; ++i) {
        if (i == 0 || i == n - 1) {
            // Dirichlet boundary condition
            A(i,i) = 1.0;
        } else {
            // Internal point.
            A(i, i-1) = -1.0;
            A(i, i)   =  2.0;
            A(i, i+1) = -1.0;
        }
    }

    // Create an AMGCL solver for the problem.
    typedef amgcl::backend::builtin<double> Backend;
    amgcl::make_solver<
        amgcl::amg<
            Backend,
            amgcl::coarsening::aggregation,
            amgcl::relaxation::spai0
            >,
        amgcl::solver::cg<Backend>
        > solve( A );

    std::cout << solve.precond() << std::endl;

    auto t_solve = prof.scoped_tic("solve");
    std::vector<double> f(n, 1.0), x(n, 0.0);
    solve(f, x);

    std::cout << prof << std::endl;
}