Skip to content
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

572 check for singularity when the solver parameters flag is turned on #603

4 changes: 0 additions & 4 deletions include/micm/jit/solver/jit_linear_solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ namespace micm
SparseMatrixPolicy& upper_matrix,
bool& is_singular);

/// @brief Decompose the matrix into upper and lower triangular matrices and general JIT functions
/// @param matrix Matrix that will be factored into lower and upper triangular matrices
void Factor(SparseMatrixPolicy& matrix, SparseMatrixPolicy& lower_matrix, SparseMatrixPolicy& upper_matrix);

/// @brief Solve for x in Ax = b
template<class MatrixPolicy>
void Solve(MatrixPolicy& x, SparseMatrixPolicy& lower_matrix, SparseMatrixPolicy& upper_matrix);
Expand Down
9 changes: 0 additions & 9 deletions include/micm/jit/solver/jit_linear_solver.inl
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ namespace micm
LinearSolver<SparseMatrixPolicy, LuDecompositionPolicy>::Factor(matrix, lower_matrix, upper_matrix, is_singular);
}

template<std::size_t L, class SparseMatrixPolicy, class LuDecompositionPolicy>
inline void JitLinearSolver<L, SparseMatrixPolicy, LuDecompositionPolicy>::Factor(
SparseMatrixPolicy &matrix,
SparseMatrixPolicy &lower_matrix,
SparseMatrixPolicy &upper_matrix)
{
LinearSolver<SparseMatrixPolicy, LuDecompositionPolicy>::Factor(matrix, lower_matrix, upper_matrix);
}

template<std::size_t L, class SparseMatrixPolicy, class LuDecompositionPolicy>
template<class MatrixPolicy>
inline void JitLinearSolver<L, SparseMatrixPolicy, LuDecompositionPolicy>::Solve(
Expand Down
10 changes: 2 additions & 8 deletions include/micm/jit/solver/jit_lu_decomposition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace micm
class JitLuDecomposition : public LuDecomposition
{
llvm::orc::ResourceTrackerSP decompose_function_resource_tracker_;
void (*decompose_function_)(const double *, double *, double *);
using FuncPtr = void (*)(const double *, double *, double *);
FuncPtr decompose_function_ = nullptr;

public:
JitLuDecomposition(){};
Expand All @@ -43,13 +44,6 @@ namespace micm
void Decompose(const SparseMatrixPolicy &A, SparseMatrixPolicy &lower, SparseMatrixPolicy &upper, bool &is_singular)
const;

/// @brief Create sparse L and U matrices for a given A matrix
/// @param A Sparse matrix that will be decomposed
/// @param lower The lower triangular matrix created by decomposition
/// @param upper The upper triangular matrix created by decomposition
template<class SparseMatrixPolicy>
void Decompose(const SparseMatrixPolicy &A, SparseMatrixPolicy &lower, SparseMatrixPolicy &upper) const;

private:
/// @brief Generates a function to perform the LU decomposition for a specific matrix sparsity structure
void GenerateDecomposeFunction();
Expand Down
31 changes: 16 additions & 15 deletions include/micm/jit/solver/jit_lu_decomposition.inl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace micm
.SetName(function_name)
.SetArguments({ { "A matrix", JitType::DoublePtr },
{ "lower matrix", JitType::DoublePtr },
{ "upper matrix", JitType::DoublePtr } })
{ "upper matrix", JitType::DoublePtr }})
.SetReturnType(JitType::Void);
llvm::Type *double_type = func.GetType(JitType::Double);
llvm::Value *zero = llvm::ConstantInt::get(*(func.context_), llvm::APInt(64, 0));
Expand Down Expand Up @@ -180,26 +180,27 @@ namespace micm
func.builder_->CreateRetVoid();

auto target = func.Generate();
decompose_function_ = (void (*)(const double *, double *, double *))(intptr_t)target.second;
decompose_function_ = (FuncPtr)(intptr_t)target.second;
decompose_function_resource_tracker_ = target.first;
}

