|
27 | 27 | #include "DoubleSparseSquareMatrix.h" |
28 | 28 | #include "OutputFiles.h" |
29 | 29 | #include <assert.h> |
| 30 | +#include <math.h> |
| 31 | + |
| 32 | +#ifdef _DEBUG_WRITE_FOR_BOTTOM_RESISTIVITY |
| 33 | +#ifdef _LINUX |
| 34 | +#include <sys/time.h> |
| 35 | +#include <sys/resource.h> |
| 36 | +#endif |
| 37 | +#endif |
30 | 38 |
|
31 | 39 | //Default Constructer |
32 | 40 | DoubleSparseSquareMatrix::DoubleSparseSquareMatrix(): |
@@ -135,6 +143,147 @@ void DoubleSparseSquareMatrix::solvePhaseMatrixSolver( const int nrhs, double* r |
135 | 143 | m_pardisoSolver.solve( m_rowIndex, m_columns, m_values, nrhs, rhs, solution ); |
136 | 144 | } |
137 | 145 |
|
| 146 | +//Solve phase of matrix solver by the conjugate gradient method with the point Jacobi preconditioner |
| 147 | +//@note Matrix should be symmetric |
| 148 | +void DoubleSparseSquareMatrix::solvePhaseMatrixSolverByPCGPointJacobi(const int nrhs, double* rhs, double* solution) const{ |
| 149 | + assert(m_hasConvertedToCRSFormat); |
| 150 | + |
| 151 | + const int maxIterationNumber = m_numRows; |
| 152 | + const double eps = 1.0e-20; |
| 153 | + double* invDiagonals = new double[m_numRows]; |
| 154 | + double* workP = new double[m_numRows]; |
| 155 | + double* workR = new double[m_numRows];// Residuals |
| 156 | + double* workQ = new double[m_numRows]; |
| 157 | + double* workX = new double[m_numRows];// Solution vector |
| 158 | + double* workZ = new double[m_numRows]; |
| 159 | + |
| 160 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 161 | + { |
| 162 | + for (int j = m_rowIndex[irow]; j < m_rowIndex[irow + 1]; ++j) |
| 163 | + { |
| 164 | + if (irow == m_columns[j]) |
| 165 | + { |
| 166 | + invDiagonals[irow] = 1.0 / m_values[j]; |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | + for (int irhs = 0; irhs < nrhs; ++irhs) |
| 171 | + { |
| 172 | + // Initial solution is a zero vector |
| 173 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 174 | + { |
| 175 | + workX[irow] = 0.0; |
| 176 | + } |
| 177 | + // [r0] = [b] - [A][x0] |
| 178 | + double normOfRhsVector(0.0); |
| 179 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 180 | + { |
| 181 | + const long long int index = static_cast<long long int>(irow) + static_cast<long long int>(irhs) * static_cast<long long int>(m_numRows); |
| 182 | + normOfRhsVector += rhs[index] * rhs[index]; |
| 183 | + workR[irow] = rhs[index]; |
| 184 | + } |
| 185 | + int iter = 0; |
| 186 | + double rhoPre(0.0); |
| 187 | + for (; iter < maxIterationNumber; ++iter) |
| 188 | + { |
| 189 | + // [z] = [M]^-1[r] |
| 190 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 191 | + { |
| 192 | + workZ[irow] = invDiagonals[irow] * workR[irow]; |
| 193 | + } |
| 194 | + // rho = [r]T[z] |
| 195 | + double rho(0.0); |
| 196 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 197 | + { |
| 198 | + rho += workR[irow] * workZ[irow]; |
| 199 | + } |
| 200 | + if (iter == 0) |
| 201 | + { |
| 202 | + // [p0] - [z0] |
| 203 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 204 | + { |
| 205 | + workP[irow] = workZ[irow]; |
| 206 | + } |
| 207 | + } |
| 208 | + else |
| 209 | + { |
| 210 | + // [p] = [z] + beta*[p] |
| 211 | + const double beta = rho / rhoPre; |
| 212 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 213 | + { |
| 214 | + workP[irow] = workZ[irow] + beta * workP[irow]; |
| 215 | + } |
| 216 | + } |
| 217 | + // [q] = [A][p] |
| 218 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 219 | + { |
| 220 | + workQ[irow] = 0.0; |
| 221 | + for (int j = m_rowIndex[irow]; j < m_rowIndex[irow + 1]; ++j) |
| 222 | + { |
| 223 | + workQ[irow] += m_values[j] * workP[m_columns[j]]; |
| 224 | + } |
| 225 | + } |
| 226 | + // alpha = rho / [p]T[q] |
| 227 | + double pq(0.0); |
| 228 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 229 | + { |
| 230 | + pq += workP[irow] * workQ[irow]; |
| 231 | + } |
| 232 | + const double alpha = rho / pq; |
| 233 | + // [x] = [x] + alpha * [p] |
| 234 | + // [r] = [r] - alpha * [q] |
| 235 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 236 | + { |
| 237 | + workX[irow] += alpha * workP[irow]; |
| 238 | + workR[irow] -= alpha * workQ[irow]; |
| 239 | + } |
| 240 | + // Check convergence |
| 241 | + double normOfResidualVector(0.0); |
| 242 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 243 | + { |
| 244 | + normOfResidualVector += workR[irow] * workR[irow]; |
| 245 | + } |
| 246 | + if( sqrt(normOfResidualVector/ normOfRhsVector) < eps ) |
| 247 | + { |
| 248 | + break; |
| 249 | + } |
| 250 | + rhoPre = rho; |
| 251 | + } |
| 252 | + if (iter >= maxIterationNumber) { |
| 253 | + OutputFiles::m_logFile << "Error : PCG solver is not converged !!" << std::endl; |
| 254 | + exit(1); |
| 255 | + } |
| 256 | + else { |
| 257 | + OutputFiles::m_logFile << "# PCG solver is converged after " << iter << " iterations." << std::endl; |
| 258 | + } |
| 259 | + for (int irow = 0; irow < m_numRows; ++irow) |
| 260 | + { |
| 261 | + const long long int index = static_cast<long long int>(irow) + static_cast<long long int>(irhs) * static_cast<long long int>(m_numRows); |
| 262 | + solution[index] = workX[irow]; |
| 263 | + } |
| 264 | + } |
| 265 | + |
| 266 | +#ifdef _DEBUG_WRITE_FOR_BOTTOM_RESISTIVITY |
| 267 | +#ifdef _LINUX |
| 268 | + { |
| 269 | + struct rusage r; |
| 270 | + if (getrusage(RUSAGE_SELF, &r) != 0) { |
| 271 | + /*Failure*/ |
| 272 | + } |
| 273 | + OutputFiles::m_logFile << "maxrss= " << r.ru_maxrss << std::endl; |
| 274 | + } |
| 275 | +#endif |
| 276 | +#endif |
| 277 | + |
| 278 | + delete[] invDiagonals; |
| 279 | + delete[] workP; |
| 280 | + delete[] workR; |
| 281 | + delete[] workQ; |
| 282 | + delete[] workX; |
| 283 | + delete[] workZ; |
| 284 | + |
| 285 | +} |
| 286 | + |
138 | 287 | //Release memory of matrix solver |
139 | 288 | void DoubleSparseSquareMatrix::releaseMemoryMatrixSolver(){ |
140 | 289 | if( m_pardisoSolver.getSolutionStage() > PARDISOSolver::MEMORY_RELEASED ){ |
|
0 commit comments