Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_AlgAMD.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
14 #ifndef _ZOLTAN2_ALGAMD_HPP_
15 #define _ZOLTAN2_ALGAMD_HPP_
16 
17 #include <Zoltan2_Algorithm.hpp>
18 #include <Zoltan2_GraphModel.hpp>
20 #include <Zoltan2_TPLTraits.hpp>
21 
22 
23 #ifdef HAVE_ZOLTAN2_AMD
24 #include "amd.h"
25 #ifdef SUITESPARSE_MAIN_VERSION
26 #if SUITESPARSE_MAIN_VERSION < 4
27 typedef UF_long SuiteSparse_long;
28 #endif
29 #endif
30 #endif
31 
32 
33 
34 namespace Zoltan2{
35 
36 
37 #ifdef HAVE_ZOLTAN2_AMD
38 template <typename Ordinal>
39 class AMDTraits
40 {
41  public:
42  Ordinal order(Ordinal n, const Ordinal *Ap, const Ordinal *Ai,
43  Ordinal *perm, double *control, double *info);
44 };
45 
46 template <>
47 class AMDTraits<int>
48 {
49  public:
50  int order(int n, const int *Ap, const int *Ai, int *perm,
51  double *control, double *info)
52  {
53  return (amd_order(n, Ap, Ai, perm, control, info));
54  }
55 };
56 
57 template <>
58 class AMDTraits<SuiteSparse_long>
59 {
60  public:
61  long order(SuiteSparse_long n, const SuiteSparse_long *Ap,
62  const SuiteSparse_long *Ai, SuiteSparse_long *perm,
63  double *control, double *info)
64  {
65  return (amd_l_order(n, Ap, Ai, perm, control, info));
66  }
67 };
68 
69 #endif
70 
71 }
72 
73 
74 namespace Zoltan2{
75 
76 template <typename Adapter>
77 class AlgAMD : public Algorithm<Adapter>
78 {
79  private:
80 
81  const RCP<const typename Adapter::base_adapter_t> adapter;
82  const RCP<Teuchos::ParameterList> pl;
83  const RCP<const Teuchos::Comm<int> > comm;
84  RCP<const Environment> env;
85  modelFlag_t graphFlags;
86 
87  public:
88 
90  const RCP<const typename Adapter::base_adapter_t> &adapter__,
91  const RCP<Teuchos::ParameterList> &pl__,
92  const RCP<const Teuchos::Comm<int> > &comm__,
93  RCP<const Environment> &env__,
94  const modelFlag_t &graphFlags__
95  ) : adapter(adapter__), pl(pl__), comm(comm__), env(env__), graphFlags(graphFlags__)
96  { }
97 
99  const RCP<GlobalOrderingSolution<typename Adapter::gno_t> > &/* solution */) {
100  throw std::logic_error("AlgAMD does not yet support global ordering.");
101  }
102 
105  {
106 #ifndef HAVE_ZOLTAN2_AMD
107  (void)solution; // remove unused parameter warning
108  throw std::runtime_error(
109  "BUILD ERROR: AMD requested but not compiled into Zoltan2.\n"
110  "Please set CMake flag Zoltan2_ENABLE_AMD:BOOL=ON.");
111 #else
112  typedef typename Adapter::gno_t gno_t;
113  typedef typename Adapter::lno_t lno_t;
114  typedef typename Adapter::offset_t offset_t;
115  typedef typename Adapter::scalar_t scalar_t;
116 
117  int ierr= 0;
118 
119  const auto model = rcp(new GraphModel<Adapter>(adapter, env, comm, graphFlags));
120  const size_t nVtx = model->getLocalNumVertices();
121 
122  //cout << "Local num vertices" << nVtx << endl;
123  ArrayView<const gno_t> edgeIds;
124  ArrayView<const offset_t> offsets;
125  ArrayView<StridedData<lno_t, scalar_t> > wgts;
126 
127  // wgts are ignored in AMD
128  model->getEdgeList(edgeIds, offsets, wgts);
129 
130  // We will always call AMD with SuiteSparse_long
131  AMDTraits<SuiteSparse_long> AMDobj;
132  double Control[AMD_CONTROL];
133  double Info[AMD_INFO];
134 
135  amd_defaults(Control);
136  amd_control(Control);
137 
138  // We will use the lno_t for local ordering
139  lno_t *perm;
140  perm = (lno_t *) (solution->getPermutationRCP().getRawPtr());
141 
142  SuiteSparse_long *amd_offsets, *amd_edgeIds;
144  offsets);
145  // This might throw depending on how SuiteSparse was compiled
146  // with long or long long and the size of both of them
148  edgeIds);
149 
150  SuiteSparse_long amd_nVtx=0;
152 
153  // Allocate a SuiteSparse_long perm
154  SuiteSparse_long *amd_perm = new SuiteSparse_long[amd_nVtx];
155 
156  lno_t result = AMDobj.order(amd_nVtx, amd_offsets,
157  amd_edgeIds, amd_perm, Control, Info);
158 
159  if (result != AMD_OK && result != AMD_OK_BUT_JUMBLED)
160  ierr = -1;
161 
162  // SR: This conversion might throw as we are going from SuiteSparse_long
163  // to lno_t. Another option is to change local ordering solution
164  // to use gno_t everywhere
165  for (size_t i = 0; i < nVtx; i++)
166  TPL_Traits<lno_t, SuiteSparse_long>::ASSIGN(perm[i], amd_perm[i]);
167 
168  // Delete copies
171  delete [] amd_perm;
172 
173  solution->setHavePerm(true);
174  return ierr;
175 #endif
176  }
177 };
178 
179 }
180 
181 
182 
183 #endif
AlgAMD(const RCP< const typename Adapter::base_adapter_t > &adapter__, const RCP< Teuchos::ParameterList > &pl__, const RCP< const Teuchos::Comm< int > > &comm__, RCP< const Environment > &env__, const modelFlag_t &graphFlags__)
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
Defines the OrderingSolution class.
Adapter::scalar_t scalar_t
int localOrder(const RCP< LocalOrderingSolution< typename Adapter::lno_t > > &solution)
Ordering method.
Algorithm defines the base class for all algorithms.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
static void ASSIGN(first_t &a, second_t b)
Traits class to handle conversions between gno_t/lno_t and TPL data types (e.g., ParMETIS&#39;s idx_t...
GraphModel defines the interface required for graph models.
static void ASSIGN_ARRAY(first_t **a, ArrayView< second_t > &b)
Defines the GraphModel interface.
static void DELETE_ARRAY(first_t **a)
int globalOrder(const RCP< GlobalOrderingSolution< typename Adapter::gno_t > > &)
Ordering method.