template<std::size_t L>
template<class SparseMatrixPolicy>
void JitLuDecomposition<L>::Decompose(
const SparseMatrixPolicy &A,
SparseMatrixPolicy &lower,
SparseMatrixPolicy &upper,
bool &is_singular) const
{
LuDecomposition::Decompose<SparseMatrixPolicy>(A, lower, upper, is_singular);
}

template<std::size_t L>
template<class SparseMatrixPolicy>
void JitLuDecomposition<L>::Decompose(const SparseMatrixPolicy &A, SparseMatrixPolicy &lower, SparseMatrixPolicy &upper)
const
void JitLuDecomposition<L>::Decompose(const SparseMatrixPolicy &A, SparseMatrixPolicy &lower, SparseMatrixPolicy &upper, bool& is_singular) const
{
is_singular = false;
decompose_function_(A.AsVector().data(), lower.AsVector().data(), upper.AsVector().data());
for(size_t block = 0; block < A.NumberOfBlocks(); ++block)
{
auto diagonals = upper.DiagonalIndices(block);
for(const auto& diagonal : diagonals)
{
if(upper.AsVector()[diagonal] == 0)
{
is_singular = true;
return;
}
}
}
}
} // namespace micm
3 changes: 0 additions & 3 deletions include/micm/solver/linear_solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ namespace micm

virtual ~LinearSolver() = default;

/// @brief Decompose the matrix into upper and lower triangular matrices
void Factor(const SparseMatrixPolicy& matrix, SparseMatrixPolicy& lower_matrix, SparseMatrixPolicy& upper_matrix) const;

/// @brief Decompose the matrix into upper and lower triangular matrices
/// @param matrix Matrix to decompose into lower and upper triangular matrices
/// @param is_singular Flag that is set to true if matrix is singular; false otherwise
Expand Down
11 changes: 0 additions & 11 deletions include/micm/solver/linear_solver.inl
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,6 @@ namespace micm
}
};

template<class SparseMatrixPolicy, class LuDecompositionPolicy>
inline void LinearSolver<SparseMatrixPolicy, LuDecompositionPolicy>::Factor(
const SparseMatrixPolicy& matrix,
SparseMatrixPolicy& lower_matrix,
SparseMatrixPolicy& upper_matrix) const
{
MICM_PROFILE_FUNCTION();

lu_decomp_.template Decompose<SparseMatrixPolicy>(matrix, lower_matrix, upper_matrix);
}

template<class SparseMatrixPolicy, class LuDecompositionPolicy>
inline void LinearSolver<SparseMatrixPolicy, LuDecompositionPolicy>::Factor(
const SparseMatrixPolicy& matrix,
Expand Down
10 changes: 0 additions & 10 deletions include/micm/solver/lu_decomposition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,6 @@ namespace micm
const SparseMatrixPolicy& A,
typename SparseMatrixPolicy::value_type initial_value);

/// @brief Perform an LU decomposition on a given A matrix
/// @param A Sparse matrix to decompose
/// @param L The lower triangular matrix created by decomposition
/// @param U The upper triangular matrix created by decomposition
template<class SparseMatrixPolicy>
requires(SparseMatrixConcept<SparseMatrixPolicy>) void Decompose(
const SparseMatrixPolicy& A,
SparseMatrixPolicy& L,
SparseMatrixPolicy& U) const;
sjsprecious marked this conversation as resolved.
Show resolved Hide resolved

/// @brief Perform an LU decomposition on a given A matrix
/// @param A Sparse matrix to decompose
/// @param L The lower triangular matrix created by decomposition
Expand Down
37 changes: 22 additions & 15 deletions include/micm/solver/lu_decomposition.inl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ namespace micm
}
niLU_.push_back(iLU);
}
uii_.push_back(LU.second.VectorIndex(0, n - 1, n - 1));
}

