GraphHelper_Scotch(const CrsMatrixType& A, const int seed = GraphHelper::DefaultRandomSeed) { _label = "GraphHelper_Scotch::" + A.Label(); _is_ordered = false; _cblk = 0; // scotch does not allow self-contribution (diagonal term in sparse matrix) _base = 0; //A.BaseVal(); _m = A.NumRows(); _nnz = A.NumNonZeros(); _rptr = size_type_array(_label+"::RowPtrArray", _m+1); _cidx = ordinal_type_array(_label+"::ColIndexArray", _nnz); _perm = ordinal_type_array(_label+"::PermutationArray", _m); _peri = ordinal_type_array(_label+"::InvPermutationArray", _m); _range = ordinal_type_array(_label+"::RangeArray", _m); _tree = ordinal_type_array(_label+"::TreeArray", _m); // create a graph structure without diagonals A.convertGraph(_nnz, _rptr, _cidx); int ierr = 0; ordinal_type *rptr = reinterpret_cast<ordinal_type*>(_rptr.ptr_on_device()); ordinal_type *cidx = reinterpret_cast<ordinal_type*>(_cidx.ptr_on_device()); if (seed != GraphHelper::DefaultRandomSeed) { SCOTCH_randomSeed(seed); SCOTCH_randomReset(); } ierr = SCOTCH_graphInit(&_graph); CHKERR(ierr); ierr = SCOTCH_graphBuild(&_graph, // scotch graph _base, // base value _m, // # of vertices rptr, // column index array pointer begin rptr+1, // column index array pointer end NULL, // weights on vertices (optional) NULL, // label array on vertices (optional) _nnz, // # of nonzeros cidx, // column index array NULL); CHKERR(ierr); // edge load array (optional) ierr = SCOTCH_graphCheck(&_graph); CHKERR(ierr); }
void setGraph(const ordinal_type m, const size_type_array rptr, const ordinal_type_array cidx) { _is_ordered = false; _cblk = 0; /// Scotch graph spec /// - no diagonals, symmetric _base = 0; _m = m; _nnz = rptr[m]; _rptr = rptr; _cidx = cidx; _perm = ordinal_type_array("Scotch::PermutationArray", _m); _peri = ordinal_type_array("Scotch::InvPermutationArray", _m); _range = ordinal_type_array("Scotch::RangeArray", _m); _tree = ordinal_type_array("Scotch::TreeArray", _m); _strat = 0; _level = 0; int ierr = 0; ordinal_type *rptr_ptr = reinterpret_cast<ordinal_type*>(_rptr.ptr_on_device()); ordinal_type *cidx_ptr = reinterpret_cast<ordinal_type*>(_cidx.ptr_on_device()); ierr = SCOTCH_graphInit(&_graph); TACHO_TEST_FOR_ABORT(ierr, "Failed in SCOTCH_graphInit"); ierr = SCOTCH_graphBuild(&_graph, // scotch graph _base, // base value _m, // # of vertices rptr_ptr, // column index array pointer begin rptr_ptr+1, // column index array pointer end NULL, // weights on vertices (optional) NULL, // label array on vertices (optional) _nnz, // # of nonzeros cidx_ptr, // column index array NULL); // edge load array (optional) TACHO_TEST_FOR_ABORT(ierr, "Failed in SCOTCH_graphBuild"); ierr = SCOTCH_graphCheck(&_graph); TACHO_TEST_FOR_ABORT(ierr, "Failed in SCOTCH_graphCheck"); }
int computeOrdering() { int r_val = 0; camd_defaults(_control); camd_control(_control); ordinal_type *rptr = reinterpret_cast<ordinal_type*>(_rptr.ptr_on_device()); ordinal_type *cidx = reinterpret_cast<ordinal_type*>(_cidx.ptr_on_device()); ordinal_type *cnst = reinterpret_cast<ordinal_type*>(_cnst.ptr_on_device()); ordinal_type *next = reinterpret_cast<ordinal_type*>(_next.ptr_on_device()); ordinal_type *perm = reinterpret_cast<ordinal_type*>(_perm.ptr_on_device()); // length array // assume there always is diagonal and the given matrix is symmetry ordinal_type_array lwork(_label+"::LWorkArray", _m); ordinal_type *lwork_ptr = reinterpret_cast<ordinal_type*>(lwork.ptr_on_device()); for (ordinal_type i=0;i<_m;++i) lwork_ptr[i] = rptr[i+1] - rptr[i]; // workspace const size_type swlen = _nnz + _nnz/5 + 5*(_m+1);; ordinal_type_array swork(_label+"::SWorkArray", swlen); ordinal_type *swork_ptr = reinterpret_cast<ordinal_type*>(swork.ptr_on_device()); ordinal_type *pe_ptr = reinterpret_cast<ordinal_type*>(_pe.ptr_on_device()); // 1) Pe size_type pfree = 0; for (ordinal_type i=0;i<_m;++i) { pe_ptr[i] = pfree; pfree += lwork_ptr[i]; } if (_nnz != pfree) ERROR(">> nnz in the graph does not match to nnz count (pfree)"); ordinal_type *nv_ptr = reinterpret_cast<ordinal_type*>(_nv.ptr_on_device()); // 2) Nv ordinal_type *hd_ptr = swork_ptr; swork_ptr += (_m+1); // 3) Head ordinal_type *el_ptr = reinterpret_cast<ordinal_type*>(_el.ptr_on_device()); // 4) Elen ordinal_type *dg_ptr = swork_ptr; swork_ptr += _m; // 5) Degree ordinal_type *wk_ptr = swork_ptr; swork_ptr += (_m+1); // 6) W ordinal_type *bk_ptr = swork_ptr; swork_ptr += _m; // 7) BucketSet const size_type iwlen = swlen - (4*_m+2); ordinal_type *iw_ptr = swork_ptr; swork_ptr += iwlen; // Iw for (ordinal_type i=0;i<pfree;++i) iw_ptr[i] = cidx[i]; CAMD::run(_m, pe_ptr, iw_ptr, lwork_ptr, iwlen, pfree, // output nv_ptr, next, perm, hd_ptr, el_ptr, dg_ptr, wk_ptr, _control, _info, cnst, bk_ptr); r_val = (_info[CAMD_STATUS] != CAMD_OK); for (ordinal_type i=0;i<_m;++i) _peri[_perm[i]] = i; _is_ordered = true; return r_val; }