47#ifndef MUELU_MATLABUTILS_DEF_HPP
48#define MUELU_MATLABUTILS_DEF_HPP
52#if !defined(HAVE_MUELU_MATLAB) || !defined(HAVE_MUELU_EPETRA)
53#error "Muemex types require MATLAB, Epetra and Tpetra."
128#ifdef HAVE_MUELU_INTREPID2
153 mxClassID probIDtype = mxGetClassID(mxa);
155 if(probIDtype == mxINT32_CLASS)
157 rv = *((
int*) mxGetData(mxa));
159 else if(probIDtype == mxLOGICAL_CLASS)
161 rv = (int) *((
bool*) mxGetData(mxa));
163 else if(probIDtype == mxDOUBLE_CLASS)
165 rv = (int) *((
double*) mxGetData(mxa));
167 else if(probIDtype == mxUINT32_CLASS)
169 rv = (int) *((
unsigned int*) mxGetData(mxa));
174 throw std::runtime_error(
"Error: Unrecognized numerical type.");
182 return *((
bool*) mxGetData(mxa));
188 return *((
double*) mxGetPr(mxa));
194 double realpart = real<double>(*((
double*) mxGetPr(mxa)));
195 double imagpart = imag<double>(*((
double*) mxGetPi(mxa)));
203 if (mxGetClassID(mxa) != mxCHAR_CLASS)
205 throw runtime_error(
"Can't construct string from anything but a char array.");
207 rv = string(mxArrayToString(mxa));
214 RCP<const Teuchos::Comm<int> > comm = rcp(
new Teuchos::SerialComm<int>());
215 int nr = mxGetM(mxa);
216 int nc = mxGetN(mxa);
218 throw std::runtime_error(
"A Xpetra::Map representation from MATLAB must be a single row vector.");
219 double* pr = mxGetPr(mxa);
222 std::vector<mm_GlobalOrd> localGIDs(numGlobalIndices);
223 for(
int i = 0; i < int(numGlobalIndices); i++) {
224 localGIDs[i] = Teuchos::as<mm_GlobalOrd>(pr[i]);
227 const Teuchos::ArrayView<const mm_GlobalOrd> localGIDs_view(&localGIDs[0],localGIDs.size());
228 RCP<Xpetra_map> map =
229 Xpetra::MapFactory<mm_LocalOrd, mm_GlobalOrd, mm_node_t>::Build(
231 Teuchos::OrdinalTraits<mm_GlobalOrd>::invalid(),
236 throw runtime_error(
"Failed to create Xpetra::Map.");
243 RCP<const Teuchos::Comm<int> > comm = rcp(
new Teuchos::SerialComm<int>());
244 if(mxGetN(mxa) != 1 && mxGetM(mxa) != 1)
245 throw std::runtime_error(
"An OrdinalVector from MATLAB must be a single row or column vector.");
246 mm_GlobalOrd numGlobalIndices = mxGetM(mxa) * mxGetN(mxa);
247 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);
248 if(mxGetClassID(mxa) != mxINT32_CLASS)
249 throw std::runtime_error(
"Can only construct LOVector with int32 data.");
250 int* array = (
int*) mxGetData(mxa);
252 throw runtime_error(
"Failed to create map for Xpetra ordinal vector.");
253 RCP<Xpetra_ordinal_vector> loVec = Xpetra::VectorFactory<mm_LocalOrd, mm_LocalOrd, mm_GlobalOrd, mm_node_t>::Build(map,
false);
255 throw runtime_error(
"Failed to create ordinal vector with Xpetra::VectorFactory.");
256 for(
int i = 0; i < int(numGlobalIndices); i++)
258 loVec->replaceGlobalValue(i, 0, array[i]);
266 RCP<Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>> mv;
269 int nr = mxGetM(mxa);
270 int nc = mxGetN(mxa);
271 double* pr = mxGetPr(mxa);
272 RCP<const Teuchos::Comm<int>> comm = Tpetra::getDefaultComm();
276 Teuchos::ArrayView<const double> arrView(pr, nr * nc);
277 mv = rcp(
new Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(map, arrView,
size_t(nr),
size_t(nc)));
279 catch(std::exception& e)
281 mexPrintf(
"Error constructing Tpetra MultiVector.\n");
282 std::cout << e.what() << std::endl;
290 RCP<Tpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>> mv;
293 int nr = mxGetM(mxa);
294 int nc = mxGetN(mxa);
295 double* pr = mxGetPr(mxa);
296 double* pi = mxGetPi(mxa);
297 RCP<const Teuchos::Comm<int>> comm = Tpetra::getDefaultComm();
302 for(
int n = 0; n < nc; n++)
304 for(
int m = 0; m < nr; m++)
306 myArr[n * nr + m] =
complex_t(pr[n * nr + m], pi[n * nr + m]);
309 Teuchos::ArrayView<complex_t> arrView(myArr, nr * nc);
310 mv = rcp(
new Tpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(map, arrView, nr, nc));
312 catch(std::exception& e)
314 mexPrintf(
"Error constructing Tpetra MultiVector.\n");
315 std::cout << e.what() << std::endl;
323 bool success =
false;
324 RCP<Tpetra_CrsMatrix_double> A;
331 RCP<const Teuchos::Comm<int>> comm = rcp(
new Teuchos::SerialComm<int>());
333 const size_t numGlobalIndices = mxGetM(mxa);
334 RCP<const muemex_map_type> rowMap = rcp(
new muemex_map_type(numGlobalIndices, 0, comm));
335 RCP<const muemex_map_type> domainMap = rcp(
new muemex_map_type(mxGetN(mxa), 0, comm));
336 double* valueArray = mxGetPr(mxa);
337 int nc = mxGetN(mxa);
346 rowind = (
int*) mxGetIr(mxa);
347 colptr = (
int*) mxGetJc(mxa);
350 Teuchos::Array<size_t> rowCounts(numGlobalIndices);
351 for(
int i = 0; i < nc; i++)
353 for(
int j = colptr[i]; j < colptr[i + 1]; j++)
355 rowCounts[rowind[j]]++;
358 A = rcp(
new Tpetra::CrsMatrix<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(rowMap, rowCounts()));
359 for(
int i = 0; i < nc; i++)
361 for(
int j = colptr[i]; j < colptr[i + 1]; j++)
364 Teuchos::ArrayView<mm_GlobalOrd> cols = Teuchos::ArrayView<mm_GlobalOrd>(&i, 1);
366 Teuchos::ArrayView<double> vals = Teuchos::ArrayView<double>(&valueArray[j], 1);
367 A->insertGlobalValues(rowind[j], cols, vals);
370 A->fillComplete(domainMap, rowMap);
373 delete[] rowind; rowind = NULL;
374 delete[] colptr; colptr = NULL;
378 catch(std::exception& e)
382 if(rowind!=NULL)
delete[] rowind;
383 if(colptr!=NULL)
delete[] colptr;
387 mexPrintf(
"Error while constructing Tpetra matrix:\n");
388 std::cout << e.what() << std::endl;
391 mexErrMsgTxt(
"An error occurred while setting up a Tpetra matrix.\n");
398 RCP<Tpetra_CrsMatrix_complex> A;
402 RCP<const Teuchos::Comm<int>> comm = Tpetra::getDefaultComm();
403 const Tpetra::global_size_t numGlobalIndices = mxGetM(mxa);
405 RCP<const muemex_map_type> rowMap = rcp(
new muemex_map_type(numGlobalIndices, indexBase, comm));
406 RCP<const muemex_map_type> domainMap = rcp(
new muemex_map_type(mxGetN(mxa), indexBase, comm));
407 double* realArray = mxGetPr(mxa);
408 double* imagArray = mxGetPi(mxa);
411 int nc = mxGetN(mxa);
420 rowind = (
int*) mxGetIr(mxa);
421 colptr = (
int*) mxGetJc(mxa);
424 Teuchos::Array<size_t> rowCounts(numGlobalIndices);
425 for(
int i = 0; i < nc; i++)
427 for(
int j = colptr[i]; j < colptr[i + 1]; j++)
429 rowCounts[rowind[j]]++;
432 A = rcp(
new Tpetra::CrsMatrix<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>(rowMap, rowCounts()));
433 for(
int i = 0; i < nc; i++)
435 for(
int j = colptr[i]; j < colptr[i + 1]; j++)
439 complex_t value = std::complex<double>(realArray[j], imagArray[j]);
440 Teuchos::ArrayView<mm_GlobalOrd> cols = Teuchos::ArrayView<mm_GlobalOrd>(&i, 1);
441 Teuchos::ArrayView<complex_t> vals = Teuchos::ArrayView<complex_t>(&value, 1);
442 A->insertGlobalValues(rowind[j], cols, vals);
445 A->fillComplete(domainMap, rowMap);
452 catch(std::exception& e)
454 mexPrintf(
"Error while constructing tpetra matrix:\n");
455 std::cout << e.what() << std::endl;
491 RCP<Epetra_CrsMatrix> matrix;
496 double* vals = mxGetPr(mxa);
497 int nr = mxGetM(mxa);
498 int nc = mxGetN(mxa);
506 rowind = (
int*) mxGetIr(mxa);
507 colptr = (
int*) mxGetJc(mxa);
509 Epetra_SerialComm Comm;
510 Epetra_Map RangeMap(nr, 0, Comm);
511 Epetra_Map DomainMap(nc, 0, Comm);
512 matrix = rcp(
new Epetra_CrsMatrix(Epetra_DataAccess::Copy, RangeMap, DomainMap, 0));
514 for(
int i = 0; i < nc; i++)
516 for(
int j = colptr[i]; j < colptr[i + 1]; j++)
519 matrix->InsertGlobalValues(rowind[j], 1, &vals[j], &i);
522 matrix->FillComplete(DomainMap, RangeMap);
529 catch(std::exception& e)
531 mexPrintf(
"An error occurred while setting up an Epetra matrix:\n");
532 std::cout << e.what() << std::endl;
540 int nr = mxGetM(mxa);
541 int nc = mxGetN(mxa);
542 Epetra_SerialComm Comm;
543 Epetra_BlockMap map(nr * nc, 1, 0, Comm);
544 return rcp(
new Epetra_MultiVector(Epetra_DataAccess::Copy, map, mxGetPr(mxa), nr, nc));
550 if(mxGetNumberOfElements(mxa) != 1)
551 throw runtime_error(
"Aggregates must be individual structs in MATLAB.");
553 throw runtime_error(
"Trying to pull aggregates from non-struct MATLAB object.");
556 const int correctNumFields = 5;
557 if(mxGetNumberOfFields(mxa) != correctNumFields)
558 throw runtime_error(
"Aggregates structure has wrong number of fields.");
560 int nVert = *(
int*) mxGetData(mxGetField(mxa, 0,
"nVertices"));
561 int nAgg = *(
int*) mxGetData(mxGetField(mxa, 0,
"nAggregates"));
564 RCP<const Teuchos::Comm<int>> comm = Teuchos::DefaultComm<int>::getComm();
565 int myRank = comm->getRank();
566 Xpetra::UnderlyingLib lib = Xpetra::UseTpetra;
567 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);
569 agg->SetNumAggregates(nAgg);
572 ArrayRCP<mm_LocalOrd> vertex2AggId = agg->GetVertex2AggId()->getDataNonConst(0);
573 ArrayRCP<mm_LocalOrd> procWinner = agg->GetProcWinner()->getDataNonConst(0);
577 mxArray* vertToAggID_in = mxGetField(mxa, 0,
"vertexToAggID");
578 int* vertToAggID_inArray = (
int*) mxGetData(vertToAggID_in);
579 mxArray* rootNodes_in = mxGetField(mxa, 0,
"rootNodes");
580 int* rootNodes_inArray = (
int*) mxGetData(rootNodes_in);
581 for(
int i = 0; i < nVert; i++)
583 vertex2AggId[i] = vertToAggID_inArray[i];
584 procWinner[i] = myRank;
585 agg->SetIsRoot(i,
false);
587 for(
int i = 0; i < nAgg; i++)
589 agg->SetIsRoot(rootNodes_inArray[i],
true);
592 agg->ComputeAggregateSizes(
true);
593 agg->AggregatesCrossProcessors(
false);
601 throw runtime_error(
"AmalgamationInfo not supported in Muemex yet.");
609 mxArray* edges = mxGetField(mxa, 0,
"edges");
610 mxArray* boundaryNodes = mxGetField(mxa, 0,
"boundaryNodes");
612 throw runtime_error(
"Graph structure in MATLAB must have a field called 'edges' (logical sparse matrix)");
613 if(boundaryNodes == NULL)
614 throw runtime_error(
"Graph structure in MATLAB must have a field called 'boundaryNodes' (int32 array containing list of boundary nodes)");
615 int* boundaryList = (
int*) mxGetData(boundaryNodes);
616 if(!mxIsSparse(edges) || mxGetClassID(edges) != mxLOGICAL_CLASS)
617 throw runtime_error(
"Graph edges must be stored as a logical sparse matrix.");
619 mwIndex* matlabColPtrs = mxGetJc(edges);
620 mwIndex* matlabRowIndices = mxGetIr(edges);
626 Teuchos::Array<int> entriesPerRow(nRows);
627 int nnz = matlabColPtrs[mxGetN(edges)];
628 for(
int i = 0; i < nnz; i++)
629 entriesPerRow[matlabRowIndices[i]]++;
632 Teuchos::Array<int> rows(nRows+1);
634 for(
int i = 0; i < nRows; i++)
635 rows[i+1] = rows[i] + entriesPerRow[i];
636 Teuchos::Array<int> cols(nnz);
637 Teuchos::Array<int> insertionsPerRow(nRows,0);
638 int ncols = mxGetN(edges);
639 for (
int colNum=0; colNum<ncols; ++colNum) {
640 int ci = matlabColPtrs[colNum];
641 for (
int j=ci; j<Teuchos::as<int>(matlabColPtrs[colNum+1]); ++j) {
642 int rowNum = matlabRowIndices[j];
643 cols[ rows[rowNum] + insertionsPerRow[rowNum] ] = colNum;
644 insertionsPerRow[rowNum]++;
649 for(
int i = 0; i < nRows; i++) {
650 if(maxNzPerRow < entriesPerRow[i])
651 maxNzPerRow = entriesPerRow[i];
654 RCP<const Teuchos::Comm<mm_GlobalOrd>> comm = rcp(
new Teuchos::SerialComm<mm_GlobalOrd>());
655 typedef Xpetra::TpetraMap<mm_LocalOrd, mm_GlobalOrd, mm_node_t> MMap;
656 RCP<MMap> map = rcp(
new MMap(nRows, 0, comm));
657 typedef Xpetra::TpetraCrsGraph<mm_LocalOrd, mm_GlobalOrd, mm_node_t> TpetraGraph;
658 RCP<TpetraGraph> tgraph = rcp(
new TpetraGraph(map, (
size_t) maxNzPerRow));
660 for(
int i = 0; i < nRows; ++i) {
661 tgraph->insertGlobalIndices((
mm_GlobalOrd) i, cols(rows[i],entriesPerRow[i]));
663 tgraph->fillComplete(map, map);
664 RCP<MGraph> mgraph = rcp(
new MueLu::Graph<mm_LocalOrd, mm_GlobalOrd, mm_node_t>(tgraph));
666 int numBoundaryNodes = mxGetNumberOfElements(boundaryNodes);
667 bool* boundaryFlags =
new bool[nRows];
668 for(
int i = 0; i < nRows; i++)
670 boundaryFlags[i] =
false;
672 for(
int i = 0; i < numBoundaryNodes; i++)
674 boundaryFlags[boundaryList[i]] =
true;
676 ArrayRCP<bool> boundaryNodesInput(boundaryFlags, 0, nRows,
true);
677 mgraph->SetBoundaryNodeMap(boundaryNodesInput);
682#ifdef HAVE_MUELU_INTREPID2
686 if(mxGetClassID(mxa) != mxINT32_CLASS)
687 throw runtime_error(
"FieldContainer must have integer storage entries");
689 int *data = (
int *) mxGetData(mxa);
690 int nr = mxGetM(mxa);
691 int nc = mxGetN(mxa);
693 RCP<FieldContainer_ordinal> fc = rcp(
new FieldContainer_ordinal(
"FC from Matlab",nr,nc));
694 for(
int col = 0; col < nc; col++)
696 for(
int row = 0; row < nr; row++)
698 (*fc)(row,col) = data[col * nr + row];
712 mwSize dims[] = {1, 1};
713 mxArray* mxa = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
714 *((
int*) mxGetData(mxa)) = data;
721 mwSize dims[] = {1, 1};
722 mxArray* mxa = mxCreateLogicalArray(2, dims);
723 *((
bool*) mxGetData(mxa)) = data;
730 return mxCreateDoubleScalar(data);
736 mwSize dims[] = {1, 1};
737 mxArray* mxa = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxCOMPLEX);
738 *((
double*) mxGetPr(mxa)) = real<double>(data);
739 *((
double*) mxGetPi(mxa)) = imag<double>(data);
746 return mxCreateString(data.c_str());
753 int nc = data->getGlobalNumElements();
756 double* array = (
double*) malloc(
sizeof(
double) * nr * nc);
757 for(
int col = 0; col < nc; col++)
760 array[col] = Teuchos::as<double>(gid);
770 mwSize len = data->getGlobalLength();
772 mwSize dimensions[] = {len, 1};
773 mxArray* rv = mxCreateNumericArray(2, dimensions, mxINT32_CLASS, mxREAL);
774 int* dataPtr = (
int*) mxGetData(rv);
775 ArrayRCP<const mm_LocalOrd> arr = data->getData(0);
776 for(
int i = 0; i < int(data->getGlobalLength()); i++)
784mxArray*
saveDataToMatlab(RCP<Tpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>>& data)
791mxArray*
saveDataToMatlab(RCP<Tpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>>& data)
816 Teuchos::rcp_const_cast<Xpetra_CrsGraph>(data->getCrsGraph())->computeGlobalConstants();
818 int nr = data->getGlobalNumRows();
819 int nc = data->getGlobalNumCols();
820 int nnz = data->getGlobalNumEntries();
823 RCP<Teuchos::FancyOStream> fancyStream = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
824 mat->describe(*fancyStream, Teuchos::VERB_EXTREME);
829 for(
int i = 0; i < nc + 1; i++)
834 size_t maxEntriesPerRow = data->getGlobalMaxNumRowEntries();
835 if(maxEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid() || maxEntriesPerRow == 0) maxEntriesPerRow = data->getLocalMaxNumRowEntries();
837 int* rowProgress =
new int[nc];
841 if(data->isLocallyIndexed())
844 Teuchos::ArrayView<Scalar> rowVals(rowValArray, maxEntriesPerRow);
846 Teuchos::ArrayView<mm_LocalOrd> rowIndices(rowIndicesArray, maxEntriesPerRow);
849 data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
850 for(
mm_LocalOrd entry = 0; entry < int(numEntries); entry++)
852 jc[rowIndices[entry] + 1]++;
857 int entriesAccum = 0;
858 for(
int n = 0; n <= nc; n++)
860 int temp = entriesAccum;
861 entriesAccum += jc[n];
865 for(
int i = 0; i < nc; i++)
872 data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
877 sparseVals[jc[col] + rowProgress[col]] = rowVals[i];
878 ir[jc[col] + rowProgress[col]] = m;
882 delete[] rowIndicesArray;
886 Teuchos::ArrayView<const mm_GlobalOrd> rowIndices;
887 Teuchos::ArrayView<const Scalar> rowVals;
890 data->getGlobalRowView(m, rowIndices, rowVals);
893 jc[rowIndices[n] + 1]++;
899 for(
int i = 0; i < nc; i++)
903 int entriesAccum = 0;
904 for(
int n = 0; n <= nc; n++)
906 int temp = entriesAccum;
907 entriesAccum += jc[n];
913 data->getGlobalRowView(m, rowIndices, rowVals);
917 sparseVals[jc[col] + rowProgress[col]] = rowVals[i];
918 ir[jc[col] + rowProgress[col]] = m;
926 delete[] rowProgress;
936 Teuchos::rcp_const_cast<Xpetra_CrsGraph>(data->getCrsGraph())->computeGlobalConstants();
938 int nr = data->getGlobalNumRows();
939 int nc = data->getGlobalNumCols();
940 int nnz = data->getGlobalNumEntries();
942 RCP<Teuchos::FancyOStream> fancyStream = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
943 mat->describe(*fancyStream, Teuchos::VERB_EXTREME);
948 for(
int i = 0; i < nc + 1; i++)
952 size_t maxEntriesPerRow = data->getGlobalMaxNumRowEntries();
953 int* rowProgress =
new int[nc];
957 if(data->isLocallyIndexed())
960 Teuchos::ArrayView<Scalar> rowVals(rowValArray, maxEntriesPerRow);
962 Teuchos::ArrayView<mm_LocalOrd> rowIndices(rowIndicesArray, maxEntriesPerRow);
965 data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
966 for(
mm_LocalOrd entry = 0; entry < int(numEntries); entry++)
968 jc[rowIndices[entry] + 1]++;
972 int entriesAccum = 0;
973 for(
int n = 0; n <= nc; n++)
975 int temp = entriesAccum;
976 entriesAccum += jc[n];
980 for(
int i = 0; i < nc; i++)
987 data->getLocalRowCopy(m, rowIndices, rowVals, numEntries);
992 sparseVals[jc[col] + rowProgress[col]] = rowVals[i];
993 ir[jc[col] + rowProgress[col]] = m;
997 delete[] rowIndicesArray;
1001 Teuchos::ArrayView<const mm_GlobalOrd> rowIndices;
1002 Teuchos::ArrayView<const Scalar> rowVals;
1005 data->getGlobalRowView(m, rowIndices, rowVals);
1008 jc[rowIndices[n] + 1]++;
1014 for(
int i = 0; i < nc; i++)
1018 int entriesAccum = 0;
1019 for(
int n = 0; n <= nc; n++)
1021 int temp = entriesAccum;
1022 entriesAccum += jc[n];
1028 data->getGlobalRowView(m, rowIndices, rowVals);
1029 for(
mm_LocalOrd i = 0; i < rowIndices.size(); i++)
1032 sparseVals[jc[col] + rowProgress[col]] = rowVals[i];
1033 ir[jc[col] + rowProgress[col]] = m;
1040 delete[] sparseVals;
1041 delete[] rowProgress;
1069mxArray*
saveDataToMatlab(RCP<Xpetra::MultiVector<double, mm_LocalOrd, mm_GlobalOrd, mm_node_t>>& data)
1072 int nr = data->getGlobalLength();
1073 int nc = data->getNumVectors();
1075 double* array = (
double*) malloc(
sizeof(
double) * nr * nc);
1076 for(
int col = 0; col < nc; col++)
1078 Teuchos::ArrayRCP<const double> colData = data->getData(col);
1079 for(
int row = 0; row < nr; row++)
1081 array[col * nr + row] = colData[row];
1090mxArray*
saveDataToMatlab(RCP<Xpetra::MultiVector<complex_t, mm_LocalOrd, mm_GlobalOrd, mm_node_t>>& data)
1093 int nr = data->getGlobalLength();
1094 int nc = data->getNumVectors();
1097 for(
int col = 0; col < nc; col++)
1099 Teuchos::ArrayRCP<const complex_t> colData = data->getData(col);
1100 for(
int row = 0; row < nr; row++)
1102 array[col * nr + row] = colData[row];
1120 mxArray* output = mxCreateDoubleMatrix(data->GlobalLength(), data->NumVectors(), mxREAL);
1121 double* dataPtr = mxGetPr(output);
1122 data->ExtractCopy(dataPtr, data->GlobalLength());
1130 int numNodes = data->GetVertex2AggId()->getData(0).size();
1131 int numAggs = data->GetNumAggregates();
1133 mwSize singleton[] = {1, 1};
1134 dataIn[0] = mxCreateNumericArray(2, singleton, mxINT32_CLASS, mxREAL);
1135 *((
int*) mxGetData(dataIn[0])) = numNodes;
1136 dataIn[1] = mxCreateNumericArray(2, singleton, mxINT32_CLASS, mxREAL);
1137 *((
int*) mxGetData(dataIn[1])) = numAggs;
1138 mwSize nodeArrayDims[] = {(mwSize) numNodes, 1};
1139 dataIn[2] = mxCreateNumericArray(2, nodeArrayDims, mxINT32_CLASS, mxREAL);
1140 int* vtaid = (
int*) mxGetData(dataIn[2]);
1141 ArrayRCP<const mm_LocalOrd> vertexToAggID = data->GetVertex2AggId()->getData(0);
1142 for(
int i = 0; i < numNodes; i++)
1144 vtaid[i] = vertexToAggID[i];
1146 mwSize aggArrayDims[] = {(mwSize) numAggs, 1};
1147 dataIn[3] = mxCreateNumericArray(2, aggArrayDims, mxINT32_CLASS, mxREAL);
1150 for(
int i = 0; i < numNodes; i++)
1155 bool reassignRoots =
false;
1156 if(totalRoots != numAggs)
1158 cout << endl <<
"Warning: Number of root nodes and number of aggregates do not match." << endl;
1159 cout <<
"Will reassign root nodes when writing aggregates to matlab." << endl << endl;
1160 reassignRoots =
true;
1162 int* rn = (
int*) mxGetData(dataIn[3]);
1167 int lastFoundNode = 0;
1168 for(
int i = 0; i < numAggs; i++)
1171 for(
int j = lastFoundNode; j < lastFoundNode + numNodes; j++)
1173 int index = j % numNodes;
1174 if(vertexToAggID[index] == i)
1177 lastFoundNode = index;
1180 TEUCHOS_TEST_FOR_EXCEPTION(rn[i] == -1, runtime_error,
"Invalid aggregates: Couldn't find any node in aggregate #" << i <<
".");
1186 for(
int j = 0; j < numNodes; j++)
1191 throw runtime_error(
"Cannot store invalid aggregates in MATLAB - more root nodes than aggregates.");
1197 throw runtime_error(
"Cannot store invalid aggregates in MATLAB - fewer root nodes than aggregates.");
1200 dataIn[4] = mxCreateNumericArray(1, aggArrayDims, mxINT32_CLASS, mxREAL);
1201 int* as = (
int*) mxGetData(dataIn[4]);
1202 ArrayRCP<mm_LocalOrd> aggSizes = data->ComputeAggregateSizes();
1203 for(
int i = 0; i < numAggs; i++)
1205 as[i] = aggSizes[i];
1207 mxArray* matlabAggs[1];
1208 int result = mexCallMATLAB(1, matlabAggs, 5, dataIn,
"constructAggregates");
1210 throw runtime_error(
"Matlab encountered an error while constructing aggregates struct.");
1211 return matlabAggs[0];
1217 throw runtime_error(
"AmalgamationInfo not supported in MueMex yet.");
1218 return mxCreateDoubleScalar(0);
1224 int numEntries = (int) data->GetGlobalNumEdges();
1225 int numRows = (int) data->GetDomainMap()->getGlobalNumElements();
1226 mxArray* mat = mxCreateSparseLogicalMatrix(numRows, numRows, numEntries);
1227 mxLogical* outData = (mxLogical*) mxGetData(mat);
1228 mwIndex* rowInds = mxGetIr(mat);
1229 mwIndex* colPtrs = mxGetJc(mat);
1232 int* entriesPerRow =
new int[numRows];
1233 int* entriesPerCol =
new int[numRows];
1234 for(
int i = 0; i < numRows; i++)
1236 entriesPerRow[i] = 0;
1237 entriesPerCol[i] = 0;
1239 for(
int i = 0; i < numRows; i++)
1241 ArrayView<const mm_LocalOrd> neighbors = data->getNeighborVertices(i);
1242 memcpy(iter, neighbors.getRawPtr(),
sizeof(
mm_LocalOrd) * neighbors.size());
1243 entriesPerRow[i] = neighbors.size();
1244 for(
int j = 0; j < neighbors.size(); j++)
1246 entriesPerCol[neighbors[j]]++;
1248 iter += neighbors.size();
1251 mxLogical** valuesByColumn =
new mxLogical*[numRows];
1252 int* numEnteredPerCol =
new int[numRows];
1254 for(
int i = 0; i < numRows; i++)
1256 rowIndsByColumn[i] = &rowInds[accum];
1258 valuesByColumn[i] = &outData[accum];
1259 accum += entriesPerCol[i];
1260 if(accum > numEntries)
1261 throw runtime_error(
"potato");
1263 for(
int i = 0; i < numRows; i++)
1265 numEnteredPerCol[i] = 0;
1269 for(
int row = 0; row < numRows; row++)
1271 for(
int entryInRow = 0; entryInRow < entriesPerRow[row]; entryInRow++)
1273 int col = dataCopy[accum];
1275 rowIndsByColumn[col][numEnteredPerCol[col]] = row;
1276 valuesByColumn[col][numEnteredPerCol[col]] = (mxLogical) 1;
1277 numEnteredPerCol[col]++;
1281 for(
int col = 0; col < numRows; col++)
1283 colPtrs[col] = accum;
1284 accum += entriesPerCol[col];
1286 colPtrs[numRows] = accum;
1287 delete[] numEnteredPerCol;
1288 delete[] rowIndsByColumn;
1289 delete[] valuesByColumn;
1291 delete[] entriesPerRow;
1292 delete[] entriesPerCol;
1294 const ArrayRCP<const bool> boundaryFlags = data->GetBoundaryNodeMap();
1295 int numBoundaryNodes = 0;
1296 for(
int i = 0; i < boundaryFlags.size(); i++)
1298 if(boundaryFlags[i])
1301 cout <<
"Graph has " << numBoundaryNodes <<
" Dirichlet boundary nodes." << endl;
1302 mwSize dims[] = {(mwSize) numBoundaryNodes, 1};
1303 mxArray* boundaryList = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
1304 int* dest = (
int*) mxGetData(boundaryList);
1305 int* destIter = dest;
1306 for(
int i = 0; i < boundaryFlags.size(); i++)
1308 if(boundaryFlags[i])
1314 mxArray* constructArgs[] = {mat, boundaryList};
1316 mexCallMATLAB(1, out, 2, constructArgs,
"constructGraph");
1320#ifdef HAVE_MUELU_INTREPID2
1324 int rank = data->rank();
1327 throw std::runtime_error(
"Error: Only rank two FieldContainers are supported.");
1329 int nr = data->extent(0);
1330 int nc = data->extent(1);
1332 mwSize dims[]={(mwSize)nr,(mwSize)nc};
1333 mxArray* mxa = mxCreateNumericArray(2,dims, mxINT32_CLASS, mxREAL);
1334 int *array = (
int*) mxGetData(mxa);
1336 for(
int col = 0; col < nc; col++)
1338 for(
int row = 0; row < nr; row++)
1340 array[col * nr + row] = (*data)(row,col);
1378 this->data = newData;
1389 lvl.
Set<T>(name, data, fact);
1397 return lvl.
Get<T>(name);
1399 catch(std::exception& e)
1401 throw std::runtime_error(
"Requested custom variable " + name +
" is not in the level.");
1406template<
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1409 using namespace std;
1411 typedef RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> Matrix_t;
1412 typedef RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> MultiVector_t;
1413 typedef RCP<Aggregates<LocalOrdinal, GlobalOrdinal, Node>> Aggregates_t;
1414 typedef RCP<AmalgamationInfo<LocalOrdinal, GlobalOrdinal, Node>> AmalgamationInfo_t;
1415 typedef RCP<MGraph> Graph_t;
1417 vector<RCP<MuemexArg>> args;
1418 for(
size_t i = 0; i < needsList.size(); i++)
1420 if(needsList[i] ==
"A" || needsList[i] ==
"P" || needsList[i] ==
"R" || needsList[i]==
"Ptent")
1422 Matrix_t mydata = lvl.
Get<Matrix_t>(needsList[i], factory->
GetFactory(needsList[i]).get());
1425 else if(needsList[i] ==
"Nullspace" || needsList[i] ==
"Coordinates")
1427 MultiVector_t mydata = lvl.
Get<MultiVector_t>(needsList[i], factory->
GetFactory(needsList[i]).get());
1430 else if(needsList[i] ==
"Aggregates")
1432 Aggregates_t mydata = lvl.
Get<Aggregates_t>(needsList[i], factory->
GetFactory(needsList[i]).get());
1435 else if(needsList[i] ==
"UnAmalgamationInfo")
1437 AmalgamationInfo_t mydata = lvl.
Get<AmalgamationInfo_t>(needsList[i], factory->
GetFactory(needsList[i]).get());
1440 else if(needsList[i] ==
"Level")
1445 else if(needsList[i] ==
"Graph")
1447 Graph_t mydata = lvl.
Get<Graph_t>(needsList[i], factory->
GetFactory(needsList[i]).get());
1452 vector<string> words;
1453 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";
1455 char* buf = (
char*) malloc(needsList[i].size() + 1);
1456 strcpy(buf, needsList[i].c_str());
1457 for(
char* iter = buf; *iter !=
' '; iter++)
1462 throw runtime_error(badNameMsg);
1464 *iter = (char) tolower(*iter);
1466 const char* wordDelim =
" ";
1467 char* mark = strtok(buf, wordDelim);
1470 string wordStr(mark);
1471 words.push_back(wordStr);
1472 mark = strtok(NULL, wordDelim);
1474 if(words.size() != 2)
1477 throw runtime_error(badNameMsg);
1479 char* typeStr = (
char*) words[0].c_str();
1480 if(strstr(typeStr,
"ordinalvector"))
1482 typedef RCP<Xpetra::Vector<mm_LocalOrd, mm_LocalOrd, mm_GlobalOrd, mm_node_t>> LOVector_t;
1486 else if(strstr(typeStr,
"map"))
1488 typedef RCP<Xpetra::Map<mm_LocalOrd, mm_GlobalOrd, mm_node_t>> Map_t;
1492 else if(strstr(typeStr,
"scalar"))
1497 else if(strstr(typeStr,
"double"))
1502 else if(strstr(typeStr,
"complex"))
1507 else if(strstr(typeStr,
"matrix"))
1512 else if(strstr(typeStr,
"multivector"))
1517 else if(strstr(typeStr,
"int"))
1522 else if(strstr(typeStr,
"string"))
1530 throw std::runtime_error(words[0] +
" is not a known variable type.");
1538template<
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1541 using namespace std;
1543 typedef RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> Matrix_t;
1544 typedef RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> MultiVector_t;
1545 typedef RCP<Aggregates<LocalOrdinal, GlobalOrdinal, Node>> Aggregates_t;
1546 typedef RCP<AmalgamationInfo<LocalOrdinal, GlobalOrdinal, Node>> AmalgamationInfo_t;
1547 typedef RCP<MGraph> Graph_t;
1549 for(
size_t i = 0; i < size_t(provides.size()); i++)
1551 if(provides[i] ==
"A" || provides[i] ==
"P" || provides[i] ==
"R" || provides[i]==
"Ptent")
1553 RCP<MuemexData<Matrix_t>> mydata = Teuchos::rcp_static_cast<MuemexData<Matrix_t>>(mexOutput[i]);
1554 lvl.
Set(provides[i], mydata->getData(), factory);
1556 else if(provides[i] ==
"Nullspace" || provides[i] ==
"Coordinates")
1558 RCP<MuemexData<MultiVector_t>> mydata = Teuchos::rcp_static_cast<MuemexData<MultiVector_t>>(mexOutput[i]);
1559 lvl.
Set(provides[i], mydata->getData(), factory);
1561 else if(provides[i] ==
"Aggregates")
1563 RCP<MuemexData<Aggregates_t>> mydata = Teuchos::rcp_static_cast<MuemexData<Aggregates_t>>(mexOutput[i]);
1564 lvl.
Set(provides[i], mydata->getData(), factory);
1566 else if(provides[i] ==
"UnAmalgamationInfo")
1568 RCP<MuemexData<AmalgamationInfo_t>> mydata = Teuchos::rcp_static_cast<MuemexData<AmalgamationInfo_t>>(mexOutput[i]);
1569 lvl.
Set(provides[i], mydata->getData(), factory);
1571 else if(provides[i] ==
"Graph")
1573 RCP<MuemexData<Graph_t>> mydata = Teuchos::rcp_static_cast<MuemexData<Graph_t>>(mexOutput[i]);
1574 lvl.
Set(provides[i], mydata->getData(), factory);
1578 vector<string> words;
1579 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";
1581 char* buf = (
char*) malloc(provides[i].size() + 1);
1582 strcpy(buf, provides[i].c_str());
1583 for(
char* iter = buf; *iter !=
' '; iter++)
1588 throw runtime_error(badNameMsg);
1590 *iter = (char) tolower(*iter);
1592 const char* wordDelim =
" ";
1593 char* mark = strtok(buf, wordDelim);
1596 string wordStr(mark);
1597 words.push_back(wordStr);
1598 mark = strtok(NULL, wordDelim);
1600 if(words.size() != 2)
1603 throw runtime_error(badNameMsg);
1605 const char* typeStr = words[0].c_str();
1606 if(strstr(typeStr,
"ordinalvector"))
1608 typedef RCP<Xpetra::Vector<mm_LocalOrd, mm_LocalOrd, mm_GlobalOrd, mm_node_t>> LOVector_t;
1609 RCP<MuemexData<LOVector_t>> mydata = Teuchos::rcp_static_cast<MuemexData<LOVector_t>>(mexOutput[i]);
1612 else if(strstr(typeStr,
"map"))
1614 typedef RCP<Xpetra::Map<mm_LocalOrd, mm_GlobalOrd, mm_node_t>> Map_t;
1615 RCP<MuemexData<Map_t>> mydata = Teuchos::rcp_static_cast<MuemexData<Map_t>>(mexOutput[i]);
1618 else if(strstr(typeStr,
"scalar"))
1620 RCP<MuemexData<Scalar>> mydata = Teuchos::rcp_static_cast<MuemexData<Scalar>>(mexOutput[i]);
1623 else if(strstr(typeStr,
"double"))
1625 RCP<MuemexData<double>> mydata = Teuchos::rcp_static_cast<MuemexData<double>>(mexOutput[i]);
1628 else if(strstr(typeStr,
"complex"))
1630 RCP<MuemexData<complex_t>> mydata = Teuchos::rcp_static_cast<MuemexData<complex_t>>(mexOutput[i]);
1633 else if(strstr(typeStr,
"matrix"))
1635 RCP<MuemexData<Matrix_t>> mydata = Teuchos::rcp_static_cast<MuemexData<Matrix_t>>(mexOutput[i]);
1638 else if(strstr(typeStr,
"multivector"))
1640 RCP<MuemexData<MultiVector_t>> mydata = Teuchos::rcp_static_cast<MuemexData<MultiVector_t>>(mexOutput[i]);
1643 else if(strstr(typeStr,
"int"))
1645 RCP<MuemexData<int>> mydata = Teuchos::rcp_static_cast<MuemexData<int>>(mexOutput[i]);
1648 else if(strstr(typeStr,
"bool"))
1650 RCP<MuemexData<bool> > mydata = Teuchos::rcp_static_cast<MuemexData<bool> >(mexOutput[i]);
1653 else if(strstr(typeStr,
"string"))
1655 RCP<MuemexData<string>> mydata = Teuchos::rcp_static_cast<MuemexData<string>>(mexOutput[i]);
1661 throw std::runtime_error(words[0] +
" is not a known variable type.");
1672 throw std::runtime_error(
"Muemex does not support long long for global indices");
1677 throw std::runtime_error(
"Muemex does not support long long for global indices");
1682 throw std::runtime_error(
"Muemex does not support long long for global indices");
1687 throw std::runtime_error(
"Muemex does not support long long for global indices");
MueLu::DefaultScalar Scalar
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
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())
MuemexArg(MuemexType dataType)
mxArray * convertToMatlab()
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 >()
MuemexType getMuemexType(const T &data)
Tpetra::Map ::local_ordinal_type mm_LocalOrd
RCP< Xpetra::MultiVector< SC, LO, GO, NO > > TpetraMultiVector_To_XpetraMultiVector(const Teuchos::RCP< Tpetra::MultiVector< SC, LO, GO, NO > > &Vtpetra)
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)
@ XPETRA_MULTIVECTOR_DOUBLE
@ XPETRA_MULTIVECTOR_COMPLEX
@ TPETRA_MULTIVECTOR_COMPLEX
@ TPETRA_MULTIVECTOR_DOUBLE
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)
RCP< Xpetra::Matrix< SC, LO, GO, NO > > EpetraCrs_To_XpetraMatrix(const Teuchos::RCP< Epetra_CrsMatrix > &A)
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)
RCP< Xpetra::Matrix< SC, LO, GO, NO > > TpetraCrs_To_XpetraMatrix(const Teuchos::RCP< Tpetra::CrsMatrix< SC, LO, GO, NO > > &Atpetra)
void fillMatlabArray(Scalar *array, const mxArray *mxa, int n)
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 ¶ms)
mxArray * createMatlabSparse< complex_t >(int numRows, int numCols, int nnz)
T loadDataFromMatlab(const mxArray *mxa)
mxArray * createMatlabMultiVector< double >(int numRows, int numCols)
mxArray * createMatlabSparse(int numRows, int numCols, int nnz)
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)