template<class SparseMatrixPolicy>
Expand Down Expand Up @@ -163,16 +164,6 @@ namespace micm
return LU;
}

template<class SparseMatrixPolicy>
requires(SparseMatrixConcept<SparseMatrixPolicy>) inline void LuDecomposition::Decompose(
const SparseMatrixPolicy& A,
SparseMatrixPolicy& L,
SparseMatrixPolicy& U) const
{
bool is_singular = false;
Decompose<SparseMatrixPolicy>(A, L, U, is_singular);
}

template<class SparseMatrixPolicy>
requires(!VectorizableSparse<SparseMatrixPolicy>) inline void LuDecomposition::Decompose(
const SparseMatrixPolicy& A,
Expand All @@ -181,6 +172,7 @@ namespace micm
bool& is_singular) const
{
MICM_PROFILE_FUNCTION();
is_singular = false;

// Loop over blocks
for (std::size_t i_block = 0; i_block < A.NumberOfBlocks(); ++i_block)
Expand All @@ -197,7 +189,6 @@ namespace micm
auto lki_nkj = lki_nkj_.begin();
auto lkj_uji = lkj_uji_.begin();
auto uii = uii_.begin();
is_singular = false;
for (auto& inLU : niLU_)
{
// Upper trianglur matrix
Expand All @@ -223,16 +214,21 @@ namespace micm
L_vector[lki_nkj->first] -= L_vector[lkj_uji->first] * U_vector[lkj_uji->second];
++lkj_uji;
}

if (U_vector[*uii] == 0.0)
{
is_singular = true;
return;
sjsprecious marked this conversation as resolved.
Show resolved Hide resolved
}
L_vector[lki_nkj->first] /= U_vector[*uii];
++lki_nkj;
++uii;
}
}
// check the bottom right corner of the matrix
if (U_vector[*uii] == 0.0)
{
is_singular = true;
}
}
}

Expand All @@ -250,6 +246,7 @@ namespace micm
std::size_t A_GroupSizeOfFlatBlockSize = A.GroupSize(A.FlatBlockSize());
std::size_t L_GroupSizeOfFlatBlockSize = L.GroupSize(L.FlatBlockSize());
std::size_t U_GroupSizeOfFlatBlockSize = U.GroupSize(U.FlatBlockSize());
is_singular = false;

