void PETScVector::shallowCopy(const PETScVector &v) { destroy(); VecDuplicate(v.getRawVector(), &_v); _start_rank = v._start_rank; _end_rank = v._end_rank; _size = v._size; _size_loc = v._size_loc; _size_ghosts = v._size_ghosts; _has_ghost_id = v._has_ghost_id; VecSetOption(_v, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE); }
bool PETScLinearSolver::solve(PETScMatrix& A, PETScVector& b, PETScVector& x) { BaseLib::RunTime wtimer; wtimer.start(); // define TEST_MEM_PETSC #ifdef TEST_MEM_PETSC PetscLogDouble mem1, mem2; PetscMemoryGetCurrentUsage(&mem1); #endif #if (PETSC_VERSION_NUMBER > 3040) KSPSetOperators(_solver, A.getRawMatrix(), A.getRawMatrix()); #else KSPSetOperators(_solver, A.getRawMatrix(), A.getRawMatrix(), DIFFERENT_NONZERO_PATTERN); #endif KSPSolve(_solver, b.getRawVector(), x.getRawVector()); KSPConvergedReason reason; KSPGetConvergedReason(_solver, &reason); bool converged = true; if (reason > 0) { const char* ksp_type; const char* pc_type; KSPGetType(_solver, &ksp_type); PCGetType(_pc, &pc_type); PetscPrintf(PETSC_COMM_WORLD, "\n================================================"); PetscPrintf(PETSC_COMM_WORLD, "\nLinear solver %s with %s preconditioner", ksp_type, pc_type); PetscInt its; KSPGetIterationNumber(_solver, &its); PetscPrintf(PETSC_COMM_WORLD, "\nconverged in %d iterations", its); switch (reason) { case KSP_CONVERGED_RTOL: PetscPrintf(PETSC_COMM_WORLD, " (relative convergence criterion fulfilled)."); break; case KSP_CONVERGED_ATOL: PetscPrintf(PETSC_COMM_WORLD, " (absolute convergence criterion fulfilled)."); break; default: PetscPrintf(PETSC_COMM_WORLD, "."); } PetscPrintf(PETSC_COMM_WORLD, "\n================================================\n"); } else if (reason == KSP_DIVERGED_ITS) { const char* ksp_type; const char* pc_type; KSPGetType(_solver, &ksp_type); PCGetType(_pc, &pc_type); PetscPrintf(PETSC_COMM_WORLD, "\nLinear solver %s with %s preconditioner", ksp_type, pc_type); PetscPrintf(PETSC_COMM_WORLD, "\nWarning: maximum number of iterations reached.\n"); } else { converged = false; if (reason == KSP_DIVERGED_INDEFINITE_PC) { PetscPrintf(PETSC_COMM_WORLD, "\nDivergence because of indefinite preconditioner,"); PetscPrintf(PETSC_COMM_WORLD, "\nTry to run again with " "-pc_factor_shift_positive_definite option.\n"); } else if (reason == KSP_DIVERGED_BREAKDOWN_BICG) { PetscPrintf(PETSC_COMM_WORLD, "\nKSPBICG method was detected so the method could not " "continue to enlarge the Krylov space."); PetscPrintf(PETSC_COMM_WORLD, "\nTry to run again with another solver.\n"); } else if (reason == KSP_DIVERGED_NONSYMMETRIC) { PetscPrintf(PETSC_COMM_WORLD, "\nMatrix or preconditioner is unsymmetric but KSP " "requires symmetric.\n"); } else { PetscPrintf(PETSC_COMM_WORLD, "\nDivergence detected, use command option " "-ksp_monitor or -log_summary to check the details.\n"); } } #ifdef TEST_MEM_PETSC PetscMemoryGetCurrentUsage(&mem2); PetscPrintf( PETSC_COMM_WORLD, "###Memory usage by solver. Before: %f After: %f Increase: %d\n", mem1, mem2, (int)(mem2 - mem1)); #endif _elapsed_ctime += wtimer.elapsed(); return converged; }