MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_AggregationExportFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// MueLu: A package for multigrid based preconditioning
6// Copyright 2012 Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact
39// Jonathan Hu (jhu@sandia.gov)
40// Andrey Prokopenko (aprokop@sandia.gov)
41// Ray Tuminaro (rstumin@sandia.gov)
42//
43// ***********************************************************************
44//
45// @HEADER
46/*
47 * MueLu_AggregationExportFactory_def.hpp
48 *
49 * Created on: Feb 10, 2012
50 * Author: wiesner
51 */
52
53#ifndef MUELU_AGGREGATIONEXPORTFACTORY_DEF_HPP_
54#define MUELU_AGGREGATIONEXPORTFACTORY_DEF_HPP_
55
56#include <Xpetra_Matrix.hpp>
57#include <Xpetra_CrsMatrixWrap.hpp>
58#include <Xpetra_ImportFactory.hpp>
59#include <Xpetra_MultiVectorFactory.hpp>
61#include "MueLu_Level.hpp"
62#include "MueLu_Aggregates.hpp"
63#include "MueLu_Graph.hpp"
64#include "MueLu_AmalgamationFactory.hpp"
65#include "MueLu_AmalgamationInfo.hpp"
66#include "MueLu_Monitor.hpp"
67#include <vector>
68#include <list>
69#include <algorithm>
70#include <string>
71#include <stdexcept>
72#include <cstdio>
73#include <cmath>
74
75namespace MueLu {
76
77 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
79 RCP<ParameterList> validParamList = rcp(new ParameterList());
80
81 std::string output_msg = "Output filename template (%TIMESTEP is replaced by \'Output file: time step\' variable,"
82 "%ITER is replaced by \'Output file: iter\' variable, %LEVELID is replaced level id, %PROCID is replaced by processor id)";
83 std::string output_def = "aggs_level%LEVELID_proc%PROCID.out";
84
85 validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Factory for A.");
86 validParamList->set< RCP<const FactoryBase> >("Coordinates", Teuchos::null, "Factory for Coordinates.");
87 validParamList->set< RCP<const FactoryBase> >("Graph", Teuchos::null, "Factory for Graph.");
88 validParamList->set< RCP<const FactoryBase> >("Aggregates", Teuchos::null, "Factory for Aggregates.");
89 validParamList->set< RCP<const FactoryBase> >("UnAmalgamationInfo", Teuchos::null, "Factory for UnAmalgamationInfo.");
90 validParamList->set< RCP<const FactoryBase> >("DofsPerNode", Teuchos::null, "Factory for DofsPerNode.");
91 // CMS/BMK: Old style factory-only options. Deprecate me.
92 validParamList->set< std::string > ("Output filename", output_def, output_msg);
93 validParamList->set< int > ("Output file: time step", 0, "time step variable for output file name");
94 validParamList->set< int > ("Output file: iter", 0, "nonlinear iteration variable for output file name");
95
96 // New-style master list options (here are same defaults as in masterList.xml)
97 validParamList->set< std::string > ("aggregation: output filename", "", "filename for VTK-style visualization output");
98 validParamList->set< int > ("aggregation: output file: time step", 0, "time step variable for output file name");// Remove me?
99 validParamList->set< int > ("aggregation: output file: iter", 0, "nonlinear iteration variable for output file name");//Remove me?
100 validParamList->set<std::string> ("aggregation: output file: agg style", "Point Cloud", "style of aggregate visualization for VTK output");
101 validParamList->set<bool> ("aggregation: output file: fine graph edges", false, "Whether to draw all fine node connections along with the aggregates.");
102 validParamList->set<bool> ("aggregation: output file: coarse graph edges", false, "Whether to draw all coarse node connections along with the aggregates.");
103 validParamList->set<bool> ("aggregation: output file: build colormap", false, "Whether to output a random colormap for ParaView in a separate XML file.");
104 return validParamList;
105 }
106
107 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
109 Input(fineLevel, "Aggregates"); //< factory which created aggregates
110 Input(fineLevel, "DofsPerNode"); //< CoalesceAndDropFactory (needed for DofsPerNode variable)
111 Input(fineLevel, "UnAmalgamationInfo"); //< AmalgamationFactory (needed for UnAmalgamationInfo variable)
112
113 const ParameterList & pL = GetParameterList();
114 //Only pull in coordinates if the user explicitly requests direct VTK output, so as not to break uses of old code
115 if(pL.isParameter("aggregation: output filename") && pL.get<std::string>("aggregation: output filename").length())
116 {
117 Input(fineLevel, "Coordinates");
118 Input(fineLevel, "A");
119 Input(fineLevel, "Graph");
120 if(pL.get<bool>("aggregation: output file: coarse graph edges"))
121 {
122 Input(coarseLevel, "Coordinates");
123 Input(coarseLevel, "A");
124 Input(coarseLevel, "Graph");
125 }
126 }
127 }
128
129 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
131 using namespace std;
132 //Decide which build function to follow, based on input params
133 const ParameterList& pL = GetParameterList();
134 FactoryMonitor m(*this, "AggregationExportFactory", coarseLevel);
135 Teuchos::RCP<Aggregates> aggregates = Get< Teuchos::RCP<Aggregates> >(fineLevel,"Aggregates");
136 Teuchos::RCP<const Teuchos::Comm<int> > comm = aggregates->GetMap()->getComm();
137 int numProcs = comm->getSize();
138 int myRank = comm->getRank();
139 string masterFilename = pL.get<std::string>("aggregation: output filename"); //filename parameter from master list
140 string pvtuFilename = ""; //only root processor will set this
141 string localFilename = pL.get<std::string>("Output filename");
142 string filenameToWrite;
143 bool useVTK = false;
144 doCoarseGraphEdges_ = pL.get<bool>("aggregation: output file: coarse graph edges");
145 doFineGraphEdges_ = pL.get<bool>("aggregation: output file: fine graph edges");
146 if(masterFilename.length())
147 {
148 useVTK = true;
149 filenameToWrite = masterFilename;
150 if(filenameToWrite.rfind(".vtu") == string::npos) //Must have the file extension in the name
151 filenameToWrite.append(".vtu");
152 if(numProcs > 1 && filenameToWrite.rfind("%PROCID") == string::npos) //filename can't be identical between processsors in parallel problem
153 filenameToWrite.insert(filenameToWrite.rfind(".vtu"), "-proc%PROCID");
154 }
155 else
156 filenameToWrite = localFilename;
157 LocalOrdinal DofsPerNode = Get< LocalOrdinal > (fineLevel,"DofsPerNode");
158 Teuchos::RCP<AmalgamationInfo> amalgInfo = Get< RCP<AmalgamationInfo> > (fineLevel,"UnAmalgamationInfo");
159 Teuchos::RCP<Matrix> Amat = Get<RCP<Matrix> >(fineLevel, "A");
160 Teuchos::RCP<Matrix> Ac;
162 Ac = Get<RCP<Matrix> >(coarseLevel, "A");
163 Teuchos::RCP<CoordinateMultiVector> coords = Teuchos::null;
164 Teuchos::RCP<CoordinateMultiVector> coordsCoarse = Teuchos::null;
165 Teuchos::RCP<GraphBase> fineGraph = Teuchos::null;
166 Teuchos::RCP<GraphBase> coarseGraph = Teuchos::null;
168 fineGraph = Get<RCP<GraphBase> >(fineLevel, "Graph");
170 coarseGraph = Get<RCP<GraphBase> >(coarseLevel, "Graph");
171 if(useVTK) //otherwise leave null, will not be accessed by non-vtk code
172 {
173 coords = Get<RCP<CoordinateMultiVector> >(fineLevel, "Coordinates");
174 coords_ = coords;
176 coordsCoarse = Get<RCP<CoordinateMultiVector> >(coarseLevel, "Coordinates");
177 dims_ = coords->getNumVectors(); //2D or 3D?
178 if(numProcs > 1)
179 {
180 if (aggregates->AggregatesCrossProcessors())
181 { // Do we want to use the map from aggregates here instead of the map from A? Using the map from A seems to be problematic with multiple dofs per node
182 RCP<Import> coordImporter = Xpetra::ImportFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(coords->getMap(), Amat->getColMap());
183 RCP<CoordinateMultiVector> ghostedCoords = Xpetra::MultiVectorFactory<coordinate_type, LocalOrdinal, GlobalOrdinal, Node>::Build(Amat->getColMap(), dims_);
184 ghostedCoords->doImport(*coords, *coordImporter, Xpetra::INSERT);
185 coords = ghostedCoords;
186 coords_ = ghostedCoords;
187 }
189 {
190 RCP<Import> coordImporter = Xpetra::ImportFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(coordsCoarse->getMap(), Ac->getColMap());
191 RCP<CoordinateMultiVector> ghostedCoords = Xpetra::MultiVectorFactory<coordinate_type, LocalOrdinal, GlobalOrdinal, Node>::Build(Ac->getColMap(), dims_);
192 ghostedCoords->doImport(*coordsCoarse, *coordImporter, Xpetra::INSERT);
193 coordsCoarse = ghostedCoords;
194 coordsCoarse_ = ghostedCoords;
195 }
196 }
197 }
198 GetOStream(Runtime0) << "AggregationExportFactory: DofsPerNode: " << DofsPerNode << std::endl;
199 Teuchos::RCP<LocalOrdinalMultiVector> vertex2AggId_vector = aggregates->GetVertex2AggId();
200 Teuchos::RCP<LocalOrdinalVector> procWinner_vector = aggregates->GetProcWinner();
201 Teuchos::ArrayRCP<LocalOrdinal> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
202 Teuchos::ArrayRCP<LocalOrdinal> procWinner = aggregates->GetProcWinner()->getDataNonConst(0);
203
204 vertex2AggId_ = vertex2AggId;
205
206 // prepare for calculating global aggregate ids
207 std::vector<GlobalOrdinal> numAggsGlobal (numProcs, 0);
208 std::vector<GlobalOrdinal> numAggsLocal (numProcs, 0);
209 std::vector<GlobalOrdinal> minGlobalAggId(numProcs, 0);
210
211 numAggsLocal[myRank] = aggregates->GetNumAggregates();
212 Teuchos::reduceAll(*comm, Teuchos::REDUCE_SUM, numProcs, &numAggsLocal[0], &numAggsGlobal[0]);
213 for (int i = 1; i < Teuchos::as<int>(numAggsGlobal.size()); ++i)
214 {
215 numAggsGlobal [i] += numAggsGlobal[i-1];
216 minGlobalAggId[i] = numAggsGlobal[i-1];
217 }
218 if(numProcs == 0)
219 aggsOffset_ = 0;
220 else
221 aggsOffset_ = minGlobalAggId[myRank];
222 ArrayRCP<LO> aggStart;
223 ArrayRCP<GlobalOrdinal> aggToRowMap;
224 amalgInfo->UnamalgamateAggregates(*aggregates, aggStart, aggToRowMap);
225 int timeStep = pL.get< int > ("Output file: time step");
226 int iter = pL.get< int > ("Output file: iter");
227 filenameToWrite = this->replaceAll(filenameToWrite, "%LEVELID", toString(fineLevel.GetLevelID()));
228 filenameToWrite = this->replaceAll(filenameToWrite, "%TIMESTEP", toString(timeStep));
229 filenameToWrite = this->replaceAll(filenameToWrite, "%ITER", toString(iter));
230 //Proc id MUST be included in vtu filenames to distinguish them (if multiple procs)
231 //In all other cases (else), including processor # in filename is optional
232 string masterStem = "";
233 if(useVTK)
234 {
235 masterStem = filenameToWrite.substr(0, filenameToWrite.rfind(".vtu"));
236 masterStem = this->replaceAll(masterStem, "%PROCID", "");
237 }
238 pvtuFilename = masterStem + "-master.pvtu";
239 string baseFname = filenameToWrite; //get a version of the filename string with the %PROCID token, but without substituting myRank (needed for pvtu output)
240 filenameToWrite = this->replaceAll(filenameToWrite, "%PROCID", toString(myRank));
241 GetOStream(Runtime0) << "AggregationExportFactory: outputfile \"" << filenameToWrite << "\"" << std::endl;
242 ofstream fout(filenameToWrite.c_str());
243 GO numAggs = aggregates->GetNumAggregates();
244 if(!useVTK)
245 {
246 GO indexBase = aggregates->GetMap()->getIndexBase(); // extract indexBase from overlapping map within aggregates structure. The indexBase is constant throughout the whole simulation (either 0 = C++ or 1 = Fortran)
247 GO offset = amalgInfo->GlobalOffset(); // extract offset for global dof ids
248 vector<GlobalOrdinal> nodeIds;
249 for (int i = 0; i < numAggs; ++i) {
250 fout << "Agg " << minGlobalAggId[myRank] + i << " Proc " << myRank << ":";
251
252 // TODO: Use k+=DofsPerNode instead of ++k and get rid of std::unique call afterwards
253 for (int k = aggStart[i]; k < aggStart[i+1]; ++k) {
254 nodeIds.push_back((aggToRowMap[k] - offset - indexBase) / DofsPerNode + indexBase);
255 }
256
257 // remove duplicate entries from nodeids
258 std::sort(nodeIds.begin(), nodeIds.end());
259 typename std::vector<GlobalOrdinal>::iterator endLocation = std::unique(nodeIds.begin(), nodeIds.end());
260 nodeIds.erase(endLocation, nodeIds.end());
261
262 // print out nodeids
263 for(typename std::vector<GlobalOrdinal>::iterator printIt = nodeIds.begin(); printIt != nodeIds.end(); printIt++)
264 fout << " " << *printIt;
265 nodeIds.clear();
266 fout << std::endl;
267 }
268 }
269 else
270 {
271 using namespace std;
272 //Make sure we have coordinates
273 TEUCHOS_TEST_FOR_EXCEPTION(coords.is_null(), Exceptions::RuntimeError,"AggExportFactory could not get coordinates, but they are required for VTK output.");
274 numAggs_ = numAggs;
275 numNodes_ = coords->getLocalLength();
276 //Get the sizes of the aggregates to speed up grabbing node IDs
277 aggSizes_ = aggregates->ComputeAggregateSizesArrayRCP();
278 myRank_ = myRank;
279 string aggStyle = "Point Cloud";
280 try
281 {
282 aggStyle = pL.get<string>("aggregation: output file: agg style"); //Let "Point Cloud" be the default style
283 }
284 catch(std::exception& e) {}
285 vector<int> vertices;
286 vector<int> geomSizes;
287 string indent = "";
288 nodeMap_ = Amat->getMap();
289 for(LocalOrdinal i = 0; i < numNodes_; i++)
290 {
291 isRoot_.push_back(aggregates->IsRoot(i));
292 }
293 //If problem is serial and not outputting fine nor coarse graph edges, don't make pvtu file
294 //Otherwise create it
295 if(myRank == 0 && (numProcs != 1 || doCoarseGraphEdges_ || doFineGraphEdges_))
296 {
297 ofstream pvtu(pvtuFilename.c_str());
298 writePVTU_(pvtu, baseFname, numProcs);
299 pvtu.close();
300 }
301 if(aggStyle == "Point Cloud")
302 this->doPointCloud(vertices, geomSizes, numAggs_, numNodes_);
303 else if(aggStyle == "Jacks")
304 this->doJacks(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_);
305 else if(aggStyle == "Jacks++") //Not actually implemented
306 doJacksPlus_(vertices, geomSizes);
307 else if(aggStyle == "Convex Hulls")
308 doConvexHulls(vertices, geomSizes);
309 else
310 {
311 GetOStream(Warnings0) << " Unrecognized agg style.\n Possible values are Point Cloud, Jacks, Jacks++, and Convex Hulls.\n Defaulting to Point Cloud." << std::endl;
312 aggStyle = "Point Cloud";
313 this->doPointCloud(vertices, geomSizes, numAggs_, numNodes_);
314 }
315 writeFile_(fout, aggStyle, vertices, geomSizes);
317 {
318 string fname = filenameToWrite;
319 string cEdgeFile = fname.insert(fname.rfind(".vtu"), "-coarsegraph");
320 std::ofstream edgeStream(cEdgeFile.c_str());
321 doGraphEdges_(edgeStream, Ac, coarseGraph, false, DofsPerNode);
322 }
324 {
325 string fname = filenameToWrite;
326 string fEdgeFile = fname.insert(fname.rfind(".vtu"), "-finegraph");
327 std::ofstream edgeStream(fEdgeFile.c_str());
328 doGraphEdges_(edgeStream, Amat, fineGraph, true, DofsPerNode);
329 }
330 if(myRank == 0 && pL.get<bool>("aggregation: output file: build colormap"))
331 {
333 }
334 }
335 fout.close();
336 }
337
338 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
339 void AggregationExportFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doJacksPlus_(std::vector<int>& /* vertices */, std::vector<int>& /* geomSizes */) const
340 {
341 //TODO
342 }
343
344 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
345 void AggregationExportFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doConvexHulls(std::vector<int>& vertices, std::vector<int>& geomSizes) const
346 {
347 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> xCoords = coords_->getData(0);
348 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> yCoords = coords_->getData(1);
349 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> zCoords = Teuchos::null;
350
351 if(dims_ == 2) {
352 this->doConvexHulls2D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_, xCoords, yCoords);
353 } else {
354 zCoords = coords_->getData(2);
355 this->doConvexHulls3D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_, xCoords, yCoords, zCoords);
356 }
357 }
358
359 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
360 void AggregationExportFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doGraphEdges_(std::ofstream& fout, Teuchos::RCP<Matrix>& A, Teuchos::RCP<GraphBase>& G, bool fine, int dofs) const
361 {
362 using namespace std;
363 ArrayView<const Scalar> values;
364 ArrayView<const LocalOrdinal> neighbors;
365 //Allow two different colors of connections (by setting "aggregates" scalar to CONTRAST_1 or CONTRAST_2)
366 vector<pair<int, int> > vert1; //vertices (node indices)
367 vector<pair<int, int> > vert2; //size of every cell is assumed to be 2 vertices, since all edges are drawn as lines
368
369 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> xCoords = coords_->getData(0);
370 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> yCoords = coords_->getData(1);
371 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> zCoords = Teuchos::null;
372 if(dims_ == 3)
373 zCoords = coords_->getData(2);
374
375 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> cx = coordsCoarse_->getData(0);
376 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> cy = coordsCoarse_->getData(1);
377 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> cz = Teuchos::null;
378 if(dims_ == 3)
379 cz = coordsCoarse_->getData(2);
380
381 if(A->isGloballyIndexed())
382 {
383 ArrayView<const GlobalOrdinal> indices;
384 for(GlobalOrdinal globRow = 0; globRow < GlobalOrdinal(A->getGlobalNumRows()); globRow++)
385 {
386 if(dofs == 1)
387 A->getGlobalRowView(globRow, indices, values);
388 neighbors = G->getNeighborVertices((LocalOrdinal) globRow);
389 int gEdge = 0;
390 int aEdge = 0;
391 while(gEdge != int(neighbors.size()))
392 {
393 if(dofs == 1)
394 {
395 if(neighbors[gEdge] == indices[aEdge])
396 {
397 //graph and matrix both have this edge, wasn't filtered, show as color 1
398 vert1.push_back(pair<int, int>(int(globRow), neighbors[gEdge]));
399 gEdge++;
400 aEdge++;
401 }
402 else
403 {
404 //graph contains an edge at gEdge which was filtered from A, show as color 2
405 vert2.push_back(pair<int, int>(int(globRow), neighbors[gEdge]));
406 gEdge++;
407 }
408 }
409 else //for multiple DOF problems, don't try to detect filtered edges and ignore A
410 {
411 vert1.push_back(pair<int, int>(int(globRow), neighbors[gEdge]));
412 gEdge++;
413 }
414 }
415 }
416 }
417 else
418 {
419 ArrayView<const LocalOrdinal> indices;
420 for(LocalOrdinal locRow = 0; locRow < LocalOrdinal(A->getLocalNumRows()); locRow++)
421 {
422 if(dofs == 1)
423 A->getLocalRowView(locRow, indices, values);
424 neighbors = G->getNeighborVertices(locRow);
425 //Add those local indices (columns) to the list of connections (which are pairs of the form (localM, localN))
426 int gEdge = 0;
427 int aEdge = 0;
428 while(gEdge != int(neighbors.size()))
429 {
430 if(dofs == 1)
431 {
432 if(neighbors[gEdge] == indices[aEdge])
433 {
434 vert1.push_back(pair<int, int>(locRow, neighbors[gEdge]));
435 gEdge++;
436 aEdge++;
437 }
438 else
439 {
440 vert2.push_back(pair<int, int>(locRow, neighbors[gEdge]));
441 gEdge++;
442 }
443 }
444 else
445 {
446 vert1.push_back(pair<int, int>(locRow, neighbors[gEdge]));
447 gEdge++;
448 }
449 }
450 }
451 }
452 for(size_t i = 0; i < vert1.size(); i ++)
453 {
454 if(vert1[i].first > vert1[i].second)
455 {
456 int temp = vert1[i].first;
457 vert1[i].first = vert1[i].second;
458 vert1[i].second = temp;
459 }
460 }
461 for(size_t i = 0; i < vert2.size(); i++)
462 {
463 if(vert2[i].first > vert2[i].second)
464 {
465 int temp = vert2[i].first;
466 vert2[i].first = vert2[i].second;
467 vert2[i].second = temp;
468 }
469 }
470 sort(vert1.begin(), vert1.end());
471 vector<pair<int, int> >::iterator newEnd = unique(vert1.begin(), vert1.end()); //remove duplicate edges
472 vert1.erase(newEnd, vert1.end());
473 sort(vert2.begin(), vert2.end());
474 newEnd = unique(vert2.begin(), vert2.end());
475 vert2.erase(newEnd, vert2.end());
476 vector<int> points1;
477 points1.reserve(2 * vert1.size());
478 for(size_t i = 0; i < vert1.size(); i++)
479 {
480 points1.push_back(vert1[i].first);
481 points1.push_back(vert1[i].second);
482 }
483 vector<int> points2;
484 points2.reserve(2 * vert2.size());
485 for(size_t i = 0; i < vert2.size(); i++)
486 {
487 points2.push_back(vert2[i].first);
488 points2.push_back(vert2[i].second);
489 }
490 vector<int> unique1 = this->makeUnique(points1);
491 vector<int> unique2 = this->makeUnique(points2);
492 fout << "<VTKFile type=\"UnstructuredGrid\" byte_order=\"LittleEndian\">" << endl;
493 fout << " <UnstructuredGrid>" << endl;
494 fout << " <Piece NumberOfPoints=\"" << unique1.size() + unique2.size() << "\" NumberOfCells=\"" << vert1.size() + vert2.size() << "\">" << endl;
495 fout << " <PointData Scalars=\"Node Aggregate Processor\">" << endl;
496 fout << " <DataArray type=\"Int32\" Name=\"Node\" format=\"ascii\">" << endl; //node and aggregate will be set to CONTRAST_1|2, but processor will have its actual value
497 string indent = " ";
498 fout << indent;
499 for(size_t i = 0; i < unique1.size(); i++)
500 {
501 fout << CONTRAST_1_ << " ";
502 if(i % 25 == 24)
503 fout << endl << indent;
504 }
505 for(size_t i = 0; i < unique2.size(); i++)
506 {
507 fout << CONTRAST_2_ << " ";
508 if((i + 2 * vert1.size()) % 25 == 24)
509 fout << endl << indent;
510 }
511 fout << endl;
512 fout << " </DataArray>" << endl;
513 fout << " <DataArray type=\"Int32\" Name=\"Aggregate\" format=\"ascii\">" << endl;
514 fout << indent;
515 for(size_t i = 0; i < unique1.size(); i++)
516 {
517 fout << CONTRAST_1_ << " ";
518 if(i % 25 == 24)
519 fout << endl << indent;
520 }
521 for(size_t i = 0; i < unique2.size(); i++)
522 {
523 fout << CONTRAST_2_ << " ";
524 if((i + 2 * vert2.size()) % 25 == 24)
525 fout << endl << indent;
526 }
527 fout << endl;
528 fout << " </DataArray>" << endl;
529 fout << " <DataArray type=\"Int32\" Name=\"Processor\" format=\"ascii\">" << endl;
530 fout << indent;
531 for(size_t i = 0; i < unique1.size() + unique2.size(); i++)
532 {
533 fout << myRank_ << " ";
534 if(i % 25 == 24)
535 fout << endl << indent;
536 }
537 fout << endl;
538 fout << " </DataArray>" << endl;
539 fout << " </PointData>" << endl;
540 fout << " <Points>" << endl;
541 fout << " <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
542 fout << indent;
543 for(size_t i = 0; i < unique1.size(); i++)
544 {
545 if(fine)
546 {
547 fout << xCoords[unique1[i]] << " " << yCoords[unique1[i]] << " ";
548 if(dims_ == 3)
549 fout << zCoords[unique1[i]] << " ";
550 else
551 fout << "0 ";
552 if(i % 2)
553 fout << endl << indent;
554 }
555 else
556 {
557 fout << cx[unique1[i]] << " " << cy[unique1[i]] << " ";
558 if(dims_ == 3)
559 fout << cz[unique1[i]] << " ";
560 else
561 fout << "0 ";
562 if(i % 2)
563 fout << endl << indent;
564 }
565 }
566 for(size_t i = 0; i < unique2.size(); i++)
567 {
568 if(fine)
569 {
570 fout << xCoords[unique2[i]] << " " << yCoords[unique2[i]] << " ";
571 if(dims_ == 3)
572 fout << zCoords[unique2[i]] << " ";
573 else
574 fout << "0 ";
575 if(i % 2)
576 fout << endl << indent;
577 }
578 else
579 {
580 fout << cx[unique2[i]] << " " << cy[unique2[i]] << " ";
581 if(dims_ == 3)
582 fout << cz[unique2[i]] << " ";
583 else
584 fout << "0 ";
585 if((i + unique1.size()) % 2)
586 fout << endl << indent;
587 }
588 }
589 fout << endl;
590 fout << " </DataArray>" << endl;
591 fout << " </Points>" << endl;
592 fout << " <Cells>" << endl;
593 fout << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
594 fout << indent;
595 for(size_t i = 0; i < points1.size(); i++)
596 {
597 fout << points1[i] << " ";
598 if(i % 10 == 9)
599 fout << endl << indent;
600 }
601 for(size_t i = 0; i < points2.size(); i++)
602 {
603 fout << points2[i] + unique1.size() << " ";
604 if((i + points1.size()) % 10 == 9)
605 fout << endl << indent;
606 }
607 fout << endl;
608 fout << " </DataArray>" << endl;
609 fout << " <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
610 fout << indent;
611 int offset = 0;
612 for(size_t i = 0; i < vert1.size() + vert2.size(); i++)
613 {
614 offset += 2;
615 fout << offset << " ";
616 if(i % 10 == 9)
617 fout << endl << indent;
618 }
619 fout << endl;
620 fout << " </DataArray>" << endl;
621 fout << " <DataArray type=\"Int32\" Name=\"types\" format=\"ascii\">" << endl;
622 fout << indent;
623 for(size_t i = 0; i < vert1.size() + vert2.size(); i++)
624 {
625 fout << "3 ";
626 if(i % 25 == 24)
627 fout << endl << indent;
628 }
629 fout << endl;
630 fout << " </DataArray>" << endl;
631 fout << " </Cells>" << endl;
632 fout << " </Piece>" << endl;
633 fout << " </UnstructuredGrid>" << endl;
634 fout << "</VTKFile>" << endl;
635 }
636
637 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
638 void AggregationExportFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::writeFile_(std::ofstream& fout, std::string styleName, std::vector<int>& vertices, std::vector<int>& geomSizes) const
639 {
640 using namespace std;
641
642 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> xCoords = coords_->getData(0);
643 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> yCoords = coords_->getData(1);
644 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> zCoords = Teuchos::null;
645 if(dims_ == 3)
646 zCoords = coords_->getData(2);
647
648 vector<int> uniqueFine = this->makeUnique(vertices);
649 string indent = " ";
650 fout << "<!--" << styleName << " Aggregates Visualization-->" << endl;
651 fout << "<VTKFile type=\"UnstructuredGrid\" byte_order=\"LittleEndian\">" << endl;
652 fout << " <UnstructuredGrid>" << endl;
653 fout << " <Piece NumberOfPoints=\"" << uniqueFine.size() << "\" NumberOfCells=\"" << geomSizes.size() << "\">" << endl;
654 fout << " <PointData Scalars=\"Node Aggregate Processor\">" << endl;
655 fout << " <DataArray type=\"Int32\" Name=\"Node\" format=\"ascii\">" << endl;
656 indent = " ";
657 fout << indent;
658 bool localIsGlobal = GlobalOrdinal(nodeMap_->getGlobalNumElements()) == GlobalOrdinal(nodeMap_->getLocalNumElements());
659 for(size_t i = 0; i < uniqueFine.size(); i++)
660 {
661 if(localIsGlobal)
662 {
663 fout << uniqueFine[i] << " "; //if all nodes are on this processor, do not map from local to global
664 }
665 else
666 fout << nodeMap_->getGlobalElement(uniqueFine[i]) << " ";
667 if(i % 10 == 9)
668 fout << endl << indent;
669 }
670 fout << endl;
671 fout << " </DataArray>" << endl;
672 fout << " <DataArray type=\"Int32\" Name=\"Aggregate\" format=\"ascii\">" << endl;
673 fout << indent;
674 for(size_t i = 0; i < uniqueFine.size(); i++)
675 {
676 if(vertex2AggId_[uniqueFine[i]]==-1)
677 fout << vertex2AggId_[uniqueFine[i]] << " ";
678 else
679 fout << aggsOffset_ + vertex2AggId_[uniqueFine[i]] << " ";
680 if(i % 10 == 9)
681 fout << endl << indent;
682 }
683 fout << endl;
684 fout << " </DataArray>" << endl;
685 fout << " <DataArray type=\"Int32\" Name=\"Processor\" format=\"ascii\">" << endl;
686 fout << indent;
687 for(size_t i = 0; i < uniqueFine.size(); i++)
688 {
689 fout << myRank_ << " ";
690 if(i % 20 == 19)
691 fout << endl << indent;
692 }
693 fout << endl;
694 fout << " </DataArray>" << endl;
695 fout << " </PointData>" << endl;
696 fout << " <Points>" << endl;
697 fout << " <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
698 fout << indent;
699 for(size_t i = 0; i < uniqueFine.size(); i++)
700 {
701 fout << xCoords[uniqueFine[i]] << " " << yCoords[uniqueFine[i]] << " ";
702 if(dims_ == 2)
703 fout << "0 ";
704 else
705 fout << zCoords[uniqueFine[i]] << " ";
706 if(i % 3 == 2)
707 fout << endl << indent;
708 }
709 fout << endl;
710 fout << " </DataArray>" << endl;
711 fout << " </Points>" << endl;
712 fout << " <Cells>" << endl;
713 fout << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << endl;
714 fout << indent;
715 for(size_t i = 0; i < vertices.size(); i++)
716 {
717 fout << vertices[i] << " ";
718 if(i % 10 == 9)
719 fout << endl << indent;
720 }
721 fout << endl;
722 fout << " </DataArray>" << endl;
723 fout << " <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << endl;
724 fout << indent;
725 int accum = 0;
726 for(size_t i = 0; i < geomSizes.size(); i++)
727 {
728 accum += geomSizes[i];
729 fout << accum << " ";
730 if(i % 10 == 9)
731 fout << endl << indent;
732 }
733 fout << endl;
734 fout << " </DataArray>" << endl;
735 fout << " <DataArray type=\"Int32\" Name=\"types\" format=\"ascii\">" << endl;
736 fout << indent;
737 for(size_t i = 0; i < geomSizes.size(); i++)
738 {
739 switch(geomSizes[i])
740 {
741 case 1:
742 fout << "1 "; //Point
743 break;
744 case 2:
745 fout << "3 "; //Line
746 break;
747 case 3:
748 fout << "5 "; //Triangle
749 break;
750 default:
751 fout << "7 "; //Polygon
752 }
753 if(i % 30 == 29)
754 fout << endl << indent;
755 }
756 fout << endl;
757 fout << " </DataArray>" << endl;
758 fout << " </Cells>" << endl;
759 fout << " </Piece>" << endl;
760 fout << " </UnstructuredGrid>" << endl;
761 fout << "</VTKFile>" << endl;
762 }
763
764 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
766 {
767 using namespace std;
768 try
769 {
770 ofstream color("random-colormap.xml");
771 color << "<ColorMap name=\"MueLu-Random\" space=\"RGB\">" << endl;
772 //Give -1, -2, -3 distinctive colors (so that the style functions can have constrasted geometry types)
773 //Do red, orange, yellow to constrast with cool color spectrum for other types
774 color << " <Point x=\"" << CONTRAST_1_ << "\" o=\"1\" r=\"1\" g=\"0\" b=\"0\"/>" << endl;
775 color << " <Point x=\"" << CONTRAST_2_ << "\" o=\"1\" r=\"1\" g=\"0.6\" b=\"0\"/>" << endl;
776 color << " <Point x=\"" << CONTRAST_3_ << "\" o=\"1\" r=\"1\" g=\"1\" b=\"0\"/>" << endl;
777 srand(time(NULL));
778 for(int i = 0; i < 5000; i += 4)
779 {
780 color << " <Point x=\"" << i << "\" o=\"1\" r=\"" << (rand() % 50) / 256.0 << "\" g=\"" << (rand() % 256) / 256.0 << "\" b=\"" << (rand() % 256) / 256.0 << "\"/>" << endl;
781 }
782 color << "</ColorMap>" << endl;
783 color.close();
784 }
785 catch(std::exception& e)
786 {
787 GetOStream(Warnings0) << " Error while building colormap file: " << e.what() << endl;
788 }
789 }
790
791 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
792 void AggregationExportFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::writePVTU_(std::ofstream& pvtu, std::string baseFname, int numProcs) const
793 {
794 using namespace std;
795 //If using vtk, filenameToWrite now contains final, correct ***.vtu filename (for the current proc)
796 //So the root proc will need to use its own filenameToWrite to make a list of the filenames of all other procs to put in
797 //pvtu file.
798 pvtu << "<VTKFile type=\"PUnstructuredGrid\" byte_order=\"LittleEndian\">" << endl;
799 pvtu << " <PUnstructuredGrid GhostLevel=\"0\">" << endl;
800 pvtu << " <PPointData Scalars=\"Node Aggregate Processor\">" << endl;
801 pvtu << " <PDataArray type=\"Int32\" Name=\"Node\"/>" << endl;
802 pvtu << " <PDataArray type=\"Int32\" Name=\"Aggregate\"/>" << endl;
803 pvtu << " <PDataArray type=\"Int32\" Name=\"Processor\"/>" << endl;
804 pvtu << " </PPointData>" << endl;
805 pvtu << " <PPoints>" << endl;
806 pvtu << " <PDataArray type=\"Float64\" NumberOfComponents=\"3\"/>" << endl;
807 pvtu << " </PPoints>" << endl;
808 for(int i = 0; i < numProcs; i++)
809 {
810 //specify the piece for each proc (the replaceAll expression matches what the filenames will be on other procs)
811 pvtu << " <Piece Source=\"" << this->replaceAll(baseFname, "%PROCID", toString(i)) << "\"/>" << endl;
812 }
813 //reference files with graph pieces, if applicable
815 {
816 for(int i = 0; i < numProcs; i++)
817 {
818 string fn = this->replaceAll(baseFname, "%PROCID", toString(i));
819 pvtu << " <Piece Source=\"" << fn.insert(fn.rfind(".vtu"), "-finegraph") << "\"/>" << endl;
820 }
821 }
823 {
824 for(int i = 0; i < numProcs; i++)
825 {
826 string fn = this->replaceAll(baseFname, "%PROCID", toString(i));
827 pvtu << " <Piece Source=\"" << fn.insert(fn.rfind(".vtu"), "-coarsegraph") << "\"/>" << endl;
828 }
829 }
830 pvtu << " </PUnstructuredGrid>" << endl;
831 pvtu << "</VTKFile>" << endl;
832 pvtu.close();
833 }
834} // namespace MueLu
835
836#endif /* MUELU_AGGREGATIONEXPORTFACTORY_DEF_HPP_ */
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Teuchos::RCP< CoordinateMultiVector > coords_
void doJacksPlus_(std::vector< int > &vertices, std::vector< int > &geomSizes) const
void writePVTU_(std::ofstream &pvtu, std::string baseFname, int numProcs) const
void doConvexHulls(std::vector< int > &vertices, std::vector< int > &geomSizes) const
void doGraphEdges_(std::ofstream &fout, Teuchos::RCP< Matrix > &A, Teuchos::RCP< GraphBase > &G, bool fine, int dofs) const
Teuchos::RCP< CoordinateMultiVector > coordsCoarse_
void writeFile_(std::ofstream &fout, std::string styleName, std::vector< int > &vertices, std::vector< int > &geomSizes) const
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
Class that holds all level-specific information.
int GetLevelID() const
Return level number.
virtual const Teuchos::ParameterList & GetParameterList() const
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
static void doConvexHulls2D(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< DefaultScalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< DefaultScalar >::coordinateType > &yCoords)
static void doConvexHulls3D(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< DefaultScalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< DefaultScalar >::coordinateType > &yCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< DefaultScalar >::coordinateType > &zCoords)
static void doPointCloud(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes)
static void doJacks(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId)
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line).
@ Runtime0
One-liner description of what is happening.
void replaceAll(std::string &str, const std::string &from, const std::string &to)
std::string toString(const T &what)
Little helper function to convert non-string types to strings.