// Loop over groups of blocks
for (std::size_t i_group = 0; i_group < A.NumberOfGroups(A_BlockSize); ++i_group)
Expand All @@ -266,7 +263,6 @@ namespace micm
auto lki_nkj = lki_nkj_.begin();
auto lkj_uji = lkj_uji_.begin();
auto uii = uii_.begin();
is_singular = false;
const std::size_t n_cells = std::min(A_GroupVectorSize, A_BlockSize - i_group * A_GroupVectorSize);
for (auto& inLU : niLU_)
{
Expand Down Expand Up @@ -316,15 +312,26 @@ namespace micm
if (U_vector[uii_deref + i_cell] == 0.0)
{
is_singular = true;
return;
}
L_vector[lki_nkj_first + i_cell] /= U_vector[uii_deref + i_cell];
}
++lki_nkj;
++uii;
}
}
std::size_t uii_deref = *uii;
if (n_cells != A_GroupVectorSize) {
// check the bottom right corner of the matrix
for (std::size_t i_cell = 0; i_cell < n_cells; ++i_cell)
{
if (U_vector[uii_deref + i_cell] == 0.0)
{
is_singular = true;
break;
}
}
}
}
}

} // namespace micm
} // namespace micm
19 changes: 7 additions & 12 deletions include/micm/solver/rosenbrock.inl
Original file line number Diff line number Diff line change
Expand Up @@ -240,26 +240,21 @@ namespace micm
{
MICM_PROFILE_FUNCTION();

auto jacobian = state.jacobian_;
uint64_t n_consecutive = 0;
singular = false;
while (true)
{
auto jacobian = state.jacobian_;
K20shores marked this conversation as resolved.
Show resolved Hide resolved
double alpha = 1 / (H * gamma);
static_cast<Derived*>(this)->AlphaMinusJacobian(jacobian, alpha);
if (parameters_.check_singularity_)
{
linear_solver_.Factor(jacobian, state.lower_matrix_, state.upper_matrix_, singular);
}
else
{
singular = false;
linear_solver_.Factor(jacobian, state.lower_matrix_, state.upper_matrix_);
}
singular = false; // TODO This should be evaluated in some way
linear_solver_.Factor(jacobian, state.lower_matrix_, state.upper_matrix_, singular);
stats.decompositions_ += 1;
if (!singular)

// if we are checking for singularity and the matrix is not singular, we can break the loop
// if we are not checking for singularity, we always break the loop
if (!singular || !parameters_.check_singularity_)
break;

stats.singular_ += 1;
if (++n_consecutive > 5)
break;
Expand Down
2 changes: 1 addition & 1 deletion include/micm/solver/state.inl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ namespace micm
jacobian_ = BuildJacobian<SparseMatrixPolicy>(
parameters.nonzero_jacobian_elements_, parameters.number_of_grid_cells_, state_size_);

auto lu = LuDecomposition::GetLUMatrices<SparseMatrixPolicy>(jacobian_, 1.0e-30);
auto lu = LuDecomposition::GetLUMatrices<SparseMatrixPolicy>(jacobian_, 0);
auto lower_matrix = std::move(lu.first);
auto upper_matrix = std::move(lu.second);
lower_matrix_ = lower_matrix;
Expand Down
5 changes: 5 additions & 0 deletions src/solver/lu_decomposition.cu
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ namespace micm
++uii_offset;
}
}
// check the bottom right corner of the matrix
if (d_U[d_uii[uii_offset] + tid] == 0.0)
{
*d_is_singular = true;
}
}
} // end of CUDA kernel

Expand Down
2 changes: 1 addition & 1 deletion test/integration/test_analytical_rosenbrock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ TEST(AnalyticalExamples, SurfaceRxn)
test_analytical_surface_rxn(rosenbrock_6stage_da, 1e-7);
}

TEST(AnalyticalExamples, HIRESConfig)
TEST(AnalyticalExamples, HIRES)
{
auto rosenbrock_solver = [](auto params)
{
Expand Down
3 changes: 2 additions & 1 deletion test/unit/cuda/solver/test_cuda_linear_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ std::vector<double> linearSolverGenerator(std::size_t number_of_blocks)
CopyToDeviceSparse<SparseMatrixPolicy>(lower_matrix);
CopyToDeviceSparse<SparseMatrixPolicy>(upper_matrix);

solver.Factor(A, lower_matrix, upper_matrix);
bool singular{ false };
solver.Factor(A, lower_matrix, upper_matrix, singular);
solver.template Solve<MatrixPolicy>(x, lower_matrix, upper_matrix);

// Only copy the data to the host when it is a CudaMatrix
Expand Down
3 changes: 2 additions & 1 deletion test/unit/cuda/solver/test_cuda_lu_decomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ void testCudaRandomMatrix(size_t n_grids)

micm::LuDecomposition cpu_lud = micm::LuDecomposition::Create<CPUSparseMatrixPolicy>(cpu_A);
auto cpu_LU = micm::LuDecomposition::GetLUMatrices<CPUSparseMatrixPolicy>(cpu_A, 1.0e-30);
cpu_lud.Decompose<CPUSparseMatrixPolicy>(cpu_A, cpu_LU.first, cpu_LU.second);
bool singular{ false };
cpu_lud.Decompose<CPUSparseMatrixPolicy>(cpu_A, cpu_LU.first, cpu_LU.second, singular);

// checking GPU result again CPU
size_t L_size = cpu_LU.first.AsVector().size();
Expand Down
Loading
Loading