1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPBGLCollapseGraph.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*----------------------------------------------------------------------------
16 Copyright (c) Sandia Corporation
17 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
18 ----------------------------------------------------------------------------*/
19
20 #include "vtkPBGLCollapseGraph.h"
21
22 #if !defined(VTK_LEGACY_REMOVE)
23
24 #include "vtkDataSetAttributes.h"
25 #include "vtkEdgeListIterator.h"
26 #include "vtkInformation.h"
27 #include "vtkInformationVector.h"
28 #include "vtkMutableDirectedGraph.h"
29 #include "vtkMutableUndirectedGraph.h"
30 #include "vtkObjectFactory.h"
31 #include "vtkPBGLDistributedGraphHelper.h"
32 #include "vtkPBGLGraphAdapter.h"
33 #include "vtkSmartPointer.h"
34 #include "vtkStreamingDemandDrivenPipeline.h"
35 #include "vtkTable.h"
36 #include "vtkTimerLog.h"
37 #include "vtkVariantArray.h"
38 #include "vtkVertexListIterator.h"
39
40 #include <boost/graph/use_mpi.hpp> // must precede all pbgl includes
41
42 vtkStandardNewMacro(vtkPBGLCollapseGraph);
43
vtkPBGLCollapseGraph()44 vtkPBGLCollapseGraph::vtkPBGLCollapseGraph()
45 {
46 VTK_LEGACY_BODY(vtkPBGLCollapseGraph::vtkPBGLCollapseGraph, "VTK 6.2");
47 }
48
~vtkPBGLCollapseGraph()49 vtkPBGLCollapseGraph::~vtkPBGLCollapseGraph()
50 {
51 }
52
PrintSelf(ostream & os,vtkIndent indent)53 void vtkPBGLCollapseGraph::PrintSelf(ostream& os, vtkIndent indent)
54 {
55 this->Superclass::PrintSelf(os, indent);
56 }
57
58 template<class MutableGraph>
vtkPBGLCollapseGraphRequestData(vtkPBGLCollapseGraph * self,vtkAbstractArray * input_arr,vtkInformation *,vtkInformationVector ** input_vec,vtkInformationVector * output_vec)59 int vtkPBGLCollapseGraphRequestData(
60 vtkPBGLCollapseGraph* self,
61 vtkAbstractArray* input_arr,
62 vtkInformation*,
63 vtkInformationVector** input_vec,
64 vtkInformationVector* output_vec)
65 {
66 vtkSmartPointer<vtkTimerLog> timer = vtkSmartPointer<vtkTimerLog>::New();
67 timer->StartTimer();
68
69 vtkGraph* input = vtkGraph::GetData(input_vec[0]);
70 vtkGraph* output = vtkGraph::GetData(output_vec);
71
72 vtkPBGLDistributedGraphHelper* input_helper =
73 vtkPBGLDistributedGraphHelper::SafeDownCast(input->GetDistributedGraphHelper());
74
75 if (!input_arr)
76 {
77 vtkErrorWithObjectMacro(self, "Invalid input array.");
78 return 0;
79 }
80 if (input_arr->GetNumberOfComponents() != 1)
81 {
82 vtkErrorWithObjectMacro(self, "Input array must have a single component.");
83 return 0;
84 }
85
86 // Distributed input array
87 typedef vtkDistributedVertexPropertyMapType<vtkAbstractArray>::type
88 DistributedLabelMap;
89 DistributedLabelMap distrib_input_arr
90 = MakeDistributedVertexPropertyMap(input, vtkAbstractArray::SafeDownCast(input_arr));
91
92 // Create directed or undirected graph
93 MutableGraph* builder = MutableGraph::New();
94
95 // Setup the graph as a distributed graph
96 vtkSmartPointer<vtkPBGLDistributedGraphHelper> output_helper =
97 vtkSmartPointer<vtkPBGLDistributedGraphHelper>::New();
98 builder->SetDistributedGraphHelper(output_helper);
99 int input_rank = process_id(input_helper->GetProcessGroup());
100 int rank = process_id(output_helper->GetProcessGroup());
101
102 // Prepare edge data.
103 // FIXME (DPG): There's a problem with this approach to copying
104 // properties, because the number of vertices in the resulting graph
105 // may differ greatly from the number of vertices in the incoming
106 // graph, and the distribution may also be completely different. So
107 // we can't really safely allocate GetNumberOfComponents elements in
108 // the arrays in the output graph, because a given processor may, in
109 // some cases, end up with more edges than it started with.
110 #if 0
111 vtkDataSetAttributes* in_edata = input->GetEdgeData();
112 vtkDataSetAttributes* out_edata = builder->GetEdgeData();
113 for (int a = 0; a < in_edata->GetNumberOfArrays(); ++a)
114 {
115 vtkAbstractArray* in_arr = in_edata->GetAbstractArray(a);
116 vtkSmartPointer<vtkAbstractArray> arr;
117 arr.TakeReference(vtkAbstractArray::CreateArray(in_arr->GetDataType()));
118 arr->SetName(in_arr->GetName());
119 arr->SetNumberOfComponents(in_arr->GetNumberOfComponents());
120 out_edata->AddArray(arr);
121 }
122 #endif
123
124 // Prepare vertex data.
125 vtkAbstractArray *pedigrees
126 = vtkAbstractArray::CreateArray(input_arr->GetDataType());
127 pedigrees->SetName(input_arr->GetName());
128 builder->GetVertexData()->AddArray(pedigrees);
129 builder->GetVertexData()->SetPedigreeIds(pedigrees);
130
131 // Iterate through input graph, adding a vertex for every new value
132 // TODO: Handle vertex properties?
133 // For now, do not copy any vertex data since there seems to be a bug there
134 vtkSmartPointer<vtkVertexListIterator> verts = vtkSmartPointer<vtkVertexListIterator>::New();
135 input->GetVertices(verts);
136 while (verts->HasNext())
137 {
138 vtkIdType v = verts->Next();
139 vtkIdType ind = input_helper->GetVertexIndex(v);
140 vtkVariant val = input_arr->GetVariantValue(ind);
141 if (val.ToString().length() > 0)
142 {
143 builder->LazyAddVertex(input_arr->GetVariantValue(v));
144 //builder->AddVertex(input_arr->GetVariantValue(v));
145 }
146 }
147 output_helper->Synchronize();
148 cerr << "input number of vertices " << input->GetNumberOfVertices() << endl;
149 cerr << "builder number of vertices " << builder->GetNumberOfVertices() << endl;
150
151 cerr << "adding edges" << endl;
152 // Iterate through input edges, adding new edges
153 vtkSmartPointer<vtkEdgeListIterator> edges
154 = vtkSmartPointer<vtkEdgeListIterator>::New();
155 //vtkSmartPointer<vtkVariantArray> edata
156 // = vtkSmartPointer<vtkVariantArray>::New();
157 //vtkSmartPointer<vtkTable> in_etable
158 // = vtkSmartPointer<vtkTable>::New();
159 //in_etable->SetRowData(in_edata);
160 input->GetEdges(edges);
161 while (edges->HasNext())
162 {
163 vtkEdgeType e = edges->Next();
164 //vtkIdType eid = input_helper->GetEdgeIndex(e.Id);
165 //in_etable->GetRow(eid, edata);
166 vtkVariant source_val = get(distrib_input_arr, e.Source);
167 vtkVariant target_val = get(distrib_input_arr, e.Target);
168 if (source_val.ToString().length() > 0 && target_val.ToString().length() > 0)
169 {
170 builder->LazyAddEdge(source_val, target_val);
171 //builder->LazyAddEdge(source_val, target_val, edata);
172 }
173 }
174 output_helper->Synchronize();
175
176 // Copy into output graph
177 if (!output->CheckedShallowCopy(builder))
178 {
179 vtkErrorWithObjectMacro(self, "Could not copy to output.");
180 return 0;
181 }
182
183 timer->StopTimer();
184 cerr << "vtkPBGLCollapseGraph: " << timer->GetElapsedTime() << endl;
185
186 return 1;
187 }
188
RequestData(vtkInformation * info,vtkInformationVector ** input_vec,vtkInformationVector * output_vec)189 int vtkPBGLCollapseGraph::RequestData(
190 vtkInformation* info,
191 vtkInformationVector** input_vec,
192 vtkInformationVector* output_vec)
193 {
194 vtkGraph* input = vtkGraph::GetData(input_vec[0]);
195 vtkAbstractArray* input_arr = this->GetInputAbstractArrayToProcess(0, input_vec);
196 if (vtkDirectedGraph::SafeDownCast(input))
197 {
198 return vtkPBGLCollapseGraphRequestData<vtkMutableDirectedGraph>(
199 this, input_arr, info, input_vec, output_vec);
200 }
201 return vtkPBGLCollapseGraphRequestData<vtkMutableUndirectedGraph>(
202 this, input_arr, info, input_vec, output_vec);
203 }
204
205 #endif //VTK_LEGACY_REMOVE
206