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");
    }
示例#3
0
    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;
    }