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