Merge lp:~jobh/dolfin/blockmatrix into lp:dolfin/1.0.x

Proposed by Joachim Haga
Status: Merged
Merged at revision: 5604
Proposed branch: lp:~jobh/dolfin/blockmatrix
Merge into: lp:dolfin/1.0.x
Diff against target: 177 lines (+125/-1)
5 files modified
dolfin/fem/DirichletBC.cpp (+76/-0)
dolfin/fem/DirichletBC.h (+5/-0)
dolfin/la/BlockMatrix.cpp (+31/-0)
dolfin/la/BlockMatrix.h (+4/-0)
dolfin/la/EpetraMatrix.cpp (+9/-1)
To merge this branch: bzr merge lp:~jobh/dolfin/blockmatrix
Reviewer Review Type Date Requested Status
Registry Administrators Pending
Review via email: mp+47875@code.launchpad.net

Description of the change

New functionality that I use in my current block preconditioning / block LA work

To post a comment you must log in.
Revision history for this message
Garth Wells (garth-wells) wrote :

I'm not keen on the use of GenericMatrix::getrow (I want to remove this function) because it's ambiguous in parallel.

Revision history for this message
Joachim Haga (jobh) wrote :

Hi Garth, I'll look into it later this week. I can easily get rid of use
of GM::setrow, but I'll need functionality similar to GM::getrow
(whether or not this actual interface is used). Would it be helpful if
GM::setrow is excised even if GM::getrow is still used? It seems that
the latter is better supported from the backends in parallel.

I imagine at a later stage this can be changed to work on the element
tensor level, but that is a larger change.

-j.

