Skip to content

Commit 5b27fa7

Browse files
authored
Merge pull request #4079 from roystgnr/precondition_constraint_matrix
Precondition constraint matrix
2 parents 05c9ac4 + 704b2dd commit 5b27fa7

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

include/mesh/mesh_base.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1723,13 +1723,19 @@ class MeshBase : public ParallelObject
17231723
* existing node, a new NodeElem will be added to the mesh on which
17241724
* to store the new unconstrained degree(s) of freedom.
17251725
*
1726+
* If \p precondition_constraint_operator is true, then the values
1727+
* of those new unconstrained degrees of freedom may be scaled to
1728+
* improve the conditioning of typical PDE matrices integrated on
1729+
* constrained mesh elements.
1730+
*
17261731
* \p T for the constraint_operator in this function should be \p
17271732
* Real or \p Number ... and the data should be \p Real - we just
17281733
* allow complex \p T for the sake of subclasses which have to be
17291734
* configured and compiled with only one runtime option.
17301735
*/
17311736
template <typename T>
1732-
void copy_constraint_rows(const SparseMatrix<T> & constraint_operator);
1737+
void copy_constraint_rows(const SparseMatrix<T> & constraint_operator,
1738+
bool precondition_constraint_operator = false);
17331739

17341740
/**
17351741
* Prints (from processor 0) all mesh constraint rows. If \p

src/apps/calculator.C

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ int main(int argc, char ** argv)
261261

262262
old_es.init();
263263

264+
old_es.print_info();
265+
264266
goal_function =
265267
std::make_unique<WrappedFunctor<Number>>(ParsedFunction<Number>(calcfunc));
266268
}

src/mesh/mesh_base.C

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,8 @@ MeshBase::copy_constraint_rows(const MeshBase & other_mesh)
20342034

20352035
template <typename T>
20362036
void
2037-
MeshBase::copy_constraint_rows(const SparseMatrix<T> & constraint_operator)
2037+
MeshBase::copy_constraint_rows(const SparseMatrix<T> & constraint_operator,
2038+
bool precondition_constraint_operator)
20382039
{
20392040
LOG_SCOPE("copy_constraint_rows(mat)", "MeshBase");
20402041

@@ -2070,6 +2071,14 @@ MeshBase::copy_constraint_rows(const SparseMatrix<T> & constraint_operator)
20702071
columns_type;
20712072
columns_type columns(constraint_operator.n());
20722073

2074+
// If we need to precondition the constraint operator (e.g. it's an
2075+
// unpreconditioned extraction operator for a Flex IGA matrix),
2076+
// we'll want to keep track of the sum of each column, because we'll
2077+
// be dividing each column by that sum (Jacobi preconditioning on
2078+
// the right, which then leads to symmetric preconditioning on a
2079+
// physics Jacobian).
2080+
std::unordered_map<dof_id_type, Real> column_sums;
2081+
20732082
// Work in parallel, though we'll have to sync shortly
20742083
for (auto i : make_range(constraint_operator.row_start(),
20752084
constraint_operator.row_stop()))
@@ -2174,6 +2183,9 @@ MeshBase::copy_constraint_rows(const SparseMatrix<T> & constraint_operator)
21742183
++pids[constrained_node.processor_id()];
21752184
}
21762185

2186+
if (precondition_constraint_operator)
2187+
column_sums[j] = total_scaling;
2188+
21772189
libmesh_error_msg_if
21782190
(!total_entries,
21792191
"Empty column " << j <<
@@ -2246,8 +2258,23 @@ MeshBase::copy_constraint_rows(const SparseMatrix<T> & constraint_operator)
22462258

22472259
auto p = node_to_elem_ptrs[&constraining_node];
22482260

2249-
const Real coef = libmesh_real(values[jj]);
2261+
Real coef = libmesh_real(values[jj]);
22502262
libmesh_assert_equal_to(coef, values[jj]);
2263+
2264+
// If we're preconditioning and we created a nodeelem then
2265+
// we can scale the meaning of that nodeelem's value to give
2266+
// us a better-conditioned matrix after the constraints are
2267+
// applied.
2268+
if (precondition_constraint_operator)
2269+
if (auto sum_it = column_sums.find(indices[jj]);
2270+
sum_it != column_sums.end())
2271+
{
2272+
const Real scaling = sum_it->second;
2273+
2274+
if (scaling > TOLERANCE)
2275+
coef /= scaling;
2276+
}
2277+
22512278
constraint_row.emplace_back(std::make_pair(p, coef));
22522279
}
22532280

@@ -2341,11 +2368,13 @@ std::string MeshBase::get_local_constraints(bool print_nonlocal) const
23412368

23422369
// Explicit instantiations for our template function
23432370
template LIBMESH_EXPORT void
2344-
MeshBase::copy_constraint_rows(const SparseMatrix<Real> & constraint_operator);
2371+
MeshBase::copy_constraint_rows(const SparseMatrix<Real> & constraint_operator,
2372+
bool precondition_constraint_operator);
23452373

23462374
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
23472375
template LIBMESH_EXPORT void
2348-
MeshBase::copy_constraint_rows(const SparseMatrix<Complex> & constraint_operator);
2376+
MeshBase::copy_constraint_rows(const SparseMatrix<Complex> & constraint_operator,
2377+
bool precondition_constraint_operator);
23492378
#endif
23502379

23512380

0 commit comments

Comments
 (0)