PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Parallel/vtkPChacoReader.cxx

https://github.com/b3c/VTK-5.8
C++ | 580 lines | 426 code | 113 blank | 41 comment | 69 complexity | ef86a4148133a27d78fb7ad88d396f12 MD5 | raw file
  1. /*=========================================================================
  2. Program: Visualization Toolkit
  3. Module: vtkPChacoReader.cxx
  4. Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  5. All rights reserved.
  6. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even
  8. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  9. PURPOSE. See the above copyright notice for more information.
  10. =========================================================================*/
  11. /*----------------------------------------------------------------------------
  12. Copyright (c) Sandia Corporation
  13. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
  14. ----------------------------------------------------------------------------*/
  15. #include "vtkToolkits.h"
  16. #include "vtkPChacoReader.h"
  17. #include "vtkDataSetWriter.h"
  18. #include "vtkDataSetReader.h"
  19. #include "vtkExtractCells.h"
  20. #include "vtkPKdTree.h"
  21. #include "vtkObjectFactory.h"
  22. #include "vtkUnstructuredGrid.h"
  23. #include "vtkDoubleArray.h"
  24. #include "vtkCharArray.h"
  25. #include "vtkIntArray.h"
  26. #include "vtkInformation.h"
  27. #include "vtkInformationVector.h"
  28. #include "vtkIntArray.h"
  29. #include "vtkPointData.h"
  30. #include "vtkCellData.h"
  31. #include "vtkMultiProcessController.h"
  32. #include "vtkStreamingDemandDrivenPipeline.h"
  33. #include "vtkProcessGroup.h"
  34. vtkStandardNewMacro(vtkPChacoReader);
  35. //----------------------------------------------------------------------------
  36. vtkPChacoReader::vtkPChacoReader()
  37. {
  38. this->Controller = NULL;
  39. this->SetController(vtkMultiProcessController::GetGlobalController());
  40. }
  41. //----------------------------------------------------------------------------
  42. vtkPChacoReader::~vtkPChacoReader()
  43. {
  44. this->SetController(NULL);
  45. }
  46. //----------------------------------------------------------------------------
  47. void vtkPChacoReader::SetController(vtkMultiProcessController *c)
  48. {
  49. if ((c == NULL) || (c->GetNumberOfProcesses() == 0))
  50. {
  51. this->NumProcesses = 1;
  52. this->MyId = 0;
  53. }
  54. if (this->Controller == c)
  55. {
  56. return;
  57. }
  58. this->Modified();
  59. if (this->Controller != NULL)
  60. {
  61. this->Controller->UnRegister(this);
  62. this->Controller = NULL;
  63. }
  64. if (c == NULL)
  65. {
  66. return;
  67. }
  68. this->Controller = c;
  69. c->Register(this);
  70. this->NumProcesses = c->GetNumberOfProcesses();
  71. this->MyId = c->GetLocalProcessId();
  72. }
  73. //----------------------------------------------------------------------------
  74. int vtkPChacoReader::RequestInformation(
  75. vtkInformation *request,
  76. vtkInformationVector **inputVector,
  77. vtkInformationVector *outputVector)
  78. {
  79. if (!this->BaseName)
  80. {
  81. vtkErrorMacro(<< "No BaseName specified");
  82. return 0;
  83. }
  84. // Setting maximum number of pieces to -1 indicates to the
  85. // upstream consumer that I can provide the same number of pieces
  86. // as there are number of processors
  87. // get the info object
  88. vtkInformation *outInfo = outputVector->GetInformationObject(0);
  89. outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
  90. -1);
  91. int retVal = 1;
  92. if (this->MyId == 0)
  93. {
  94. retVal =
  95. this->Superclass::RequestInformation(request, inputVector, outputVector);
  96. }
  97. if (this->NumProcesses == 1)
  98. {
  99. return retVal;
  100. }
  101. unsigned long metadata[8];
  102. if (this->MyId == 0)
  103. {
  104. metadata[0] = static_cast<unsigned long>(retVal);
  105. if (retVal)
  106. {
  107. metadata[1] = static_cast<unsigned long>(this->RemakeDataCacheFlag);
  108. if (this->RemakeDataCacheFlag)
  109. {
  110. metadata[2] = static_cast<unsigned long>(this->Dimensionality);
  111. metadata[3] = static_cast<unsigned long>(this->NumberOfVertices);
  112. metadata[4] = static_cast<unsigned long>(this->NumberOfEdges);
  113. metadata[5] = static_cast<unsigned long>(this->NumberOfVertexWeights);
  114. metadata[6] = static_cast<unsigned long>(this->NumberOfEdgeWeights);
  115. metadata[7] = static_cast<unsigned long>(this->GraphFileHasVertexNumbers);
  116. }
  117. }
  118. }
  119. this->Controller->Broadcast(metadata, 8, 0);
  120. if (this->MyId > 0)
  121. {
  122. retVal = metadata[0];
  123. if (retVal)
  124. {
  125. this->RemakeDataCacheFlag = static_cast<int>(metadata[1]);
  126. if (this->RemakeDataCacheFlag)
  127. {
  128. this->Dimensionality = static_cast<int>(metadata[2]);
  129. this->NumberOfVertices = static_cast<vtkIdType>(metadata[3]);
  130. this->NumberOfEdges = static_cast<vtkIdType>(metadata[4]);
  131. this->NumberOfVertexWeights = static_cast<int>(metadata[5]);
  132. this->NumberOfEdgeWeights = static_cast<int>(metadata[6]);
  133. this->GraphFileHasVertexNumbers = static_cast<int>(metadata[7]);
  134. this->MakeWeightArrayNames(this->NumberOfVertexWeights,
  135. this->NumberOfEdgeWeights);
  136. this->SetCurrentBaseName(this->BaseName);
  137. }
  138. }
  139. }
  140. return retVal;
  141. }
  142. //----------------------------------------------------------------------------
  143. int vtkPChacoReader::RequestData(
  144. vtkInformation *vtkNotUsed(request),
  145. vtkInformationVector **vtkNotUsed(inputVector),
  146. vtkInformationVector *outputVector)
  147. {
  148. if (!this->BaseName)
  149. {
  150. vtkErrorMacro(<< "No BaseName specified");
  151. return 0;
  152. }
  153. vtkInformation* outInfo = outputVector->GetInformationObject(0);
  154. vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
  155. outInfo->Get(vtkDataObject::DATA_OBJECT()));
  156. int piece =
  157. outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  158. int numPieces =
  159. outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
  160. int pieceZeroProc = 0;
  161. vtkMultiProcessController *contr = this->Controller;
  162. int i=0;
  163. int oops = ((piece != this->MyId) || (numPieces != this->NumProcesses));
  164. int sum = 0;
  165. contr->Reduce(&oops, &sum, 1, vtkCommunicator::SUM_OP, 0);
  166. contr->Broadcast(&sum, 1, 0);
  167. if (sum > 0)
  168. {
  169. // I don't know if this situation can occur, but we'll try to handle it.
  170. int *myPiece = new int [this->NumProcesses];
  171. contr->AllGather(&piece, myPiece, 1);
  172. vtkMultiProcessController *subController;
  173. vtkProcessGroup *group = vtkProcessGroup::New();
  174. group->Initialize(contr);
  175. int nparticipants = 0;
  176. for (i=0; i<this->NumProcesses; i++)
  177. {
  178. if ((myPiece[i] >= 0) && (myPiece[i] < numPieces))
  179. {
  180. group->AddProcessId(i);
  181. if (myPiece[i] == 0)
  182. {
  183. pieceZeroProc = nparticipants;
  184. }
  185. nparticipants++;
  186. }
  187. }
  188. delete [] myPiece;
  189. if (nparticipants < numPieces) // Can this happen?
  190. {
  191. group->Delete();
  192. output->Initialize();
  193. vtkErrorMacro("<<vtkPChacoReader can't produce less than entire file");
  194. return 0;
  195. }
  196. subController = contr->CreateSubController(group);
  197. group->Delete();
  198. if (subController)
  199. {
  200. contr = subController;
  201. }
  202. else
  203. {
  204. contr = NULL;
  205. }
  206. }
  207. if ( !contr)
  208. {
  209. // This process doesn't participate (can this happen?)
  210. this->SetUpEmptyGrid(output);
  211. return 1;
  212. }
  213. int retVal = 1;
  214. if (piece == 0)
  215. {
  216. // "piece" 0 reads in the entire mesh
  217. retVal = this->BuildOutputGrid(output);
  218. }
  219. if (numPieces > 1)
  220. {
  221. contr->Broadcast(&retVal, 1, pieceZeroProc);
  222. if (retVal == 1)
  223. {
  224. retVal = this->DivideCells(contr, output, pieceZeroProc);
  225. }
  226. }
  227. if (contr != this->Controller)
  228. {
  229. contr->Delete();
  230. }
  231. return retVal;
  232. }
  233. //----------------------------------------------------------------------------
  234. void vtkPChacoReader::SetUpEmptyGrid(vtkUnstructuredGrid *output)
  235. {
  236. int i;
  237. // Note: The cell and point arrays should be added in the same order in
  238. // which they are added in vtkChacoReader::BuildOutputGrid. See "Note" in
  239. // vtkChacoReader.cxx.
  240. output->Initialize();
  241. if (this->GetGenerateVertexWeightArrays())
  242. {
  243. for (i=0; i < this->NumberOfVertexWeights; i++)
  244. {
  245. vtkDoubleArray *da = vtkDoubleArray::New();
  246. da->SetNumberOfTuples(0);
  247. da->SetNumberOfComponents(1);
  248. da->SetName(this->GetVertexWeightArrayName(i+1));
  249. output->GetPointData()->AddArray(da);
  250. da->Delete();
  251. }
  252. this->NumberOfPointWeightArrays = this->NumberOfVertexWeights;
  253. }
  254. if (this->GetGenerateEdgeWeightArrays())
  255. {
  256. for (i=0; i < this->NumberOfEdgeWeights; i++)
  257. {
  258. vtkDoubleArray *da = vtkDoubleArray::New();
  259. da->SetNumberOfTuples(0);
  260. da->SetNumberOfComponents(1);
  261. da->SetName(this->GetEdgeWeightArrayName(i+1));
  262. output->GetCellData()->AddArray(da);
  263. da->Delete();
  264. }
  265. this->NumberOfCellWeightArrays = this->NumberOfEdgeWeights;
  266. }
  267. if (this->GetGenerateGlobalElementIdArray())
  268. {
  269. vtkIntArray *ia = vtkIntArray::New();
  270. ia->SetNumberOfTuples(0);
  271. ia->SetNumberOfComponents(1);
  272. ia->SetName(this->GetGlobalElementIdArrayName());
  273. output->GetCellData()->AddArray(ia);
  274. }
  275. if (this->GetGenerateGlobalNodeIdArray())
  276. {
  277. vtkIntArray *ia = vtkIntArray::New();
  278. ia->SetNumberOfTuples(0);
  279. ia->SetNumberOfComponents(1);
  280. ia->SetName(this->GetGlobalNodeIdArrayName());
  281. output->GetPointData()->AddArray(ia);
  282. }
  283. }
  284. //----------------------------------------------------------------------------
  285. int vtkPChacoReader::DivideCells(vtkMultiProcessController *contr,
  286. vtkUnstructuredGrid *output, int source)
  287. {
  288. int retVal = 1;
  289. int i=0;
  290. int nprocs = contr->GetNumberOfProcesses();
  291. int myrank = contr->GetLocalProcessId();
  292. vtkUnstructuredGrid *mygrid = NULL;
  293. if (source == myrank)
  294. {
  295. vtkIdType ntotalcells = output->GetNumberOfCells();
  296. vtkIdType nshare = ntotalcells / nprocs;
  297. vtkIdType leftover = ntotalcells - (nprocs * nshare);
  298. vtkIdType startId = 0;
  299. for (i=0; i < nprocs; i++)
  300. {
  301. if (!retVal && (i != myrank))
  302. {
  303. this->SendGrid(contr, i, NULL); // we failed
  304. continue;
  305. }
  306. vtkIdType ncells = ((i < leftover) ? nshare + 1 : nshare);
  307. vtkIdType endId = startId + ncells - 1;
  308. vtkUnstructuredGrid *ug = this->SubGrid(output, startId, endId);
  309. if (i != myrank)
  310. {
  311. retVal = this->SendGrid(contr, i, ug);
  312. ug->Delete();
  313. }
  314. else
  315. {
  316. mygrid = ug;
  317. }
  318. startId += ncells;
  319. }
  320. }
  321. else
  322. {
  323. mygrid = this->GetGrid(contr, source);
  324. if (mygrid == NULL)
  325. {
  326. retVal = 0;
  327. }
  328. }
  329. int vote = 0;
  330. contr->Reduce(&retVal, &vote, 1, vtkCommunicator::SUM_OP, 0);
  331. contr->Broadcast(&vote, 1, 0);
  332. if (vote < nprocs)
  333. {
  334. retVal = 0;
  335. }
  336. output->Initialize();
  337. if (retVal)
  338. {
  339. output->ShallowCopy(mygrid);
  340. }
  341. else if (mygrid)
  342. {
  343. mygrid->Delete();
  344. }
  345. return retVal;
  346. }
  347. int vtkPChacoReader::SendGrid(vtkMultiProcessController *contr,
  348. int to, vtkUnstructuredGrid *grid)
  349. {
  350. int retVal = 1;
  351. int bufsize=0, ack = 0;
  352. if (!grid)
  353. {
  354. // sending notice of a failure
  355. contr->Send(&bufsize, 1, to, 0x11);
  356. return retVal;
  357. }
  358. char *buf = this->MarshallDataSet(grid, bufsize);
  359. contr->Send(&bufsize, 1, to, 0x11);
  360. contr->Receive(&ack, 1, to, 0x12);
  361. if (!ack)
  362. {
  363. retVal = 0;
  364. }
  365. else
  366. {
  367. contr->Send(buf, bufsize, to, 0x13);
  368. }
  369. delete [] buf;
  370. return retVal;
  371. }
  372. vtkUnstructuredGrid *vtkPChacoReader::GetGrid(vtkMultiProcessController *contr,
  373. int from)
  374. {
  375. vtkUnstructuredGrid *grid = NULL;
  376. int bufsize=0, ack=1;
  377. contr->Receive(&bufsize, 1, from, 0x11);
  378. if (bufsize == 0)
  379. {
  380. // Node zero is reporting an error
  381. return NULL;
  382. }
  383. char *buf = new char [bufsize];
  384. if (buf)
  385. {
  386. contr->Send(&ack, 1, from, 0x12);
  387. contr->Receive(buf, bufsize, from, 0x13);
  388. grid = this->UnMarshallDataSet(buf, bufsize);
  389. delete [] buf;
  390. }
  391. else
  392. {
  393. ack = 0;
  394. contr->Send(&ack, 1, 0, 0x12);
  395. }
  396. return grid;
  397. }
  398. vtkUnstructuredGrid *
  399. vtkPChacoReader::SubGrid(vtkUnstructuredGrid *ug, vtkIdType from, vtkIdType to)
  400. {
  401. vtkUnstructuredGrid *tmp = vtkUnstructuredGrid::New();
  402. if (from > to)
  403. {
  404. this->SetUpEmptyGrid(tmp);
  405. }
  406. else
  407. {
  408. tmp->ShallowCopy(ug);
  409. vtkExtractCells *ec = vtkExtractCells::New();
  410. ec->AddCellRange(from, to);
  411. ec->SetInput(tmp);
  412. ec->Update();
  413. tmp->Initialize();
  414. tmp->ShallowCopy(ec->GetOutput());
  415. ec->Delete();
  416. }
  417. return tmp;
  418. }
  419. char *vtkPChacoReader::MarshallDataSet(vtkUnstructuredGrid *extractedGrid, int &len)
  420. {
  421. // taken from vtkCommunicator::WriteDataSet
  422. vtkUnstructuredGrid *copy;
  423. vtkDataSetWriter *writer = vtkDataSetWriter::New();
  424. copy = extractedGrid->NewInstance();
  425. copy->ShallowCopy(extractedGrid);
  426. // There is a problem with binary files with no data.
  427. if (copy->GetNumberOfCells() > 0)
  428. {
  429. writer->SetFileTypeToBinary();
  430. }
  431. writer->WriteToOutputStringOn();
  432. writer->SetInput(copy);
  433. writer->Write();
  434. len = writer->GetOutputStringLength();
  435. char *packedFormat = writer->RegisterAndGetOutputString();
  436. writer->Delete();
  437. copy->Delete();
  438. return packedFormat;
  439. }
  440. vtkUnstructuredGrid *vtkPChacoReader::UnMarshallDataSet(char *buf, int size)
  441. {
  442. // taken from vtkCommunicator::ReadDataSet
  443. vtkDataSetReader *reader = vtkDataSetReader::New();
  444. reader->ReadFromInputStringOn();
  445. vtkCharArray* mystring = vtkCharArray::New();
  446. mystring->SetArray(buf, size, 1);
  447. reader->SetInputArray(mystring);
  448. mystring->Delete();
  449. vtkDataSet *output = reader->GetOutput();
  450. output->Update();
  451. vtkUnstructuredGrid *newGrid = vtkUnstructuredGrid::New();
  452. newGrid->ShallowCopy(output);
  453. reader->Delete();
  454. return newGrid;
  455. }
  456. //----------------------------------------------------------------------------
  457. void vtkPChacoReader::PrintSelf(ostream& os, vtkIndent indent)
  458. {
  459. vtkChacoReader::PrintSelf(os,indent);
  460. os << indent << "MyId: " << this->MyId << endl;
  461. os << indent << "NumProcesses: " << this->NumProcesses << endl;
  462. os << indent << "Controller: " << this->Controller << endl;
  463. }