8000 Power iteration: check norm of initial vector by peterrum · Pull Request #18178 · dealii/dealii · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Power iteration: check norm of initial vector #18178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

peterrum
Copy link
Member

... and early return if norm is zero. This might happen if all degrees of freedoms (on a coarse grid/single cell) are constrained.

Comment on lines 2400 to 2406
eigenvector /= eigenvector.l2_norm();

const auto norm = eigenvector.l2_norm();

if (norm == 0.0)
return 1.0;

eigenvector /= norm;
Copy link
Member
@bangerth bangerth Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's the wrong solution. If you pass in a zero vector by accident, the function pretends that the largest eigenvalue of the operator is one. That's just not true.

The function should probably document that one must provide a non-zero vector and that if the vector is zero throw an exception that one can catch.

@peterrum
Copy link
Member Author
peterrum commented Mar 1, 2025

I think that's the wrong solution. If you pass in a zero vector by accident, the function pretends that the largest eigenvalue of the operator is one. That's just not true.
The function should probably document that one must provide a non-zero vector and that if the vector is zero throw an exception that one can catch.

One should note that this is the internal eigenvalue estimation of PreconditionChebyshev and PreconditionRelaxation. They use either EigenvalueAlgorithm::lanczos or EigenvalueAlgorithm::power_iteration. The first one returned for the described system (all dofs are constrained; as sometimes is the case on the coarse grid) ev_min=ev_max=1.0 (which makes sense if one considers the matrix corresponding to a fully constrained system to be a identity matrix). The second crashed because there is a division by 0. This PR tries to fix this behavior.

In the new commit, I have moved the if-statement from internal::power_iteration() to internal::estimate_eigenvalues(). Furthermore, I have added a simplified test which checks the desired behavior.

This is the best solution I can come up. I am open for suggestions how to alternatively fix this issue.

Copy link
Member
@kronbichler kronbichler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is much clearer, so I'd go with this setup.

Copy link
Member
@blaisb blaisb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this a lot. Good work.

@masterleinad masterleinad requested a review from bangerth March 8, 2025 17:16
if (data.eigenvalue_algorithm == internal::EigenvalueAlgorithm::lanczos)
// note: temp_vector1 only contains zeroes, which happens if all dofs
// are constrained, there is nothing to do
if (temp_vector1.l2_norm() != 0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use all_zero() here? We do require that for the vector space vector concept (which this template doesn't check for).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, that should be cheaper.

Copy link
Member
@bangerth bangerth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is much clearer.

if (data.eigenvalue_algorithm == internal::EigenvalueAlgorithm::lanczos)
// note: temp_vector1 only contains zeroes, which happens if all dofs
// are constrained, there is nothing to do
if (temp_vector1.l2_norm() != 0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, that should be cheaper.

Comment on lines +2454 to +2456
// note: temp_vector1 only contains zeroes, which happens if all dofs
// are constrained, there is nothing to do
if (temp_vector1.l2_norm() != 0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment has the wrong grammar. "temp_vector1 only contains zeroes" is a statement, but the statement is not generally true. I think what you want to say is something like this:

Suggested change
// note: temp_vector1 only contains zeroes, which happens if all dofs
// are constrained, there is nothing to do
if (temp_vector1.l2_norm() != 0.0)
// We want to run the power iteration starting with temp_vector1, but for that it
// needs to be a nonzero vector. However, there are situations where it only contains
// zeroes (e.g., if all dofs are constrained). If that is the case, there is nothing to do.
if (temp_vector1.l2_norm() != 0.0)

@bangerth
Copy link
Member

Do you think we could add a test that checks that this continues to work?

@bangerth
Copy link
Member
bangerth commented May 7, 2025

@peterrum Ping?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0