Skip to content
Snippets Groups Projects
Commit 7077ed86 authored by Patrick Jaap's avatar Patrick Jaap
Browse files

setupLaplacian: Add optional diagonal regularization


This generalizes the necessary regularization for the umfpacktest and
makes it usable for other algorithms. A hint in Cholmodtest is added and
the other tests using this methods are kept unchanged.

The method was also cleaned up and modernized.

Co-authored-by: Santiago Ospina De Los Ríos's avatarSantiago Ospina De Los Ríos <sospinar@gmail.com>
parent b60d796c
No related branches found
No related tags found
1 merge request!539setupLaplacian: Add optional diagonal regularization
...@@ -5,6 +5,8 @@ SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception ...@@ -5,6 +5,8 @@ SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
# Master (will become release 2.10) # Master (will become release 2.10)
- Improve testing support on Laplacian matrices with an optional diagonal regularization parameter.
- Base the implementation of `VariableBlockVector` on `std::vector` as the storage type. Note that - Base the implementation of `VariableBlockVector` on `std::vector` as the storage type. Note that
this prevents from using `bool` as block type that was possible before. this prevents from using `bool` as block type that was possible before.
......
...@@ -39,6 +39,7 @@ bool test() ...@@ -39,6 +39,7 @@ bool test()
// fill matrix with external method // fill matrix with external method
BCRSMatrix<FieldMatrix<double,bs,bs>> A; BCRSMatrix<FieldMatrix<double,bs,bs>> A;
// no regularization, A may be singular!
setupLaplacian(A, N); setupLaplacian(A, N);
BlockVector<FieldVector<double,bs>> b,x; BlockVector<FieldVector<double,bs>> b,x;
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
// vi: set et ts=4 sw=2 sts=2: // vi: set et ts=4 sw=2 sts=2:
#ifndef LAPLACIAN_HH #ifndef LAPLACIAN_HH
#define LAPLACIAN_HH #define LAPLACIAN_HH
#include <optional>
#include <dune/istl/bcrsmatrix.hh> #include <dune/istl/bcrsmatrix.hh>
#include <dune/common/fvector.hh> #include <dune/common/fvector.hh>
#include <dune/common/scalarmatrixview.hh> #include <dune/common/scalarmatrixview.hh>
...@@ -38,15 +41,22 @@ void setupSparsityPattern(Dune::BCRSMatrix<B,Alloc>& A, int N) ...@@ -38,15 +41,22 @@ void setupSparsityPattern(Dune::BCRSMatrix<B,Alloc>& A, int N)
} }
} }
/* \brief Setup a FD Laplace matrix on a square 2D grid
*
* \param A The resulting matrix
* \param N Number of grid nodes per direction
* \param reg (optional) Regularization added to the diagonal to ensure a good condition number
*/
template<class B, class Alloc> template<class B, class Alloc>
void setupLaplacian(Dune::BCRSMatrix<B,Alloc>& A, int N) void setupLaplacian(Dune::BCRSMatrix<B,Alloc>& A,
int N,
std::optional<typename Dune::BCRSMatrix<B,Alloc>::field_type> reg = {} )
{ {
typedef typename Dune::BCRSMatrix<B,Alloc>::field_type FieldType; using field_type = typename Dune::BCRSMatrix<B,Alloc>::field_type;
setupSparsityPattern(A,N); setupSparsityPattern(A,N);
B diagonal(static_cast<FieldType>(0)), bone(static_cast<FieldType>(0)); B diagonal(static_cast<field_type>(0)), bone(static_cast<field_type>(0));
auto setDiagonal = [](auto&& scalarOrMatrix, const auto& value) { auto setDiagonal = [](auto&& scalarOrMatrix, const auto& value) {
auto&& matrix = Dune::Impl::asMatrix(scalarOrMatrix); auto&& matrix = Dune::Impl::asMatrix(scalarOrMatrix);
...@@ -57,42 +67,42 @@ void setupLaplacian(Dune::BCRSMatrix<B,Alloc>& A, int N) ...@@ -57,42 +67,42 @@ void setupLaplacian(Dune::BCRSMatrix<B,Alloc>& A, int N)
setDiagonal(diagonal, 4.0); setDiagonal(diagonal, 4.0);
setDiagonal(bone, -1.0); setDiagonal(bone, -1.0);
for (typename Dune::BCRSMatrix<B,Alloc>::RowIterator i = A.begin(); i != A.end(); ++i) { for (auto i = A.begin(); i != A.end(); ++i)
{
int x = i.index()%N; // x coordinate in the 2d field int x = i.index()%N; // x coordinate in the 2d field
int y = i.index()/N; // y coordinate in the 2d field int y = i.index()/N; // y coordinate in the 2d field
/* if(x==0 || x==N-1 || y==0||y==N-1){ i->operator[](i.index())=diagonal;
i->operator[](i.index())=1.0;
if(y>0) if(y>0)
i->operator[](i.index()-N)=0; i->operator[](i.index()-N)=bone;
if(y<N-1) if(y<N-1)
i->operator[](i.index()+N)=0.0; i->operator[](i.index()+N)=bone;
if(x>0) if(x>0)
i->operator[](i.index()-1)=0.0; i->operator[](i.index()-1)=bone;
if(x < N-1) if(x < N-1)
i->operator[](i.index()+1)=0.0; i->operator[](i.index()+1)=bone;
}
}else*/ // add regularization to the diagonal
if ( reg.has_value() )
{
for ( auto rowIt=A.begin(); rowIt!=A.end(); rowIt++ )
{ {
for ( auto entryIt=rowIt->begin(); entryIt!=rowIt->end(); entryIt++ )
i->operator[](i.index())=diagonal; {
if ( entryIt.index() == rowIt.index() )
if(y>0) {
i->operator[](i.index()-N)=bone; auto&& block = Dune::Impl::asMatrix(*entryIt);
for ( auto it=block.begin(); it!=block.end(); ++it )
if(y<N-1) {
i->operator[](i.index()+N)=bone; (*it)[it.index()] += reg.value();
}
if(x>0) }
i->operator[](i.index()-1)=bone; }
if(x < N-1)
i->operator[](i.index()+1)=bone;
} }
} }
} }
......
...@@ -16,24 +16,6 @@ ...@@ -16,24 +16,6 @@
using namespace Dune; using namespace Dune;
// helper to add something to the diagonal of a BCRSMatrix with blocks
auto addToDiagonal = [](auto&& matrix, const auto& value) {
for( auto rowIt=matrix.begin(); rowIt!=matrix.end(); rowIt++ )
{
for( auto entryIt=rowIt->begin(); entryIt!=rowIt->end(); entryIt++ )
{
if ( entryIt.index() == rowIt.index() )
{
auto&& block = Dune::Impl::asMatrix(*entryIt);
for (auto it=block.begin(); it!=block.end(); ++it)
{
(*it)[it.index()] += value;
}
}
}
}
};
template<typename Matrix, typename Vector, typename BitVector> template<typename Matrix, typename Vector, typename BitVector>
TestSuite runUMFPack(std::size_t N) TestSuite runUMFPack(std::size_t N)
{ {
...@@ -42,10 +24,8 @@ TestSuite runUMFPack(std::size_t N) ...@@ -42,10 +24,8 @@ TestSuite runUMFPack(std::size_t N)
Matrix mat; Matrix mat;
Vector b(N*N), x(N*N), b1(N/2), x1(N/2); Vector b(N*N), x(N*N), b1(N/2), x1(N/2);
setupLaplacian(mat,N); // with additional diagonal regularization
setupLaplacian(mat,N,100.0);
// make this regular
addToDiagonal(mat,100.0);
b=1; b=1;
b1=1; b1=1;
...@@ -148,14 +128,10 @@ TestSuite runUMFPackMultitype2x2(std::size_t N) ...@@ -148,14 +128,10 @@ TestSuite runUMFPackMultitype2x2(std::size_t N)
// initialize all 4 matrix blocks // initialize all 4 matrix blocks
setupLaplacian(mat[_0][_0],N); setupLaplacian(mat[_0][_0],N,100.0); // regularize the diagonal block
setupLaplacian(mat[_0][_1],N); setupLaplacian(mat[_0][_1],N);
setupLaplacian(mat[_1][_0],N); setupLaplacian(mat[_1][_0],N);
setupLaplacian(mat[_1][_1],N); setupLaplacian(mat[_1][_1],N,200.0); // regularize the diagonal block
// make this regular
addToDiagonal(mat[_0][_0],200.0);
addToDiagonal(mat[_1][_1],100.0);
b=1.0; b=1.0;
b1=1.0; b1=1.0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment