MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_MatlabUtils_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
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
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef MUELU_MATLABUTILS_DEF_HPP
48 #define MUELU_MATLABUTILS_DEF_HPP
49 
51 
52 #if !defined(HAVE_MUELU_MATLAB) || !defined(HAVE_MUELU_EPETRA)
53 #error "Muemex types require MATLAB, Epetra and Tpetra."
54 #else
55 
56 using Teuchos::RCP;
57 using Teuchos::rcp;
58 using namespace std;
59 
60 namespace MueLu {
61 
62 extern bool rewrap_ints;
63 
64 /* ******************************* */
65 /* getMuemexType */
66 /* ******************************* */
67 
68 template <typename T>
69 MuemexType getMuemexType(const T& data) { throw std::runtime_error("Unknown Type"); }
70 
71 template <>
72 MuemexType getMuemexType(const int& data) { return INT; }
73 template <>
75 template <>
77 
78 template <>
79 MuemexType getMuemexType(const double& data) { return DOUBLE; }
80 template <>
82 
83 template <>
84 MuemexType getMuemexType(const std::string& data) { return STRING; }
85 template <>
87 
88 template <>
89 MuemexType getMuemexType(const complex_t& data) { return COMPLEX; }
90 template <>
92 
93 template <>
95 template <>
96 MuemexType getMuemexType<RCP<Xpetra_map> >() { return XPETRA_MAP; }
97 
98 template <>
100 template <>
101 MuemexType getMuemexType<RCP<Xpetra_ordinal_vector> >() { return XPETRA_ORDINAL_VECTOR; }
102 
103 template <>
105 template <>
106 MuemexType getMuemexType<RCP<Tpetra_MultiVector_double> >() { return TPETRA_MULTIVECTOR_DOUBLE; }
107 
108 template <>
110 template <>
111 MuemexType getMuemexType<RCP<Tpetra_MultiVector_complex> >() { return TPETRA_MULTIVECTOR_COMPLEX; }
112 
113 template <>
115 template <>
116 MuemexType getMuemexType<RCP<Tpetra_CrsMatrix_double> >() { return TPETRA_MATRIX_DOUBLE; }
117 
118 template <>
120 template <>
121 MuemexType getMuemexType<RCP<Tpetra_CrsMatrix_complex> >() { return TPETRA_MATRIX_COMPLEX; }
122 
123 template <>
125 template <>
126 MuemexType getMuemexType<RCP<Xpetra_MultiVector_double> >() { return XPETRA_MULTIVECTOR_DOUBLE; }
127 
128 template <>
130 template <>
131 MuemexType getMuemexType<RCP<Xpetra_MultiVector_complex> >() { return XPETRA_MULTIVECTOR_COMPLEX; }
132 
133 template <>
135 template <>
136 MuemexType getMuemexType<RCP<Xpetra_Matrix_double> >() { return XPETRA_MATRIX_DOUBLE; }
137 
138 template <>
140 template <>
141 MuemexType getMuemexType<RCP<Xpetra_Matrix_complex> >() { return XPETRA_MATRIX_COMPLEX; }
142 
143 template <>
145 template <>
146 MuemexType getMuemexType<RCP<Epetra_CrsMatrix> >() { return EPETRA_CRSMATRIX; }
147 
148 template <>
150 template <>
151 MuemexType getMuemexType<RCP<Epetra_MultiVector> >() { return EPETRA_MULTIVECTOR; }
152 
153 template <>
155 template <>
156 MuemexType getMuemexType<RCP<MAggregates> >() { return AGGREGATES; }
157 
158 template <>
160 template <>
161 MuemexType getMuemexType<RCP<MAmalInfo> >() { return AMALGAMATION_INFO; }
162 
163 template <>
164 MuemexType getMuemexType(const RCP<MGraph>& data) { return GRAPH; }
165 template <>
166 MuemexType getMuemexType<RCP<MGraph> >() { return GRAPH; }
167 
168 #ifdef HAVE_MUELU_INTREPID2
169 template <>
170 MuemexType getMuemexType(const RCP<FieldContainer_ordinal>& data) { return FIELDCONTAINER_ORDINAL; }
171 template <>
172 MuemexType getMuemexType<RCP<FieldContainer_ordinal> >() { return FIELDCONTAINER_ORDINAL; }
173 #endif
174 
175 /* "prototypes" for specialized functions used in other specialized functions */
176 
177 template <>
178 mxArray* createMatlabSparse<double>(int numRows, int numCols, int nnz);
179 template <>
180 mxArray* createMatlabSparse<complex_t>(int numRows, int numCols, int nnz);
181 template <>
182 mxArray* createMatlabMultiVector<double>(int numRows, int numCols);
183 template <>
184 mxArray* createMatlabMultiVector<complex_t>(int numRows, int numCols);
185 template <>
186 void fillMatlabArray<double>(double* array, const mxArray* mxa, int n);
187 template <>
188 void fillMatlabArray<complex_t>(complex_t* array, const mxArray* mxa, int n);
189 template <>
191 template <>
193 template <>
195 template <>
197 
198 /* ******************************* */
199 /* loadDataFromMatlab */
200 /* ******************************* */
201 
202 template <>
203 int loadDataFromMatlab<int>(const mxArray* mxa) {
204  mxClassID probIDtype = mxGetClassID(mxa);
205  int rv;
206  if (probIDtype == mxINT32_CLASS) {
207  rv = *((int*)mxGetData(mxa));
208  } else if (probIDtype == mxLOGICAL_CLASS) {
209  rv = (int)*((bool*)mxGetData(mxa));
210  } else if (probIDtype == mxDOUBLE_CLASS) {
211  rv = (int)*((double*)mxGetData(mxa));
212  } else if (probIDtype == mxUINT32_CLASS) {
213  rv = (int)*((unsigned int*)mxGetData(mxa));
214  } else {
215  rv = -1;
216  throw std::runtime_error("Error: Unrecognized numerical type.");
217  }
218  return rv;
219 }
220 
221 template <>
222 bool loadDataFromMatlab<bool>(const mxArray* mxa) {
223  return *((bool*)mxGetData(mxa));
224 }
225 
226 template <>
227 double loadDataFromMatlab<double>(const mxArray* mxa) {
228  return *((double*)mxGetPr(mxa));
229 }
230 
231 template <>
233  double realpart = real<double>(*((double*)mxGetPr(mxa)));
234  double imagpart = imag<double>(*((double*)mxGetPi(mxa)));
235  return complex_t(realpart, imagpart);
236 }
237 
238 template <>
239 string loadDataFromMatlab<string>(const mxArray* mxa) {
240  string rv = "";
241  if (mxGetClassID(mxa) != mxCHAR_CLASS) {
242  throw runtime_error("Can't construct string from anything but a char array.");
243  }
244  rv = string(mxArrayToString(mxa));
245  return rv;
246 }
247 
248 template <>
249 RCP<Xpetra_map> loadDataFromMatlab<RCP<Xpetra_map> >(const mxArray* mxa) {
251  int nr = mxGetM(mxa);
252  int nc = mxGetN(mxa);
253  if (nr != 1)
254  throw std::runtime_error("A Xpetra::Map representation from MATLAB must be a single row vector.");
255  double* pr = mxGetPr(mxa);
256  mm_GlobalOrd numGlobalIndices = nc;
257 
258  std::vector<mm_GlobalOrd> localGIDs(numGlobalIndices);
259  for (int i = 0; i < int(numGlobalIndices); i++) {
260  localGIDs[i] = Teuchos::as<mm_GlobalOrd>(pr[i]);
261  }
262 
263  const Teuchos::ArrayView<const mm_GlobalOrd> localGIDs_view(&localGIDs[0], localGIDs.size());
264  RCP<Xpetra_map> map =
268  localGIDs_view,
269  0, comm);
270 
271  if (map.is_null())
272  throw runtime_error("Failed to create Xpetra::Map.");
273  return map;
274 }
275 
276 template <>
277 RCP<Xpetra_ordinal_vector> loadDataFromMatlab<RCP<Xpetra_ordinal_vector> >(const mxArray* mxa) {
279  if (mxGetN(mxa) != 1 && mxGetM(mxa) != 1)
280  throw std::runtime_error("An OrdinalVector from MATLAB must be a single row or column vector.");
281  mm_GlobalOrd numGlobalIndices = mxGetM(mxa) * mxGetN(mxa);
283  if (mxGetClassID(mxa) != mxINT32_CLASS)
284  throw std::runtime_error("Can only construct LOVector with int32 data.");
285  int* array = (int*)mxGetData(mxa);
286  if (map.is_null())
287  throw runtime_error("Failed to create map for Xpetra ordinal vector.");
289  if (loVec.is_null())
290  throw runtime_error("Failed to create ordinal vector with Xpetra::VectorFactory.");
291  for (int i = 0; i < int(numGlobalIndices); i++) {
292  loVec->replaceGlobalValue(i, 0, array[i]);
293  }
294  return loVec;
295 }
296 
297 template <>
298 RCP<Tpetra_MultiVector_double> loadDataFromMatlab<RCP<Tpetra_MultiVector_double> >(const mxArray* mxa) {
300  try {
301  int nr = mxGetM(mxa);
302  int nc = mxGetN(mxa);
303  double* pr = mxGetPr(mxa);
305  // numGlobalIndices for map constructor is the number of rows in matrix/vectors, right?
307  // Allocate a new array of complex values to use with the multivector
308  Teuchos::ArrayView<const double> arrView(pr, nr * nc);
309  mv = rcp(new Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(map, arrView, size_t(nr), size_t(nc)));
310  } catch (std::exception& e) {
311  mexPrintf("Error constructing Tpetra MultiVector.\n");
312  std::cout << e.what() << std::endl;
313  }
314  return mv;
315 }
316 
317 template <>
318 RCP<Tpetra_MultiVector_complex> loadDataFromMatlab<RCP<Tpetra_MultiVector_complex> >(const mxArray* mxa) {
320  try {
321  int nr = mxGetM(mxa);
322  int nc = mxGetN(mxa);
323  double* pr = mxGetPr(mxa);
324  double* pi = mxGetPi(mxa);
326  // numGlobalIndices for map constructor is the number of rows in matrix/vectors, right?
328  // Allocate a new array of complex values to use with the multivector
329  complex_t* myArr = new complex_t[nr * nc];
330  for (int n = 0; n < nc; n++) {
331  for (int m = 0; m < nr; m++) {
332  myArr[n * nr + m] = complex_t(pr[n * nr + m], pi[n * nr + m]);
333  }
334  }
335  Teuchos::ArrayView<complex_t> arrView(myArr, nr * nc);
337  } catch (std::exception& e) {
338  mexPrintf("Error constructing Tpetra MultiVector.\n");
339  std::cout << e.what() << std::endl;
340  }
341  return mv;
342 }
343 
344 template <>
345 RCP<Tpetra_CrsMatrix_double> loadDataFromMatlab<RCP<Tpetra_CrsMatrix_double> >(const mxArray* mxa) {
346  bool success = false;
348 
349  int* colptr = NULL;
350  int* rowind = NULL;
351 
352  try {
354  // numGlobalIndices is just the number of rows in the matrix
355  const size_t numGlobalIndices = mxGetM(mxa);
356  RCP<const muemex_map_type> rowMap = rcp(new muemex_map_type(numGlobalIndices, 0, comm));
357  RCP<const muemex_map_type> domainMap = rcp(new muemex_map_type(mxGetN(mxa), 0, comm));
358  double* valueArray = mxGetPr(mxa);
359  int nc = mxGetN(mxa);
360  if (rewrap_ints) {
361  // mwIndex_to_int allocates memory so must delete[] later
362  colptr = mwIndex_to_int(nc + 1, mxGetJc(mxa));
363  rowind = mwIndex_to_int(colptr[nc], mxGetIr(mxa));
364  } else {
365  rowind = (int*)mxGetIr(mxa);
366  colptr = (int*)mxGetJc(mxa);
367  }
368  // Need this to convert CSC colptrs to CRS row counts
369  Teuchos::Array<size_t> rowCounts(numGlobalIndices);
370  for (int i = 0; i < nc; i++) {
371  for (int j = colptr[i]; j < colptr[i + 1]; j++) {
372  rowCounts[rowind[j]]++;
373  }
374  }
376  for (int i = 0; i < nc; i++) {
377  for (int j = colptr[i]; j < colptr[i + 1]; j++) {
378  //'array' of 1 element, containing column (in global matrix).
380  //'array' of 1 element, containing value
381  Teuchos::ArrayView<double> vals = Teuchos::ArrayView<double>(&valueArray[j], 1);
382  A->insertGlobalValues(rowind[j], cols, vals);
383  }
384  }
385  A->fillComplete(domainMap, rowMap);
386  if (rewrap_ints) {
387  delete[] rowind;
388  rowind = NULL;
389  delete[] colptr;
390  colptr = NULL;
391  }
392  success = true;
393  } catch (std::exception& e) {
394  if (rewrap_ints) {
395  if (rowind != NULL) delete[] rowind;
396  if (colptr != NULL) delete[] colptr;
397  rowind = NULL;
398  colptr = NULL;
399  }
400  mexPrintf("Error while constructing Tpetra matrix:\n");
401  std::cout << e.what() << std::endl;
402  }
403  if (!success)
404  mexErrMsgTxt("An error occurred while setting up a Tpetra matrix.\n");
405  return A;
406 }
407 
408 template <>
409 RCP<Tpetra_CrsMatrix_complex> loadDataFromMatlab<RCP<Tpetra_CrsMatrix_complex> >(const mxArray* mxa) {
411  // Create a map in order to create the matrix (taken from muelu basic example - complex)
412  try {
414  const Tpetra::global_size_t numGlobalIndices = mxGetM(mxa);
415  const mm_GlobalOrd indexBase = 0;
416  RCP<const muemex_map_type> rowMap = rcp(new muemex_map_type(numGlobalIndices, indexBase, comm));
417  RCP<const muemex_map_type> domainMap = rcp(new muemex_map_type(mxGetN(mxa), indexBase, comm));
418  double* realArray = mxGetPr(mxa);
419  double* imagArray = mxGetPi(mxa);
420  int* colptr;
421  int* rowind;
422  int nc = mxGetN(mxa);
423  if (rewrap_ints) {
424  // mwIndex_to_int allocates memory so must delete[] later
425  colptr = mwIndex_to_int(nc + 1, mxGetJc(mxa));
426  rowind = mwIndex_to_int(colptr[nc], mxGetIr(mxa));
427  } else {
428  rowind = (int*)mxGetIr(mxa);
429  colptr = (int*)mxGetJc(mxa);
430  }
431  // Need this to convert CSC colptrs to CRS row counts
432  Teuchos::Array<size_t> rowCounts(numGlobalIndices);
433  for (int i = 0; i < nc; i++) {
434  for (int j = colptr[i]; j < colptr[i + 1]; j++) {
435  rowCounts[rowind[j]]++;
436  }
437  }
439  for (int i = 0; i < nc; i++) {
440  for (int j = colptr[i]; j < colptr[i + 1]; j++) {
441  // here assuming that complex_t will always be defined as std::complex<double>
442  // use 'value' over and over again with Teuchos::ArrayViews to insert into matrix
443  complex_t value = std::complex<double>(realArray[j], imagArray[j]);
446  A->insertGlobalValues(rowind[j], cols, vals);
447  }
448  }
449  A->fillComplete(domainMap, rowMap);
450  if (rewrap_ints) {
451  delete[] rowind;
452  delete[] colptr;
453  }
454  } catch (std::exception& e) {
455  mexPrintf("Error while constructing tpetra matrix:\n");
456  std::cout << e.what() << std::endl;
457  }
458  return A;
459 }
460 
461 template <>
462 RCP<Xpetra::Matrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > loadDataFromMatlab<RCP<Xpetra::Matrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(const mxArray* mxa) {
463  RCP<Tpetra::CrsMatrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > tmat = loadDataFromMatlab<RCP<Tpetra::CrsMatrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(mxa);
464  return MueLu::TpetraCrs_To_XpetraMatrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(tmat);
465 }
466 
467 template <>
468 RCP<Xpetra::Matrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > loadDataFromMatlab<RCP<Xpetra::Matrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(const mxArray* mxa) {
469  RCP<Tpetra::CrsMatrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > tmat = loadDataFromMatlab<RCP<Tpetra::CrsMatrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(mxa);
470  return MueLu::TpetraCrs_To_XpetraMatrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(tmat);
471 }
472 
473 template <>
474 RCP<Xpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > loadDataFromMatlab<RCP<Xpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(const mxArray* mxa) {
475  RCP<Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > tpetraMV = loadDataFromMatlab<RCP<Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(mxa);
476  return MueLu::TpetraMultiVector_To_XpetraMultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(tpetraMV);
477 }
478 
479 template <>
480 RCP<Xpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > loadDataFromMatlab<RCP<Xpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(const mxArray* mxa) {
481  RCP<Tpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > tpetraMV = loadDataFromMatlab<RCP<Tpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t> > >(mxa);
482  return MueLu::TpetraMultiVector_To_XpetraMultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(tpetraMV);
483 }
484 
485 template <>
486 RCP<Epetra_CrsMatrix> loadDataFromMatlab<RCP<Epetra_CrsMatrix> >(const mxArray* mxa) {
487  RCP<Epetra_CrsMatrix> matrix;
488  try {
489  int* colptr;
490  int* rowind;
491  double* vals = mxGetPr(mxa);
492  int nr = mxGetM(mxa);
493  int nc = mxGetN(mxa);
494  if (rewrap_ints) {
495  colptr = mwIndex_to_int(nc + 1, mxGetJc(mxa));
496  rowind = mwIndex_to_int(colptr[nc], mxGetIr(mxa));
497  } else {
498  rowind = (int*)mxGetIr(mxa);
499  colptr = (int*)mxGetJc(mxa);
500  }
501  Epetra_SerialComm Comm;
502  Epetra_Map RangeMap(nr, 0, Comm);
503  Epetra_Map DomainMap(nc, 0, Comm);
504  matrix = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy, RangeMap, DomainMap, 0));
505  /* Do the matrix assembly */
506  for (int i = 0; i < nc; i++) {
507  for (int j = colptr[i]; j < colptr[i + 1]; j++) {
508  // global row, # of entries, value array, column indices array
509  matrix->InsertGlobalValues(rowind[j], 1, &vals[j], &i);
510  }
511  }
512  matrix->FillComplete(DomainMap, RangeMap);
513  if (rewrap_ints) {
514  delete[] rowind;
515  delete[] colptr;
516  }
517  } catch (std::exception& e) {
518  mexPrintf("An error occurred while setting up an Epetra matrix:\n");
519  std::cout << e.what() << std::endl;
520  }
521  return matrix;
522 }
523 
524 template <>
525 RCP<Epetra_MultiVector> loadDataFromMatlab<RCP<Epetra_MultiVector> >(const mxArray* mxa) {
526  int nr = mxGetM(mxa);
527  int nc = mxGetN(mxa);
528  Epetra_SerialComm Comm;
529  Epetra_BlockMap map(nr * nc, 1, 0, Comm);
530  return rcp(new Epetra_MultiVector(Epetra_DataAccess::Copy, map, mxGetPr(mxa), nr, nc));
531 }
532 
533 template <>
534 RCP<MAggregates> loadDataFromMatlab<RCP<MAggregates> >(const mxArray* mxa) {
535  if (mxGetNumberOfElements(mxa) != 1)
536  throw runtime_error("Aggregates must be individual structs in MATLAB.");
537  if (!mxIsStruct(mxa))
538  throw runtime_error("Trying to pull aggregates from non-struct MATLAB object.");
539  // assume that in matlab aggregate structs will only be stored in a 1x1 array
540  // mxa must have the same fields as the ones declared in constructAggregates function in muelu.m for this to work
541  const int correctNumFields = 5; // change if more fields are added to the aggregates representation in constructAggregates in muelu.m
542  if (mxGetNumberOfFields(mxa) != correctNumFields)
543  throw runtime_error("Aggregates structure has wrong number of fields.");
544  // Pull MuemexData types back out
545  int nVert = *(int*)mxGetData(mxGetField(mxa, 0, "nVertices"));
546  int nAgg = *(int*)mxGetData(mxGetField(mxa, 0, "nAggregates"));
547  // Now have all the data needed to fully reconstruct the aggregate
548  // Use similar approach as UserAggregationFactory (which is written for >1 thread but will just be serial here)
550  int myRank = comm->getRank();
553  RCP<MAggregates> agg = rcp(new MAggregates(map));
554  agg->SetNumAggregates(nAgg);
555  // Get handles for the vertex2AggId and procwinner arrays in reconstituted aggregates object
556  // this is serial so all procwinner values will be same (0)
557  ArrayRCP<mm_LocalOrd> vertex2AggId = agg->GetVertex2AggId()->getDataNonConst(0); // the '0' means first (and only) column of multivector, since is just vector
558  ArrayRCP<mm_LocalOrd> procWinner = agg->GetProcWinner()->getDataNonConst(0);
559  // mm_LocalOrd and int are equivalent, so is ok to talk about aggSize with just 'int'
560  // Deep copy the entire vertex2AggID and isRoot arrays, which are both nVert items long
561  // At the same time, set ProcWinner
562  mxArray* vertToAggID_in = mxGetField(mxa, 0, "vertexToAggID");
563  int* vertToAggID_inArray = (int*)mxGetData(vertToAggID_in);
564  mxArray* rootNodes_in = mxGetField(mxa, 0, "rootNodes");
565  int* rootNodes_inArray = (int*)mxGetData(rootNodes_in);
566  for (int i = 0; i < nVert; i++) {
567  vertex2AggId[i] = vertToAggID_inArray[i];
568  procWinner[i] = myRank; // all nodes are going to be on the same proc
569  agg->SetIsRoot(i, false); // the ones that are root will be set in next loop
570  }
571  for (int i = 0; i < nAgg; i++) // rootNodesToCopy is an array of node IDs which are the roots of their aggs
572  {
573  agg->SetIsRoot(rootNodes_inArray[i], true);
574  }
575  // Now recompute the aggSize array the results in the object
576  agg->ComputeAggregateSizes(true);
577  agg->AggregatesCrossProcessors(false);
578  return agg;
579 }
580 
581 template <>
582 RCP<MAmalInfo> loadDataFromMatlab<RCP<MAmalInfo> >(const mxArray* mxa) {
583  RCP<MAmalInfo> amal;
584  throw runtime_error("AmalgamationInfo not supported in Muemex yet.");
585  return amal;
586 }
587 
588 template <>
589 RCP<MGraph> loadDataFromMatlab<RCP<MGraph> >(const mxArray* mxa) {
590  // mxa must be struct with logical sparse matrix called 'edges' and Nx1 int32 array 'boundaryNodes'
591  mxArray* edges = mxGetField(mxa, 0, "edges");
592  mxArray* boundaryNodes = mxGetField(mxa, 0, "boundaryNodes");
593  if (edges == NULL)
594  throw runtime_error("Graph structure in MATLAB must have a field called 'edges' (logical sparse matrix)");
595  if (boundaryNodes == NULL)
596  throw runtime_error("Graph structure in MATLAB must have a field called 'boundaryNodes' (int32 array containing list of boundary nodes)");
597  int* boundaryList = (int*)mxGetData(boundaryNodes);
598  if (!mxIsSparse(edges) || mxGetClassID(edges) != mxLOGICAL_CLASS)
599  throw runtime_error("Graph edges must be stored as a logical sparse matrix.");
600  // Note that Matlab stores sparse matrices in column major format.
601  mwIndex* matlabColPtrs = mxGetJc(edges);
602  mwIndex* matlabRowIndices = mxGetIr(edges);
603  mm_GlobalOrd nRows = (mm_GlobalOrd)mxGetM(edges);
604 
605  // Create and populate row-major CRS data structures for Xpetra::TpetraCrsGraph.
606 
607  // calculate number of nonzeros in each row
608  Teuchos::Array<int> entriesPerRow(nRows);
609  int nnz = matlabColPtrs[mxGetN(edges)]; // last entry in matlabColPtrs
610  for (int i = 0; i < nnz; i++)
611  entriesPerRow[matlabRowIndices[i]]++;
612  // Populate usual row index array. We don't need this for the Xpetra Graph ctor, but
613  // it's convenient for building up the column index array, which the ctor does need.
614  Teuchos::Array<int> rows(nRows + 1);
615  rows[0] = 0;
616  for (int i = 0; i < nRows; i++)
617  rows[i + 1] = rows[i] + entriesPerRow[i];
618  Teuchos::Array<int> cols(nnz); // column index array
619  Teuchos::Array<int> insertionsPerRow(nRows, 0); // track of #insertions done per row
620  int ncols = mxGetN(edges);
621  for (int colNum = 0; colNum < ncols; ++colNum) {
622  int ci = matlabColPtrs[colNum];
623  for (int j = ci; j < Teuchos::as<int>(matlabColPtrs[colNum + 1]); ++j) {
624  int rowNum = matlabRowIndices[j];
625  cols[rows[rowNum] + insertionsPerRow[rowNum]] = colNum;
626  insertionsPerRow[rowNum]++;
627  }
628  }
629  // Find maximum
630  int maxNzPerRow = 0;
631  for (int i = 0; i < nRows; i++) {
632  if (maxNzPerRow < entriesPerRow[i])
633  maxNzPerRow = entriesPerRow[i];
634  }
635 
638  RCP<MMap> map = rcp(new MMap(nRows, 0, comm));
640  RCP<TpetraGraph> tgraph = rcp(new TpetraGraph(map, (size_t)maxNzPerRow));
641  // Populate tgraph in compressed-row format. Must get each row individually...
642  for (int i = 0; i < nRows; ++i) {
643  tgraph->insertGlobalIndices((mm_GlobalOrd)i, cols(rows[i], entriesPerRow[i]));
644  }
645  tgraph->fillComplete(map, map);
647  // Set boundary nodes
648  int numBoundaryNodes = mxGetNumberOfElements(boundaryNodes);
649  bool* boundaryFlags = new bool[nRows];
650  for (int i = 0; i < nRows; i++) {
651  boundaryFlags[i] = false;
652  }
653  for (int i = 0; i < numBoundaryNodes; i++) {
654  boundaryFlags[boundaryList[i]] = true;
655  }
656  ArrayRCP<bool> boundaryNodesInput(boundaryFlags, 0, nRows, true);
657  mgraph->SetBoundaryNodeMap(boundaryNodesInput);
658  return mgraph;
659 }
660 
661 #ifdef HAVE_MUELU_INTREPID2
662 template <>
663 RCP<FieldContainer_ordinal> loadDataFromMatlab<RCP<FieldContainer_ordinal> >(const mxArray* mxa) {
664  if (mxGetClassID(mxa) != mxINT32_CLASS)
665  throw runtime_error("FieldContainer must have integer storage entries");
666 
667  int* data = (int*)mxGetData(mxa);
668  int nr = mxGetM(mxa);
669  int nc = mxGetN(mxa);
670 
671  RCP<FieldContainer_ordinal> fc = rcp(new FieldContainer_ordinal("FC from Matlab", nr, nc));
672  for (int col = 0; col < nc; col++) {
673  for (int row = 0; row < nr; row++) {
674  (*fc)(row, col) = data[col * nr + row];
675  }
676  }
677  return fc;
678 }
679 #endif
680 
681 /* ******************************* */
682 /* saveDataToMatlab */
683 /* ******************************* */
684 
685 template <>
686 mxArray* saveDataToMatlab(int& data) {
687  mwSize dims[] = {1, 1};
688  mxArray* mxa = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
689  *((int*)mxGetData(mxa)) = data;
690  return mxa;
691 }
692 
693 template <>
694 mxArray* saveDataToMatlab(bool& data) {
695  mwSize dims[] = {1, 1};
696  mxArray* mxa = mxCreateLogicalArray(2, dims);
697  *((bool*)mxGetData(mxa)) = data;
698  return mxa;
699 }
700 
701 template <>
702 mxArray* saveDataToMatlab(double& data) {
703  return mxCreateDoubleScalar(data);
704 }
705 
706 template <>
707 mxArray* saveDataToMatlab(complex_t& data) {
708  mwSize dims[] = {1, 1};
709  mxArray* mxa = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxCOMPLEX);
710  *((double*)mxGetPr(mxa)) = real<double>(data);
711  *((double*)mxGetPi(mxa)) = imag<double>(data);
712  return mxa;
713 }
714 
715 template <>
716 mxArray* saveDataToMatlab(string& data) {
717  return mxCreateString(data.c_str());
718 }
719 
720 template <>
722  // Precondition: Memory has already been allocated by MATLAB for the array.
723  int nc = data->getGlobalNumElements();
724  int nr = 1;
725  mxArray* output = createMatlabMultiVector<double>(nr, nc);
726  double* array = (double*)malloc(sizeof(double) * nr * nc);
727  for (int col = 0; col < nc; col++) {
728  mm_GlobalOrd gid = data->getGlobalElement(col);
729  array[col] = Teuchos::as<double>(gid);
730  }
731  fillMatlabArray<double>(array, output, nc * nr);
732  free(array);
733  return output;
734 }
735 
736 template <>
738  mwSize len = data->getGlobalLength();
739  // create a single column vector
740  mwSize dimensions[] = {len, 1};
741  mxArray* rv = mxCreateNumericArray(2, dimensions, mxINT32_CLASS, mxREAL);
742  int* dataPtr = (int*)mxGetData(rv);
743  ArrayRCP<const mm_LocalOrd> arr = data->getData(0);
744  for (int i = 0; i < int(data->getGlobalLength()); i++) {
745  dataPtr[i] = arr[i];
746  }
747  return rv;
748 }
749 
750 template <>
753  return saveDataToMatlab(xmv);
754 }
755 
756 template <>
759  return saveDataToMatlab(xmv);
760 }
761 
762 template <>
765  return saveDataToMatlab(xmat);
766 }
767 
768 template <>
771  return saveDataToMatlab(xmat);
772 }
773 
774 template <>
776  typedef double Scalar;
777  // Compute global constants, if we need them
778  Teuchos::rcp_const_cast<Xpetra_CrsGraph>(data->getCrsGraph())->computeGlobalConstants();
779 
780  int nr = data->getGlobalNumRows();
781  int nc = data->getGlobalNumCols();
782  int nnz = data->getGlobalNumEntries();
783 
784 #ifdef VERBOSE_OUTPUT
785  RCP<Teuchos::FancyOStream> fancyStream = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
786  mat->describe(*fancyStream, Teuchos::VERB_EXTREME);
787 #endif
788  mxArray* mxa = createMatlabSparse<Scalar>(nr, nc, nnz);
789  mwIndex* ir = mxGetIr(mxa);
790  mwIndex* jc = mxGetJc(mxa);
791  for (int i = 0; i < nc + 1; i++) {
792  jc[i] = 0;
793  }
794 
795  size_t maxEntriesPerRow = data->getGlobalMaxNumRowEntries();
796  if (maxEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid() || maxEntriesPerRow == 0) maxEntriesPerRow = data->getLocalMaxNumRowEntries();
797 
798  int* rowProgress = new int[nc];
799  // The array that will be copied to Pr and (if complex) Pi later
800  Scalar* sparseVals = new Scalar[nnz];
801  size_t numEntries;
802  if (data->isLocallyIndexed()) {
803  Scalar* rowValArray = new Scalar[maxEntriesPerRow];
804  Teuchos::ArrayView<Scalar> rowVals(rowValArray, maxEntriesPerRow);
805  mm_LocalOrd* rowIndicesArray = new mm_LocalOrd[maxEntriesPerRow];
806  Teuchos::ArrayView<mm_LocalOrd> rowIndices(rowIndicesArray, maxEntriesPerRow);
807  for (mm_LocalOrd m = 0; m < nr; m++) // All rows in the Xpetra matrix
808  {
809  data->getLocalRowCopy(m, rowIndices, rowVals, numEntries); // Get the row
810  for (mm_LocalOrd entry = 0; entry < int(numEntries); entry++) // All entries in row
811  {
812  jc[rowIndices[entry] + 1]++; // for each entry, increase jc for the entry's column
813  }
814  }
815 
816  // now jc holds the number of elements in each column, but needs cumulative sum over all previous columns also
817  int entriesAccum = 0;
818  for (int n = 0; n <= nc; n++) {
819  int temp = entriesAccum;
820  entriesAccum += jc[n];
821  jc[n] += temp;
822  }
823  // Jc now populated with colptrs
824  for (int i = 0; i < nc; i++) {
825  rowProgress[i] = 0;
826  }
827  // Row progress values like jc but keep track as the MATLAB matrix is being filled in
828  for (mm_LocalOrd m = 0; m < nr; m++) // rows
829  {
830  data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
831  for (mm_LocalOrd i = 0; i < int(numEntries); i++) // entries in row m (NOT columns)
832  {
833  // row is m, col is rowIndices[i], val is rowVals[i]
834  mm_LocalOrd col = rowIndices[i];
835  sparseVals[jc[col] + rowProgress[col]] = rowVals[i]; // Set value
836  ir[jc[col] + rowProgress[col]] = m; // Set row at which value occurs
837  rowProgress[col]++;
838  }
839  }
840  delete[] rowIndicesArray;
841  } else {
844  for (mm_GlobalOrd m = 0; m < nr; m++) {
845  data->getGlobalRowView(m, rowIndices, rowVals);
846  for (mm_GlobalOrd n = 0; n < rowIndices.size(); n++) {
847  jc[rowIndices[n] + 1]++;
848  }
849  }
850  // Last element of jc is just nnz
851  jc[nc] = nnz;
852  // Jc now populated with colptrs
853  for (int i = 0; i < nc; i++) {
854  rowProgress[i] = 0;
855  }
856  int entriesAccum = 0;
857  for (int n = 0; n <= nc; n++) {
858  int temp = entriesAccum;
859  entriesAccum += jc[n];
860  jc[n] += temp;
861  }
862  // Row progress values like jc but keep track as the MATLAB matrix is being filled in
863  for (mm_GlobalOrd m = 0; m < nr; m++) // rows
864  {
865  data->getGlobalRowView(m, rowIndices, rowVals);
866  for (mm_LocalOrd i = 0; i < rowIndices.size(); i++) // entries in row m
867  {
868  mm_GlobalOrd col = rowIndices[i]; // row is m, col is rowIndices[i], val is rowVals[i]
869  sparseVals[jc[col] + rowProgress[col]] = rowVals[i]; // Set value
870  ir[jc[col] + rowProgress[col]] = m; // Set row at which value occurs
871  rowProgress[col]++;
872  }
873  }
874  }
875  // finally, copy sparseVals into pr (and pi, if complex)
876  fillMatlabArray<Scalar>(sparseVals, mxa, nnz);
877  delete[] sparseVals;
878  delete[] rowProgress;
879  return mxa;
880 }
881 
882 template <>
884  typedef complex_t Scalar;
885 
886  // Compute global constants, if we need them
887  Teuchos::rcp_const_cast<Xpetra_CrsGraph>(data->getCrsGraph())->computeGlobalConstants();
888 
889  int nr = data->getGlobalNumRows();
890  int nc = data->getGlobalNumCols();
891  int nnz = data->getGlobalNumEntries();
892 #ifdef VERBOSE_OUTPUT
893  RCP<Teuchos::FancyOStream> fancyStream = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
894  mat->describe(*fancyStream, Teuchos::VERB_EXTREME);
895 #endif
896  mxArray* mxa = createMatlabSparse<Scalar>(nr, nc, nnz);
897  mwIndex* ir = mxGetIr(mxa);
898  mwIndex* jc = mxGetJc(mxa);
899  for (int i = 0; i < nc + 1; i++) {
900  jc[i] = 0;
901  }
902  size_t maxEntriesPerRow = data->getGlobalMaxNumRowEntries();
903  int* rowProgress = new int[nc];
904  // The array that will be copied to Pr and (if complex) Pi later
905  Scalar* sparseVals = new Scalar[nnz];
906  size_t numEntries;
907  if (data->isLocallyIndexed()) {
908  Scalar* rowValArray = new Scalar[maxEntriesPerRow];
909  Teuchos::ArrayView<Scalar> rowVals(rowValArray, maxEntriesPerRow);
910  mm_LocalOrd* rowIndicesArray = new mm_LocalOrd[maxEntriesPerRow];
911  Teuchos::ArrayView<mm_LocalOrd> rowIndices(rowIndicesArray, maxEntriesPerRow);
912  for (mm_LocalOrd m = 0; m < nr; m++) // All rows in the Xpetra matrix
913  {
914  data->getLocalRowCopy(m, rowIndices, rowVals, numEntries); // Get the row
915  for (mm_LocalOrd entry = 0; entry < int(numEntries); entry++) // All entries in row
916  {
917  jc[rowIndices[entry] + 1]++; // for each entry, increase jc for the entry's column
918  }
919  }
920  // now jc holds the number of elements in each column, but needs cumulative sum over all previous columns also
921  int entriesAccum = 0;
922  for (int n = 0; n <= nc; n++) {
923  int temp = entriesAccum;
924  entriesAccum += jc[n];
925  jc[n] += temp;
926  }
927  // Jc now populated with colptrs
928  for (int i = 0; i < nc; i++) {
929  rowProgress[i] = 0;
930  }
931  // Row progress values like jc but keep track as the MATLAB matrix is being filled in
932  for (mm_LocalOrd m = 0; m < nr; m++) // rows
933  {
934  data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
935  for (mm_LocalOrd i = 0; i < int(numEntries); i++) // entries in row m (NOT columns)
936  {
937  // row is m, col is rowIndices[i], val is rowVals[i]
938  mm_LocalOrd col = rowIndices[i];
939  sparseVals[jc[col] + rowProgress[col]] = rowVals[i]; // Set value
940  ir[jc[col] + rowProgress[col]] = m; // Set row at which value occurs
941  rowProgress[col]++;
942  }
943  }
944  delete[] rowIndicesArray;
945  } else {
948  for (mm_GlobalOrd m = 0; m < nr; m++) {
949  data->getGlobalRowView(m, rowIndices, rowVals);
950  for (mm_GlobalOrd n = 0; n < rowIndices.size(); n++) {
951  jc[rowIndices[n] + 1]++;
952  }
953  }
954  // Last element of jc is just nnz
955  jc[nc] = nnz;
956  // Jc now populated with colptrs
957  for (int i = 0; i < nc; i++) {
958  rowProgress[i] = 0;
959  }
960  int entriesAccum = 0;
961  for (int n = 0; n <= nc; n++) {
962  int temp = entriesAccum;
963  entriesAccum += jc[n];
964  jc[n] += temp;
965  }
966  // Row progress values like jc but keep track as the MATLAB matrix is being filled in
967  for (mm_GlobalOrd m = 0; m < nr; m++) // rows
968  {
969  data->getGlobalRowView(m, rowIndices, rowVals);
970  for (mm_LocalOrd i = 0; i < rowIndices.size(); i++) // entries in row m
971  {
972  mm_GlobalOrd col = rowIndices[i]; // row is m, col is rowIndices[i], val is rowVals[i]
973  sparseVals[jc[col] + rowProgress[col]] = rowVals[i]; // Set value
974  ir[jc[col] + rowProgress[col]] = m; // Set row at which value occurs
975  rowProgress[col]++;
976  }
977  }
978  }
979  // finally, copy sparseVals into pr (and pi, if complex)
980  fillMatlabArray<Scalar>(sparseVals, mxa, nnz);
981  delete[] sparseVals;
982  delete[] rowProgress;
983  return mxa;
984 }
985 
986 /*
987 template<>
988 mxArray* saveDataToMatlab(RCP<Xpetra::MultiVector<Scalar, mm_LocalOrd, mm_GlobalOrd, mm_node_t>>& data)
989 {
990  //Precondition: Memory has already been allocated by MATLAB for the array.
991  int nr = data->getGlobalLength();
992  int nc = data->getNumVectors();
993  mxArray* output = createMatlabMultiVector<Scalar>(nr, nc);
994  Scalar* array = (Scalar*) malloc(sizeof(Scalar) * nr * nc);
995  for(int col = 0; col < nc; col++)
996  {
997  Teuchos::ArrayRCP<const Scalar> colData = data->getData(col);
998  for(int row = 0; row < nr; row++)
999  {
1000  array[col * nr + row] = colData[row];
1001  }
1002  }
1003  fillMatlabArray<Scalar>(array, output, nc * nr);
1004  free(array);
1005  return output;
1006 }
1007 */
1008 
1009 template <>
1011  // Precondition: Memory has already been allocated by MATLAB for the array.
1012  int nr = data->getGlobalLength();
1013  int nc = data->getNumVectors();
1014  mxArray* output = createMatlabMultiVector<double>(nr, nc);
1015  double* array = (double*)malloc(sizeof(double) * nr * nc);
1016  for (int col = 0; col < nc; col++) {
1017  Teuchos::ArrayRCP<const double> colData = data->getData(col);
1018  for (int row = 0; row < nr; row++) {
1019  array[col * nr + row] = colData[row];
1020  }
1021  }
1022  fillMatlabArray<double>(array, output, nc * nr);
1023  free(array);
1024  return output;
1025 }
1026 
1027 template <>
1029  // Precondition: Memory has already been allocated by MATLAB for the array.
1030  int nr = data->getGlobalLength();
1031  int nc = data->getNumVectors();
1032  mxArray* output = createMatlabMultiVector<complex_t>(nr, nc);
1033  complex_t* array = (complex_t*)malloc(sizeof(complex_t) * nr * nc);
1034  for (int col = 0; col < nc; col++) {
1035  Teuchos::ArrayRCP<const complex_t> colData = data->getData(col);
1036  for (int row = 0; row < nr; row++) {
1037  array[col * nr + row] = colData[row];
1038  }
1039  }
1040  fillMatlabArray<complex_t>(array, output, nc * nr);
1041  free(array);
1042  return output;
1043 }
1044 
1045 template <>
1047  RCP<Xpetra_Matrix_double> xmat = EpetraCrs_To_XpetraMatrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(data);
1048  return saveDataToMatlab(xmat);
1049 }
1050 
1051 template <>
1053  mxArray* output = mxCreateDoubleMatrix(data->GlobalLength(), data->NumVectors(), mxREAL);
1054  double* dataPtr = mxGetPr(output);
1055  data->ExtractCopy(dataPtr, data->GlobalLength());
1056  return output;
1057 }
1058 
1059 template <>
1061  // Set up array of inputs for matlab constructAggregates
1062  int numNodes = data->GetVertex2AggId()->getData(0).size();
1063  int numAggs = data->GetNumAggregates();
1064  mxArray* dataIn[5];
1065  mwSize singleton[] = {1, 1};
1066  dataIn[0] = mxCreateNumericArray(2, singleton, mxINT32_CLASS, mxREAL);
1067  *((int*)mxGetData(dataIn[0])) = numNodes;
1068  dataIn[1] = mxCreateNumericArray(2, singleton, mxINT32_CLASS, mxREAL);
1069  *((int*)mxGetData(dataIn[1])) = numAggs;
1070  mwSize nodeArrayDims[] = {(mwSize)numNodes, 1}; // dimensions for Nx1 array, where N is number of nodes (vert2Agg)
1071  dataIn[2] = mxCreateNumericArray(2, nodeArrayDims, mxINT32_CLASS, mxREAL);
1072  int* vtaid = (int*)mxGetData(dataIn[2]);
1073  ArrayRCP<const mm_LocalOrd> vertexToAggID = data->GetVertex2AggId()->getData(0);
1074  for (int i = 0; i < numNodes; i++) {
1075  vtaid[i] = vertexToAggID[i];
1076  }
1077  mwSize aggArrayDims[] = {(mwSize)numAggs, 1}; // dims for Nx1 array, where N is number of aggregates (rootNodes, aggSizes)
1078  dataIn[3] = mxCreateNumericArray(2, aggArrayDims, mxINT32_CLASS, mxREAL);
1079  // First, find out if the aggregates even have 1 root node per aggregate. If not, assume roots are invalid and assign ourselves
1080  int totalRoots = 0;
1081  for (int i = 0; i < numNodes; i++) {
1082  if (data->IsRoot(i))
1083  totalRoots++;
1084  }
1085  bool reassignRoots = false;
1086  if (totalRoots != numAggs) {
1087  cout << endl
1088  << "Warning: Number of root nodes and number of aggregates do not match." << endl;
1089  cout << "Will reassign root nodes when writing aggregates to matlab." << endl
1090  << endl;
1091  reassignRoots = true;
1092  }
1093  int* rn = (int*)mxGetData(dataIn[3]); // list of root nodes (in no particular order)
1094  {
1095  if (reassignRoots) {
1096  // For each aggregate, just pick the first node we see in it and set it as root
1097  int lastFoundNode = 0; // heuristic for speed, a node in aggregate N+1 is likely to come very soon after a node in agg N
1098  for (int i = 0; i < numAggs; i++) {
1099  rn[i] = -1;
1100  for (int j = lastFoundNode; j < lastFoundNode + numNodes; j++) {
1101  int index = j % numNodes;
1102  if (vertexToAggID[index] == i) {
1103  rn[i] = index;
1104  lastFoundNode = index;
1105  }
1106  }
1107  TEUCHOS_TEST_FOR_EXCEPTION(rn[i] == -1, runtime_error, "Invalid aggregates: Couldn't find any node in aggregate #" << i << ".");
1108  }
1109  } else {
1110  int i = 0; // iterates over aggregate IDs
1111  for (int j = 0; j < numNodes; j++) {
1112  if (data->IsRoot(j)) {
1113  if (i == numAggs)
1114  throw runtime_error("Cannot store invalid aggregates in MATLAB - more root nodes than aggregates.");
1115  rn[i] = j; // now we know this won't go out of bounds (rn's underlying matlab array is numAggs in length)
1116  i++;
1117  }
1118  }
1119  if (i + 1 < numAggs)
1120  throw runtime_error("Cannot store invalid aggregates in MATLAB - fewer root nodes than aggregates.");
1121  }
1122  }
1123  dataIn[4] = mxCreateNumericArray(1, aggArrayDims, mxINT32_CLASS, mxREAL);
1124  int* as = (int*)mxGetData(dataIn[4]); // list of aggregate sizes
1125  ArrayRCP<mm_LocalOrd> aggSizes = data->ComputeAggregateSizes();
1126  for (int i = 0; i < numAggs; i++) {
1127  as[i] = aggSizes[i];
1128  }
1129  mxArray* matlabAggs[1];
1130  int result = mexCallMATLAB(1, matlabAggs, 5, dataIn, "constructAggregates");
1131  if (result != 0)
1132  throw runtime_error("Matlab encountered an error while constructing aggregates struct.");
1133  return matlabAggs[0];
1134 }
1135 
1136 template <>
1138  throw runtime_error("AmalgamationInfo not supported in MueMex yet.");
1139  return mxCreateDoubleScalar(0);
1140 }
1141 
1142 template <>
1144  int numEntries = (int)data->GetGlobalNumEdges();
1145  int numRows = (int)data->GetDomainMap()->getGlobalNumElements(); // assume numRows == numCols
1146  mxArray* mat = mxCreateSparseLogicalMatrix(numRows, numRows, numEntries);
1147  mxLogical* outData = (mxLogical*)mxGetData(mat);
1148  mwIndex* rowInds = mxGetIr(mat);
1149  mwIndex* colPtrs = mxGetJc(mat);
1150  mm_LocalOrd* dataCopy = new mm_LocalOrd[numEntries];
1151  mm_LocalOrd* iter = dataCopy;
1152  int* entriesPerRow = new int[numRows];
1153  int* entriesPerCol = new int[numRows];
1154  for (int i = 0; i < numRows; i++) {
1155  entriesPerRow[i] = 0;
1156  entriesPerCol[i] = 0;
1157  }
1158  for (int i = 0; i < numRows; i++) {
1159  ArrayView<const mm_LocalOrd> neighbors = data->getNeighborVertices(i); // neighbors has the column indices for row i
1160  memcpy(iter, neighbors.getRawPtr(), sizeof(mm_LocalOrd) * neighbors.size());
1161  entriesPerRow[i] = neighbors.size();
1162  for (int j = 0; j < neighbors.size(); j++) {
1163  entriesPerCol[neighbors[j]]++;
1164  }
1165  iter += neighbors.size();
1166  }
1167  mwIndex** rowIndsByColumn = new mwIndex*[numRows]; // rowIndsByColumn[0] points to array of row indices in column 1
1168  mxLogical** valuesByColumn = new mxLogical*[numRows];
1169  int* numEnteredPerCol = new int[numRows];
1170  int accum = 0;
1171  for (int i = 0; i < numRows; i++) {
1172  rowIndsByColumn[i] = &rowInds[accum];
1173  // cout << "Entries in column " << i << " start at offset " << accum << endl;
1174  valuesByColumn[i] = &outData[accum];
1175  accum += entriesPerCol[i];
1176  if (accum > numEntries)
1177  throw runtime_error("potato");
1178  }
1179  for (int i = 0; i < numRows; i++) {
1180  numEnteredPerCol[i] = 0; // rowIndsByColumn[n][numEnteredPerCol[n]] gives the next place to put a row index
1181  }
1182  // entriesPerCol now has Jc information (col offsets)
1183  accum = 0; // keep track of cumulative index in dataCopy
1184  for (int row = 0; row < numRows; row++) {
1185  for (int entryInRow = 0; entryInRow < entriesPerRow[row]; entryInRow++) {
1186  int col = dataCopy[accum];
1187  accum++;
1188  rowIndsByColumn[col][numEnteredPerCol[col]] = row;
1189  valuesByColumn[col][numEnteredPerCol[col]] = (mxLogical)1;
1190  numEnteredPerCol[col]++;
1191  }
1192  }
1193  accum = 0; // keep track of total entries over all columns
1194  for (int col = 0; col < numRows; col++) {
1195  colPtrs[col] = accum;
1196  accum += entriesPerCol[col];
1197  }
1198  colPtrs[numRows] = accum; // the last entry in jc, which is equivalent to numEntries
1199  delete[] numEnteredPerCol;
1200  delete[] rowIndsByColumn;
1201  delete[] valuesByColumn;
1202  delete[] dataCopy;
1203  delete[] entriesPerRow;
1204  delete[] entriesPerCol;
1205  // Construct list of boundary nodes
1206  const ArrayRCP<const bool> boundaryFlags = data->GetBoundaryNodeMap();
1207  int numBoundaryNodes = 0;
1208  for (int i = 0; i < boundaryFlags.size(); i++) {
1209  if (boundaryFlags[i])
1210  numBoundaryNodes++;
1211  }
1212  cout << "Graph has " << numBoundaryNodes << " Dirichlet boundary nodes." << endl;
1213  mwSize dims[] = {(mwSize)numBoundaryNodes, 1};
1214  mxArray* boundaryList = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
1215  int* dest = (int*)mxGetData(boundaryList);
1216  int* destIter = dest;
1217  for (int i = 0; i < boundaryFlags.size(); i++) {
1218  if (boundaryFlags[i]) {
1219  *destIter = i;
1220  destIter++;
1221  }
1222  }
1223  mxArray* constructArgs[] = {mat, boundaryList};
1224  mxArray* out[1];
1225  mexCallMATLAB(1, out, 2, constructArgs, "constructGraph");
1226  return out[0];
1227 }
1228 
1229 #ifdef HAVE_MUELU_INTREPID2
1230 template <>
1232  int rank = data->rank();
1233  // NOTE: Only supports rank 2 arrays
1234  if (rank != 2)
1235  throw std::runtime_error("Error: Only rank two FieldContainers are supported.");
1236 
1237  int nr = data->extent(0);
1238  int nc = data->extent(1);
1239 
1240  mwSize dims[] = {(mwSize)nr, (mwSize)nc};
1241  mxArray* mxa = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
1242  int* array = (int*)mxGetData(mxa);
1243 
1244  for (int col = 0; col < nc; col++) {
1245  for (int row = 0; row < nr; row++) {
1246  array[col * nr + row] = (*data)(row, col);
1247  }
1248  }
1249  return mxa;
1250 }
1251 #endif
1252 
1253 template <typename T>
1254 MuemexData<T>::MuemexData(const mxArray* mxa)
1255  : MuemexArg(getMuemexType<T>()) {
1256  data = loadDataFromMatlab<T>(mxa);
1257 }
1258 
1259 template <typename T>
1261  return saveDataToMatlab<T>(data);
1262 }
1263 
1264 template <typename T>
1265 MuemexData<T>::MuemexData(T& dataToCopy, MuemexType dataType)
1266  : MuemexArg(dataType) {
1267  data = dataToCopy;
1268 }
1269 
1270 template <typename T>
1272  : MuemexData(dataToCopy, getMuemexType(dataToCopy)) {}
1273 
1274 template <typename T>
1276  return data;
1277 }
1278 
1279 template <typename T>
1280 void MuemexData<T>::setData(T& newData) {
1281  this->data = newData;
1282 }
1283 
1284 /* ***************************** */
1285 /* More Template Functions */
1286 /* ***************************** */
1287 
1288 template <typename T>
1289 void addLevelVariable(const T& data, std::string& name, Level& lvl, const Factory* fact) {
1290  lvl.AddKeepFlag(name, fact, MueLu::UserData);
1291  lvl.Set<T>(name, data, fact);
1292 }
1293 
1294 template <typename T>
1295 const T& getLevelVariable(std::string& name, Level& lvl) {
1296  try {
1297  return lvl.Get<T>(name);
1298  } catch (std::exception& e) {
1299  throw std::runtime_error("Requested custom variable " + name + " is not in the level.");
1300  }
1301 }
1302 
1303 // Functions used to put data through matlab factories - first arg is "this" pointer of matlab factory
1304 template <typename Scalar, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
1305 std::vector<Teuchos::RCP<MuemexArg> > processNeeds(const Factory* factory, std::string& needsParam, Level& lvl) {
1306  using namespace std;
1307  using namespace Teuchos;
1311  typedef RCP<AmalgamationInfo<LocalOrdinal, GlobalOrdinal, Node> > AmalgamationInfo_t;
1312  typedef RCP<MGraph> Graph_t;
1313  vector<string> needsList = tokenizeList(needsParam);
1314  vector<RCP<MuemexArg> > args;
1315  for (size_t i = 0; i < needsList.size(); i++) {
1316  if (needsList[i] == "A" || needsList[i] == "P" || needsList[i] == "R" || needsList[i] == "Ptent") {
1317  Matrix_t mydata = lvl.Get<Matrix_t>(needsList[i], factory->GetFactory(needsList[i]).get());
1318  args.push_back(rcp(new MuemexData<Matrix_t>(mydata)));
1319  } else if (needsList[i] == "Nullspace" || needsList[i] == "Coordinates") {
1320  MultiVector_t mydata = lvl.Get<MultiVector_t>(needsList[i], factory->GetFactory(needsList[i]).get());
1321  args.push_back(rcp(new MuemexData<MultiVector_t>(mydata)));
1322  } else if (needsList[i] == "Aggregates") {
1323  Aggregates_t mydata = lvl.Get<Aggregates_t>(needsList[i], factory->GetFactory(needsList[i]).get());
1324  args.push_back(rcp(new MuemexData<Aggregates_t>(mydata)));
1325  } else if (needsList[i] == "UnAmalgamationInfo") {
1326  AmalgamationInfo_t mydata = lvl.Get<AmalgamationInfo_t>(needsList[i], factory->GetFactory(needsList[i]).get());
1327  args.push_back(rcp(new MuemexData<AmalgamationInfo_t>(mydata)));
1328  } else if (needsList[i] == "Level") {
1329  int levelNum = lvl.GetLevelID();
1330  args.push_back(rcp(new MuemexData<int>(levelNum)));
1331  } else if (needsList[i] == "Graph") {
1332  Graph_t mydata = lvl.Get<Graph_t>(needsList[i], factory->GetFactory(needsList[i]).get());
1333  args.push_back(rcp(new MuemexData<Graph_t>(mydata)));
1334  } else {
1335  vector<string> words;
1336  string badNameMsg = "Custom Muemex variables in \"Needs\" list require a type and a name, e.g. \"double myVal\". \n Leading and trailing spaces are OK. \n Don't know how to handle \"" + needsList[i] + "\".\n";
1337  // compare type without case sensitivity
1338  char* buf = (char*)malloc(needsList[i].size() + 1);
1339  strcpy(buf, needsList[i].c_str());
1340  for (char* iter = buf; *iter != ' '; iter++) {
1341  if (*iter == 0) {
1342  free(buf);
1343  throw runtime_error(badNameMsg);
1344  }
1345  *iter = (char)tolower(*iter);
1346  }
1347  const char* wordDelim = " ";
1348  char* mark = strtok(buf, wordDelim);
1349  while (mark != NULL) {
1350  string wordStr(mark);
1351  words.push_back(wordStr);
1352  mark = strtok(NULL, wordDelim);
1353  }
1354  if (words.size() != 2) {
1355  free(buf);
1356  throw runtime_error(badNameMsg);
1357  }
1358  char* typeStr = (char*)words[0].c_str();
1359  if (strstr(typeStr, "ordinalvector")) {
1361  LOVector_t mydata = getLevelVariable<LOVector_t>(needsList[i], lvl);
1362  args.push_back(rcp(new MuemexData<LOVector_t>(mydata)));
1363  } else if (strstr(typeStr, "map")) {
1365  Map_t mydata = getLevelVariable<Map_t>(needsList[i], lvl);
1366  args.push_back(rcp(new MuemexData<Map_t>(mydata)));
1367  } else if (strstr(typeStr, "scalar")) {
1368  Scalar mydata = getLevelVariable<Scalar>(needsList[i], lvl);
1369  args.push_back(rcp(new MuemexData<Scalar>(mydata)));
1370  } else if (strstr(typeStr, "double")) {
1371  double mydata = getLevelVariable<double>(needsList[i], lvl);
1372  args.push_back(rcp(new MuemexData<double>(mydata)));
1373  } else if (strstr(typeStr, "complex")) {
1374  complex_t mydata = getLevelVariable<complex_t>(needsList[i], lvl);
1375  args.push_back(rcp(new MuemexData<complex_t>(mydata)));
1376  } else if (strstr(typeStr, "matrix")) {
1377  Matrix_t mydata = getLevelVariable<Matrix_t>(needsList[i], lvl);
1378  args.push_back(rcp(new MuemexData<Matrix_t>(mydata)));
1379  } else if (strstr(typeStr, "multivector")) {
1380  MultiVector_t mydata = getLevelVariable<MultiVector_t>(needsList[i], lvl);
1381  args.push_back(rcp(new MuemexData<MultiVector_t>(mydata)));
1382  } else if (strstr(typeStr, "int")) {
1383  int mydata = getLevelVariable<int>(needsList[i], lvl);
1384  args.push_back(rcp(new MuemexData<int>(mydata)));
1385  } else if (strstr(typeStr, "string")) {
1386  string mydata = getLevelVariable<string>(needsList[i], lvl);
1387  args.push_back(rcp(new MuemexData<string>(mydata)));
1388  } else {
1389  free(buf);
1390  throw std::runtime_error(words[0] + " is not a known variable type.");
1391  }
1392  free(buf);
1393  }
1394  }
1395  return args;
1396 }
1397 
1398 template <typename Scalar, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
1399 void processProvides(std::vector<Teuchos::RCP<MuemexArg> >& mexOutput, const Factory* factory, std::string& providesParam, Level& lvl) {
1400  using namespace std;
1401  using namespace Teuchos;
1405  typedef RCP<AmalgamationInfo<LocalOrdinal, GlobalOrdinal, Node> > AmalgamationInfo_t;
1406  typedef RCP<MGraph> Graph_t;
1407  vector<string> provides = tokenizeList(providesParam);
1408  for (size_t i = 0; i < size_t(provides.size()); i++) {
1409  if (provides[i] == "A" || provides[i] == "P" || provides[i] == "R" || provides[i] == "Ptent") {
1410  RCP<MuemexData<Matrix_t> > mydata = Teuchos::rcp_static_cast<MuemexData<Matrix_t> >(mexOutput[i]);
1411  lvl.Set(provides[i], mydata->getData(), factory);
1412  } else if (provides[i] == "Nullspace" || provides[i] == "Coordinates") {
1413  RCP<MuemexData<MultiVector_t> > mydata = Teuchos::rcp_static_cast<MuemexData<MultiVector_t> >(mexOutput[i]);
1414  lvl.Set(provides[i], mydata->getData(), factory);
1415  } else if (provides[i] == "Aggregates") {
1416  RCP<MuemexData<Aggregates_t> > mydata = Teuchos::rcp_static_cast<MuemexData<Aggregates_t> >(mexOutput[i]);
1417  lvl.Set(provides[i], mydata->getData(), factory);
1418  } else if (provides[i] == "UnAmalgamationInfo") {
1419  RCP<MuemexData<AmalgamationInfo_t> > mydata = Teuchos::rcp_static_cast<MuemexData<AmalgamationInfo_t> >(mexOutput[i]);
1420  lvl.Set(provides[i], mydata->getData(), factory);
1421  } else if (provides[i] == "Graph") {
1422  RCP<MuemexData<Graph_t> > mydata = Teuchos::rcp_static_cast<MuemexData<Graph_t> >(mexOutput[i]);
1423  lvl.Set(provides[i], mydata->getData(), factory);
1424  } else {
1425  vector<string> words;
1426  string badNameMsg = "Custom Muemex variables in \"Provides\" list require a type and a name, e.g. \"double myVal\". \n Leading and trailing spaces are OK. \n Don't know how to handle \"" + provides[i] + "\".\n";
1427  // compare type without case sensitivity
1428  char* buf = (char*)malloc(provides[i].size() + 1);
1429  strcpy(buf, provides[i].c_str());
1430  for (char* iter = buf; *iter != ' '; iter++) {
1431  if (*iter == 0) {
1432  free(buf);
1433  throw runtime_error(badNameMsg);
1434  }
1435  *iter = (char)tolower(*iter);
1436  }
1437  const char* wordDelim = " ";
1438  char* mark = strtok(buf, wordDelim);
1439  while (mark != NULL) {
1440  string wordStr(mark);
1441  words.push_back(wordStr);
1442  mark = strtok(NULL, wordDelim);
1443  }
1444  if (words.size() != 2) {
1445  free(buf);
1446  throw runtime_error(badNameMsg);
1447  }
1448  const char* typeStr = words[0].c_str();
1449  if (strstr(typeStr, "ordinalvector")) {
1451  RCP<MuemexData<LOVector_t> > mydata = Teuchos::rcp_static_cast<MuemexData<LOVector_t> >(mexOutput[i]);
1452  addLevelVariable<LOVector_t>(mydata->getData(), words[1], lvl, factory);
1453  } else if (strstr(typeStr, "map")) {
1455  RCP<MuemexData<Map_t> > mydata = Teuchos::rcp_static_cast<MuemexData<Map_t> >(mexOutput[i]);
1456  addLevelVariable<Map_t>(mydata->getData(), words[1], lvl, factory);
1457  } else if (strstr(typeStr, "scalar")) {
1458  RCP<MuemexData<Scalar> > mydata = Teuchos::rcp_static_cast<MuemexData<Scalar> >(mexOutput[i]);
1459  addLevelVariable<Scalar>(mydata->getData(), words[1], lvl, factory);
1460  } else if (strstr(typeStr, "double")) {
1461  RCP<MuemexData<double> > mydata = Teuchos::rcp_static_cast<MuemexData<double> >(mexOutput[i]);
1462  addLevelVariable<double>(mydata->getData(), words[1], lvl, factory);
1463  } else if (strstr(typeStr, "complex")) {
1464  RCP<MuemexData<complex_t> > mydata = Teuchos::rcp_static_cast<MuemexData<complex_t> >(mexOutput[i]);
1465  addLevelVariable<complex_t>(mydata->getData(), words[1], lvl, factory);
1466  } else if (strstr(typeStr, "matrix")) {
1467  RCP<MuemexData<Matrix_t> > mydata = Teuchos::rcp_static_cast<MuemexData<Matrix_t> >(mexOutput[i]);
1468  addLevelVariable<Matrix_t>(mydata->getData(), words[1], lvl, factory);
1469  } else if (strstr(typeStr, "multivector")) {
1470  RCP<MuemexData<MultiVector_t> > mydata = Teuchos::rcp_static_cast<MuemexData<MultiVector_t> >(mexOutput[i]);
1471  addLevelVariable<MultiVector_t>(mydata->getData(), words[1], lvl, factory);
1472  } else if (strstr(typeStr, "int")) {
1473  RCP<MuemexData<int> > mydata = Teuchos::rcp_static_cast<MuemexData<int> >(mexOutput[i]);
1474  addLevelVariable<int>(mydata->getData(), words[1], lvl, factory);
1475  } else if (strstr(typeStr, "bool")) {
1476  RCP<MuemexData<bool> > mydata = Teuchos::rcp_static_cast<MuemexData<bool> >(mexOutput[i]);
1477  addLevelVariable<bool>(mydata->getData(), words[1], lvl, factory);
1478  } else if (strstr(typeStr, "string")) {
1479  RCP<MuemexData<string> > mydata = Teuchos::rcp_static_cast<MuemexData<string> >(mexOutput[i]);
1480  addLevelVariable<string>(mydata->getData(), words[1], lvl, factory);
1481  } else {
1482  free(buf);
1483  throw std::runtime_error(words[0] + " is not a known variable type.");
1484  }
1485  free(buf);
1486  }
1487  }
1488 }
1489 
1490 // Throwable Stubs for long long
1491 
1492 template <>
1493 std::vector<Teuchos::RCP<MuemexArg> > processNeeds<double, mm_LocalOrd, long long, mm_node_t>(const Factory* factory, std::string& needsParam, Level& lvl) {
1494  throw std::runtime_error("Muemex does not support long long for global indices");
1495 }
1496 
1497 template <>
1498 std::vector<Teuchos::RCP<MuemexArg> > processNeeds<complex_t, mm_LocalOrd, long long, mm_node_t>(const Factory* factory, std::string& needsParam, Level& lvl) {
1499  throw std::runtime_error("Muemex does not support long long for global indices");
1500 }
1501 
1502 template <>
1503 void processProvides<double, mm_LocalOrd, long long, mm_node_t>(std::vector<Teuchos::RCP<MuemexArg> >& mexOutput, const Factory* factory, std::string& providesParam, Level& lvl) {
1504  throw std::runtime_error("Muemex does not support long long for global indices");
1505 }
1506 
1507 template <>
1508 void processProvides<complex_t, mm_LocalOrd, long long, mm_node_t>(std::vector<Teuchos::RCP<MuemexArg> >& mexOutput, const Factory* factory, std::string& providesParam, Level& lvl) {
1509  throw std::runtime_error("Muemex does not support long long for global indices");
1510 }
1511 
1512 } // namespace MueLu
1513 #endif // HAVE_MUELU_MATLAB error handler
1514 #endif // MUELU_MATLABUTILS_DEF_HPP guard
std::vector< Teuchos::RCP< MuemexArg > > processNeeds< double, mm_LocalOrd, long long, mm_node_t >(const Factory *factory, std::string &needsParam, Level &lvl)
template mxArray * saveDataToMatlab(bool &data)
std::vector< std::string > tokenizeList(const std::string &params)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
mxArray * createMatlabSparse< complex_t >(int numRows, int numCols, int nnz)
bool rewrap_ints
bool is_null() const
MuemexType getMuemexType< string >()
Tpetra::Map::local_ordinal_type mm_LocalOrd
Tpetra::Map::global_ordinal_type mm_GlobalOrd
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
RCP< Xpetra::MultiVector< SC, LO, GO, NO > > TpetraMultiVector_To_XpetraMultiVector(const Teuchos::RCP< Tpetra::MultiVector< SC, LO, GO, NO >> &Vtpetra)
size_type size() const
User data are always kept. This flag is set automatically when Level::Set(&quot;data&quot;, data) is used...
std::string tolower(const std::string &str)
void fillMatlabArray< double >(double *array, const mxArray *mxa, int n)
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
template string loadDataFromMatlab< string >(const mxArray *mxa)
MuemexType getMuemexType(const T &data)
size_type size() const
std::vector< Teuchos::RCP< MuemexArg > > processNeeds(const Factory *factory, std::string &needsParam, Level &lvl)
void addLevelVariable(const T &data, std::string &name, Level &lvl, const FactoryBase *fact=NoFactory::get())
int FillComplete(bool OptimizeDataStorage=true)
size_t global_size_t
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void fillMatlabArray< complex_t >(complex_t *array, const mxArray *mxa, int n)
mxArray * createMatlabSparse< double >(int numRows, int numCols, int nnz)
MueLu::DefaultScalar Scalar
int * mwIndex_to_int(int N, mwIndex *mwi_array)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
void processProvides< complex_t, mm_LocalOrd, long long, mm_node_t >(std::vector< Teuchos::RCP< MuemexArg > > &mexOutput, const Factory *factory, std::string &providesParam, Level &lvl)
template complex_t loadDataFromMatlab< complex_t >(const mxArray *mxa)
template int loadDataFromMatlab< int >(const mxArray *mxa)
RCP< Xpetra::Matrix< SC, LO, GO, NO > > TpetraCrs_To_XpetraMatrix(const Teuchos::RCP< Tpetra::CrsMatrix< SC, LO, GO, NO >> &Atpetra)
template bool loadDataFromMatlab< bool >(const mxArray *mxa)
const T & getLevelVariable(std::string &name, Level &lvl)
MuemexType getMuemexType< int >()
mxArray * createMatlabMultiVector< complex_t >(int numRows, int numCols)
std::vector< Teuchos::RCP< MuemexArg > > processNeeds< complex_t, mm_LocalOrd, long long, mm_node_t >(const Factory *factory, std::string &needsParam, Level &lvl)
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
T * getRawPtr() const
MuemexType getMuemexType< bool >()
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
void processProvides< double, mm_LocalOrd, long long, mm_node_t >(std::vector< Teuchos::RCP< MuemexArg > > &mexOutput, const Factory *factory, std::string &providesParam, Level &lvl)
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
TransListIter iter
Teuchos::RCP< const Teuchos::Comm< int > > getDefaultComm()
std::complex< double > complex_t
mxArray * createMatlabMultiVector< double >(int numRows, int numCols)
template double loadDataFromMatlab< double >(const mxArray *mxa)
MueLu::Aggregates< mm_LocalOrd, mm_GlobalOrd, mm_node_t > MAggregates
TypeTo as(const TypeFrom &t)
MuemexType getMuemexType< double >()
Tpetra::Map muemex_map_type
virtual const RCP< const FactoryBase > GetFactory(const std::string &varName) const =0
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:76
MuemexType getMuemexType< complex_t >()
void processProvides(std::vector< Teuchos::RCP< MuemexArg > > &mexOutput, const Factory *factory, std::string &providesParam, Level &lvl)
int mwIndex
bool is_null() const