Zoltan2
Zoltan2_ModelHelpers.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #include <Zoltan2_MeshAdapter.hpp>
51 
52 #ifndef _ZOLTAN2_MODELHELPERS_HPP_
53 #define _ZOLTAN2_MODELHELPERS_HPP_
54 
55 namespace Zoltan2 {
56 
57 //GFD this declaration is really messy is there a better way? I couldn't typedef outside since
58 // there is no user type until the function.
59 template <typename User>
60 RCP<Tpetra::CrsMatrix<int,
61  typename MeshAdapter<User>::lno_t,
62  typename MeshAdapter<User>::gno_t,
63  typename MeshAdapter<User>::node_t> >
64 get2ndAdjsMatFromAdjs(const Teuchos::RCP<const MeshAdapter<User> > &ia,
65  const RCP<const Comm<int> > comm,
66  Zoltan2::MeshEntityType sourcetarget,
67  Zoltan2::MeshEntityType through) {
68  typedef typename MeshAdapter<User>::gno_t gno_t;
69  typedef typename MeshAdapter<User>::lno_t lno_t;
70  typedef typename MeshAdapter<User>::node_t node_t;
71 
72  typedef int nonzero_t; // adjacency matrix doesn't need scalar_t
73  typedef Tpetra::CrsMatrix<nonzero_t,lno_t,gno_t,node_t> sparse_matrix_type;
74  typedef Tpetra::Map<lno_t, gno_t, node_t> map_type;
75  typedef Tpetra::global_size_t GST;
76  const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
77 
78 /* Find the adjacency for a nodal based decomposition */
79  if (ia->availAdjs(sourcetarget, through)) {
80  using Tpetra::DefaultPlatform;
81  using Teuchos::Array;
82  using Teuchos::as;
83  using Teuchos::RCP;
84  using Teuchos::rcp;
85 
86  // Get node-element connectivity
87 
88  const lno_t *offsets=NULL;
89  const gno_t *adjacencyIds=NULL;
90  ia->getAdjsView(sourcetarget, through, offsets, adjacencyIds);
91 
92  gno_t const *Ids=NULL;
93  ia->getIDsViewOf(sourcetarget, Ids);
94 
95  gno_t const *throughIds=NULL;
96  ia->getIDsViewOf(through, throughIds);
97 
98  size_t LocalNumIDs = ia->getLocalNumOf(sourcetarget);
99 
100  /***********************************************************************/
101  /************************* BUILD MAPS FOR ADJS *************************/
102  /***********************************************************************/
103 
104  Array<gno_t> sourcetargetGIDs;
105  Array<gno_t> throughGIDs;
106  RCP<const map_type> sourcetargetMapG;
107  RCP<const map_type> throughMapG;
108 
109  // count owned nodes
110  size_t LocalNumOfThrough = ia->getLocalNumOf(through);
111 
112  // Build a list of the global sourcetarget ids...
113  sourcetargetGIDs.resize (LocalNumIDs);
114  throughGIDs.resize (LocalNumOfThrough);
115  gno_t min[2];
116  min[0] = as<gno_t> (Ids[0]);
117  for (size_t i = 0; i < LocalNumIDs; ++i) {
118  sourcetargetGIDs[i] = as<gno_t> (Ids[i]);
119 
120  if (sourcetargetGIDs[i] < min[0]) {
121  min[0] = sourcetargetGIDs[i];
122  }
123  }
124 
125  // min(throughIds[i])
126  min[1] = as<gno_t> (throughIds[0]);
127  for (size_t i = 0; i < LocalNumOfThrough; ++i) {
128  throughGIDs[i] = as<gno_t> (throughIds[i]);
129 
130  if (throughGIDs[i] < min[1]) {
131  min[1] = throughGIDs[i];
132  }
133  }
134 
135  gno_t gmin[2];
136  Teuchos::reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MIN, 2, min, gmin);
137 
138  //Generate Map for sourcetarget.
139  sourcetargetMapG = rcp(new map_type(//ia->getGlobalNumOf(sourcetarget),
140  INVALID,
141  sourcetargetGIDs(), gmin[0], comm));
142 
143  //Create a new map with IDs uniquely assigned to ranks (oneToOneSTMap)
144  /*RCP<const map_type> oneToOneSTMap =
145  Tpetra::createOneToOne<lno_t, gno_t, node_t>(sourcetargetMapG);*/
146 
147  //Generate Map for through.
148 // TODO
149 // TODO Could check for max through id as well, and if all through ids are
150 // TODO in gmin to gmax, then default constructors works below.
151 // TODO Otherwise, may need a constructor that is not one-to-one containing
152 // TODO all through entities on processor, followed by call to createOneToOne
153 // TODO
154 
155  throughMapG = rcp (new map_type(INVALID,//ia->getGlobalNumOf(through),
156  throughGIDs, gmin[1], comm));
157 
158  //Create a new map with IDs uniquely assigned to ranks (oneToOneTMap)
159  RCP<const map_type> oneToOneTMap =
160  Tpetra::createOneToOne<lno_t, gno_t, node_t>(throughMapG);
161 
162  /***********************************************************************/
163  /************************* BUILD GRAPH FOR ADJS ************************/
164  /***********************************************************************/
165 
166  RCP<sparse_matrix_type> adjsMatrix;
167 
168  // Construct Tpetra::CrsGraph objects.
169  adjsMatrix = rcp (new sparse_matrix_type (sourcetargetMapG,//oneToOneSTMap,
170  0));
171 
172  nonzero_t justOne = 1;
173  ArrayView<nonzero_t> justOneAV = Teuchos::arrayView (&justOne, 1);
174 
175  for (size_t localElement=0; localElement<LocalNumIDs; ++localElement){
176 
177  //globalRow for Tpetra Graph
178  gno_t globalRowT = as<gno_t> (Ids[localElement]);
179 
180 // TODO: can we insert all adjacencies at once instead of one at a time
181 // (since they are contiguous in adjacencyIds)?
182 // TODO: maybe not until we get rid of zgid_t, as we need the conversion to gno_t.
183  for (lno_t j=offsets[localElement]; j<offsets[localElement+1]; ++j){
184  gno_t globalCol = as<gno_t> (adjacencyIds[j]);
185  //create ArrayView globalCol object for Tpetra
186  ArrayView<gno_t> globalColAV = Teuchos::arrayView (&globalCol,1);
187 
188  //Update Tpetra adjs Graph
189  adjsMatrix->insertGlobalValues(globalRowT,globalColAV,justOneAV);
190  }// *** through loop ***
191  }// *** source loop ***
192 
193  //Fill-complete adjs Graph
194  adjsMatrix->fillComplete (oneToOneTMap, //throughMapG,
195  adjsMatrix->getRowMap());
196 
197  // Form 2ndAdjs
198  RCP<sparse_matrix_type> secondAdjs =
199  rcp (new sparse_matrix_type(adjsMatrix->getRowMap(),0));
200  Tpetra::MatrixMatrix::Multiply(*adjsMatrix,false,*adjsMatrix,
201  true,*secondAdjs);
202  return secondAdjs;
203  }
204  return RCP<sparse_matrix_type>();
205 }
206 
207 template <typename User>
208 void get2ndAdjsViewFromAdjs(const Teuchos::RCP<const MeshAdapter<User> > &ia,
209  const RCP<const Comm<int> > comm,
210  Zoltan2::MeshEntityType sourcetarget,
211  Zoltan2::MeshEntityType through,
212  const typename MeshAdapter<User>::lno_t *&offsets,
213  const typename MeshAdapter<User>::gno_t *&adjacencyIds)
214 {
215  typedef typename MeshAdapter<User>::gno_t gno_t;
216  typedef typename MeshAdapter<User>::lno_t lno_t;
217  typedef typename MeshAdapter<User>::node_t node_t;
218 
219  typedef int nonzero_t; // adjacency matrix doesn't need scalar_t
220  typedef Tpetra::CrsMatrix<nonzero_t,lno_t,gno_t,node_t> sparse_matrix_type;
221 
222  RCP<sparse_matrix_type> secondAdjs = get2ndAdjsMatFromAdjs(ia,comm,sourcetarget,through);
223 
224  if (secondAdjs!=RCP<sparse_matrix_type>()) {
225  Array<gno_t> Indices;
226  Array<nonzero_t> Values;
227 
228  size_t nadj = 0;
229 
230  gno_t const *Ids=NULL;
231  ia->getIDsViewOf(sourcetarget, Ids);
232 
233  gno_t const *throughIds=NULL;
234  ia->getIDsViewOf(through, throughIds);
235 
236  /* Allocate memory necessary for the adjacency */
237  size_t LocalNumIDs = ia->getLocalNumOf(sourcetarget);
238  lno_t *start = new lno_t [LocalNumIDs+1];
239  std::vector<gno_t> adj;
240 
241  for (size_t localElement=0; localElement<LocalNumIDs; ++localElement){
242  start[localElement] = nadj;
243  const gno_t globalRow = Ids[localElement];
244  size_t NumEntries = secondAdjs->getNumEntriesInGlobalRow (globalRow);
245  Indices.resize (NumEntries);
246  Values.resize (NumEntries);
247  secondAdjs->getGlobalRowCopy (globalRow,Indices(),Values(),NumEntries);
248 
249  for (size_t j = 0; j < NumEntries; ++j) {
250  if(globalRow != Indices[j]) {
251  adj.push_back(Indices[j]);
252  nadj++;;
253  }
254  }
255  }
256 
257  Ids = NULL;
258  start[LocalNumIDs] = nadj;
259 
260  gno_t *adj_ = new gno_t [nadj];
261 
262  for (size_t i=0; i < nadj; i++) {
263  adj_[i] = adj[i];
264  }
265 
266  offsets = start;
267  adjacencyIds = adj_;
268  }
269 
270  //return nadj;
271 }
272 
273 }
274 
275 #endif
#define INVALID(STR)
RCP< Tpetra::CrsMatrix< int, typename MeshAdapter< User >::lno_t, typename MeshAdapter< User >::gno_t, typename MeshAdapter< User >::node_t > > get2ndAdjsMatFromAdjs(const Teuchos::RCP< const MeshAdapter< User > > &ia, const RCP< const Comm< int > > comm, Zoltan2::MeshEntityType sourcetarget, Zoltan2::MeshEntityType through)
InputTraits< User >::gno_t gno_t
size_t global_size_t
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
void get2ndAdjsViewFromAdjs(const Teuchos::RCP< const MeshAdapter< User > > &ia, const RCP< const Comm< int > > comm, Zoltan2::MeshEntityType sourcetarget, Zoltan2::MeshEntityType through, const typename MeshAdapter< User >::lno_t *&offsets, const typename MeshAdapter< User >::gno_t *&adjacencyIds)
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.