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