//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool DAF::LightsOutSolver::Solve(const std::vector<bool>& kvectorStateMatrix, std::vector<bool>& vbOptimalSolutionMatrix) { const std::size_t kuDimension = _uDimension * _uDimension; for (const std::vector<bool>& vbBasisVector : _vvbGameMatrixNullSpaceBasis ) { if ( VectorVectorScalarProduct(kuDimension, vbBasisVector, kvectorStateMatrix) ) return false; } const std::vector<bool> kvectorBasicSolutionMatrix = MatrixVectorProduct(kuDimension, _vbElementaryOperationMatrix, kvectorStateMatrix); const std::size_t kuNullSpaceBasisDimension = _vvbGameMatrixNullSpaceBasis.size(); for (std::size_t uNullSpaceBasisIndex = 0; uNullSpaceBasisIndex < kuNullSpaceBasisDimension; ++uNullSpaceBasisIndex) { if ( VectorVectorScalarProduct(kuDimension, _vvbGameMatrixNullSpaceBasis[uNullSpaceBasisIndex], kvectorStateMatrix) ) return false; } std::size_t kuOptimalSolutionMoveCount = kuDimension; std::vector<bool> vbGameMatrixNullSpaceBasisCombination(kuNullSpaceBasisDimension, false); for (;;) { std::vector<bool> vbCurrentSolutionMatrix = kvectorBasicSolutionMatrix; for (std::size_t uNullSpaceBasisIndex = 0; uNullSpaceBasisIndex < kuNullSpaceBasisDimension; ++uNullSpaceBasisIndex) { if ( vbGameMatrixNullSpaceBasisCombination[uNullSpaceBasisIndex] ) vbCurrentSolutionMatrix = VectorVectorSum(kuDimension, vbCurrentSolutionMatrix, _vvbGameMatrixNullSpaceBasis[uNullSpaceBasisIndex]); } const std::size_t kuCurrentSolutionMoveCount = std::count(vbCurrentSolutionMatrix.begin(), vbCurrentSolutionMatrix.end(), true); if ( kuCurrentSolutionMoveCount < kuOptimalSolutionMoveCount ) { vbOptimalSolutionMatrix = vbCurrentSolutionMatrix; kuOptimalSolutionMoveCount = kuCurrentSolutionMoveCount; } std::size_t uCombinationIndex = 0; for (; uCombinationIndex < kuNullSpaceBasisDimension; ++uCombinationIndex) { if ( ! vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] ) { vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] = true; break; } vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] = false; } if ( uCombinationIndex == kuNullSpaceBasisDimension ) break; } return true; }
void CSysMatrix::ComputeILUPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) { unsigned long index, index_; double *Block_ij, *Block_jk; long iPoint, jPoint, kPoint; unsigned short iVar; /*--- Copy block matrix, note that the original matrix is modified by the algorithm---*/ for (iPoint = 0; iPoint < nPoint; iPoint++) { for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) { jPoint = col_ind[index]; Block_ij = GetBlock(iPoint, jPoint); SetBlock_ILUMatrix(iPoint, jPoint, Block_ij); } for (iVar = 0; iVar < nVar; iVar++) { prod[iPoint*nVar+iVar] = vec[iPoint*nVar+iVar]; } } /*--- Transform system in Upper Matrix ---*/ for (iPoint = 1; iPoint < nPoint; iPoint++) { for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) { jPoint = col_ind[index]; if (jPoint < iPoint) { Block_ij = GetBlock_ILUMatrix(iPoint, jPoint); InverseDiagonalBlock_ILUMatrix(jPoint, block_inverse); MatrixMatrixProduct(Block_ij, block_inverse, block_weight); for (index_ = row_ptr[jPoint]; index_ < row_ptr[jPoint+1]; index_++) { kPoint = col_ind[index_]; Block_jk = GetBlock_ILUMatrix(jPoint, kPoint); if (kPoint >= jPoint) { MatrixMatrixProduct(Block_jk, block_weight, block); SubtractBlock_ILUMatrix(iPoint, kPoint, block); } } MatrixVectorProduct(block_weight, &prod[jPoint*nVar], aux_vector); for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] -= aux_vector[iVar]; } } } /*--- MPI Parallelization ---*/ SendReceive_Solution(prod, geometry, config); /*--- Backwards substitution ---*/ InverseDiagonalBlock_ILUMatrix((nPoint-1), block_inverse); MatrixVectorProduct(block_inverse, &prod[(nPoint-1)*nVar], aux_vector); for (iVar = 0; iVar < nVar; iVar++) prod[ (nPoint-1)*nVar + iVar] = aux_vector[iVar]; for (iPoint = nPoint-2; iPoint >= 0; iPoint--) { for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] = 0.0; for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) { jPoint = col_ind[index]; Block_ij = GetBlock_ILUMatrix(iPoint, jPoint); if (jPoint >= iPoint+1) { MatrixVectorProduct(Block_ij, &prod[jPoint*nVar], aux_vector); for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] += aux_vector[iVar]; } } for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = (prod[iPoint*nVar+iVar]-sum_vector[iVar]); InverseDiagonalBlock_ILUMatrix(iPoint, block_inverse); MatrixVectorProduct(block_inverse, &prod[iPoint*nVar], aux_vector); for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = aux_vector[iVar]; if (iPoint == 0) break; } /*--- MPI Parallelization ---*/ SendReceive_Solution(prod, geometry, config); }