On 01/31/2011 07:12 PM, Garth Wells wrote:
> I'm not keen on the use of GenericMatrix::getrow (I want to remove this function) because it's ambiguous in parallel.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dolfin/fem/DirichletBC.cpp'
2--- dolfin/fem/DirichletBC.cpp 2011-01-01 22:26:49 +0000
3+++ dolfin/fem/DirichletBC.cpp 2011-01-28 22:59:27 +0000
4@@ -209,6 +209,82 @@
5 A.apply("insert");
6 }
7 //-----------------------------------------------------------------------------
8+void DirichletBC::zero_columns(GenericMatrix& A, GenericVector& b, double diag_val) const
9+{
10+ Map bv_map;
11+ get_boundary_values(bv_map, _method);
12+
13+ // Create lookup table of dofs
14+ //const uint nrows = A.size(0); // should be equal to b.size()
15+ const uint ncols = A.size(1); // should be equal to max possible dof+1
16+
17+ std::pair<uint,uint> rows = A.local_range(0);
18+ //std::pair<uint,uint> cols = A.local_range(1);
19+
20+ std::vector<char> is_bc_dof(ncols);
21+ std::vector<double> bc_dof_val(ncols);
22+ for (Map::const_iterator bv = bv_map.begin(); bv != bv_map.end(); ++bv)
23+ {
24+ is_bc_dof[bv->first] = 1;
25+ bc_dof_val[bv->first] = bv->second;
26+ }
27+
28+ // Scan through all columns of all rows, setting to zero if is_bc_dof[column]
29+ // At the same time, we collect corrections to the RHS
30+
31+ std::vector<uint> cols;
32+ std::vector<double> vals;
33+ std::vector<double> b_vals;
34+ std::vector<uint> b_rows;
35+
36+ for (uint row=rows.first; row<rows.second; row++)
37+ {
38+ // If diag_val is nonzero, the matrix is a diagonal block (nrows==ncols),
39+ // and we can set the whole BC row
40+ if (diag_val != 0.0 && is_bc_dof[row])
41+ {
42+ A.getrow(row, cols, vals);
43+ for (uint j=0; j<cols.size(); j++)
44+ vals[j] = (cols[j]==row) * diag_val;
45+ A.setrow(row, cols, vals);
46+ A.apply("insert");
47+ b.setitem(row, bc_dof_val[row]*diag_val);
48+ }
49+ else // Otherwise, we scan the row for BC columns
50+ {
51+ A.getrow(row, cols, vals);
52+ bool row_changed=false;
53+ for (uint j=0; j<cols.size(); j++)
54+ {
55+ const uint col = cols[j];
56+
57+ // Skip columns that aren't BC, and entries that are zero
58+ if (!is_bc_dof[col] || vals[j] == 0.0)
59+ continue;
60+
61+ // We're going to change the row, so make room for it
62+ if (!row_changed)
63+ {
64+ row_changed = true;
65+ b_rows.push_back(row);
66+ b_vals.push_back(0.0);
67+ }
68+
69+ b_vals.back() -= bc_dof_val[col]*vals[j];
70+ vals[j] = 0.0;
71+ }
72+ if (row_changed)
73+ {
74+ A.setrow(row, cols, vals);
75+ A.apply("insert");
76+ }
77+ }
78+ }
79+
80+ b.add(&b_vals.front(), b_rows.size(), &b_rows.front());
81+ b.apply("add");
82+}
83+//-----------------------------------------------------------------------------
84 const std::vector<std::pair<dolfin::uint, dolfin::uint> >& DirichletBC::markers()
85 {
86 return facets;
87
88=== modified file 'dolfin/fem/DirichletBC.h'
89--- dolfin/fem/DirichletBC.h 2010-12-31 21:41:41 +0000
90+++ dolfin/fem/DirichletBC.h 2011-01-28 22:59:27 +0000
91@@ -169,6 +169,11 @@
92 /// non-diagonal matrices in a block matrix.
93 void zero(GenericMatrix& A) const;
94
95+ /// Make columns associated with boundary conditions zero, and
96+ /// update the RHS to reflect the changes. Useful for non-diagonals.
97+ /// The diag_val parameter would normally be -1, 0 or 1.
98+ void zero_columns(GenericMatrix& A, GenericVector& b, double diag_val=0) const;
99+
100 /// Return boundary markers (facets stored as pairs of cells and local
101 /// facet numbers)
102 const std::vector<std::pair<uint, uint> >& markers();
103
104=== modified file 'dolfin/la/BlockMatrix.cpp'
105--- dolfin/la/BlockMatrix.cpp 2011-01-22 23:04:29 +0000
106+++ dolfin/la/BlockMatrix.cpp 2011-01-28 22:59:27 +0000
107@@ -132,3 +132,34 @@
108 }
109 }
110 //-----------------------------------------------------------------------------
111+boost::shared_ptr<GenericMatrix> BlockMatrix::schur_approximation(double symmetry) const
112+{
113+ // Currently returns [diag(C * diag(A)^-1 * B) - D]
114+ if (symmetry==0)
115+ {
116+ error("only implemented for symmetry != 0");
117+ }
118+ assert(matrices.size()==2 && matrices[0].size()==2 && matrices[1].size()==2);
119+
120+ GenericMatrix &A = *matrices[0][0];
121+ GenericMatrix &C = *matrices[1][0];
122+ GenericMatrix &D = *matrices[1][1];
123+
124+ boost::shared_ptr<GenericMatrix> S(D.copy());
125+
126+ std::vector<uint> cols_i;
127+ std::vector<double> vals_i;
128+ for (uint i=0; i<D.size(0); i++)
129+ {
130+ C.getrow(i, cols_i, vals_i);
131+ double diag_ii=0;
132+ for (uint k=0; k<cols_i.size(); k++)
133+ {
134+ const uint j=cols_i[k];
135+ const double val=vals_i[k];
136+ diag_ii -= val*val/A(j,j);
137+ }
138+ S->add(&diag_ii, 1, &i, 1, &i);
139+ }
140+ return S;
141+}
142
143=== modified file 'dolfin/la/BlockMatrix.h'
144--- dolfin/la/BlockMatrix.h 2011-01-22 23:04:29 +0000
145+++ dolfin/la/BlockMatrix.h 2011-01-28 22:59:27 +0000
146@@ -53,6 +53,10 @@
147 /// Matrix-vector product, y = Ax
148 void mult(const BlockVector& x, BlockVector& y, bool transposed=false) const;
149
150+ /// Create a crude explicit Schur approximation of S = D - C A^-1 B of (A B; C D)
151+ /// If symmetry != 0, then the caller promises that B = symmetry * transpose(C).
152+ boost::shared_ptr<GenericMatrix> schur_approximation(double symmetry=1) const;
153+
154 private:
155
156 boost::multi_array<boost::shared_ptr<GenericMatrix>, 2> matrices;
157
158=== modified file 'dolfin/la/EpetraMatrix.cpp'
159--- dolfin/la/EpetraMatrix.cpp 2011-01-24 14:28:43 +0000
160+++ dolfin/la/EpetraMatrix.cpp 2011-01-28 22:59:27 +0000
161@@ -469,7 +469,15 @@
162 void EpetraMatrix::setrow(uint row, const std::vector<uint>& columns,
163 const std::vector<double>& values)
164 {
165- dolfin_not_implemented();
166+ static bool print_msg_once=true;
167+ if (print_msg_once)
168+ {
169+ info("EpetraMatrix::setrow is implemented inefficiently");
170+ print_msg_once = false;
171+ }
172+
173+ for (uint i=0; i<columns.size(); i++)
174+ set(&values[i], 1, &row, 1, &columns[i]);
175 }
176 //-----------------------------------------------------------------------------
177 LinearAlgebraFactory& EpetraMatrix::factory() const

Subscribers

People subscribed via source and target branches