Salome HOME
Full rework of distributed logic
[modules/paravis.git] / src / Plugins / MEDReader / plugin / MEDReaderIO / vtkFileSeriesGroupReader.cxx
1 #include "vtkFileSeriesGroupReader.h"
2
3 #include <vtkInformation.h>
4 #include <vtkInformationVector.h>
5 #include <vtkMultiBlockDataSet.h>
6 #include <vtkMultiProcessController.h>
7 #include <vtkObjectFactory.h>
8 #include <vtkSmartPointer.h>
9 #include <vtkStreamingDemandDrivenPipeline.h>
10
11 #include "vtkMEDReader.h"
12
13 #include <vector>
14 #include <string>
15
16 vtkStandardNewMacro(vtkFileSeriesGroupReader);
17
18 //=============================================================================
19 struct vtkFileSeriesGroupReaderInternals
20 {
21   std::vector<std::string> FileNames;
22 };
23
24 //=============================================================================
25 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
26   : Internals(new vtkFileSeriesGroupReaderInternals())
27 {
28   this->SetNumberOfInputPorts(0);
29   this->SetNumberOfOutputPorts(1);
30 }
31
32 //-----------------------------------------------------------------------------
33 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
34
35 //----------------------------------------------------------------------------
36 void vtkFileSeriesGroupReader::AddFileName(const char* name)
37 {
38   // Make sure the reader always has a filename set
39   this->ReaderSetFileName(name);
40
41   this->AddFileNameInternal(name);
42   this->Modified();
43 }
44
45 //----------------------------------------------------------------------------
46 void vtkFileSeriesGroupReader::RemoveAllFileNames()
47 {
48   this->RemoveAllFileNamesInternal();
49   this->Modified();
50 }
51
52 //----------------------------------------------------------------------------
53 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
54 {
55   this->Internals->FileNames.clear();
56 }
57
58 //----------------------------------------------------------------------------
59 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
60 {
61   this->Internals->FileNames.emplace_back(name);
62 }
63
64 //----------------------------------------------------------------------------
65 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
66 {
67   return static_cast<unsigned int>(this->Internals->FileNames.size());
68 }
69
70 //----------------------------------------------------------------------------
71 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
72 {
73   if (idx >= this->Internals->FileNames.size())
74   {
75     return nullptr;
76   }
77   return this->Internals->FileNames[idx].c_str();
78 }
79
80 //----------------------------------------------------------------------------
81 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
82 {
83   if (!this->Reader)
84   {
85     return 0;
86   }
87
88   return this->ReaderCanReadFile(filename);
89 }
90
91 //----------------------------------------------------------------------------
92 int vtkFileSeriesGroupReader::RequestInformation(
93   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
94 {
95   return this->Reader->ProcessRequest(request, inputVector, outputVector);
96 }
97
98 //----------------------------------------------------------------------------
99 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
100   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
101 {
102   auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
103   unsigned int nBlock = this->GetNumberOfFileNames();
104   output->SetNumberOfBlocks(nBlock);
105
106   vtkInformation* info = outputVector->GetInformationObject(0);
107   double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
108
109   vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
110   unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
111   unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
112
113   // Simple case, one file/bloc for n proc
114   if (nBlock == 1)
115   {
116     // No need to set the FileName, already set by the subproxy mechanism
117     this->Reader->UpdateTimeStep(time);
118     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
119     output->SetBlock(0, outputReader);
120   }
121   // N file/block read by m proc, with n <= m, means 0/1 file/block per proc
122   else if (nBlock <= nProc && iProc < nBlock)
123   {
124     // Distribute in MEDReader only when reading a single file in a single block
125     vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
126
127     // Needed as the MEDReader do not support changing its filename
128     // without reloading everything.
129     this->ReaderSetFileName(this->GetFileName(iProc));
130     vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
131     this->Reader->UpdateInformation();
132
133     this->Reader->UpdateTimeStep(time);
134     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
135     output->SetBlock(iProc, outputReader);
136   }
137   // Multiple files/block per proc
138   else
139   {
140     unsigned int nFiles = nBlock / nProc;
141     unsigned int offFile = iProc * nFiles;
142     unsigned int supFiles = nBlock % nProc;
143
144     // Last proc handle remaining files/block
145     if (iProc + 1 == nProc)
146     {
147       nFiles += supFiles;
148     }
149
150     for (unsigned int i = 0; i < nFiles; i++)
151     {
152       this->ReaderSetFileName(this->GetFileName(i + offFile));
153       vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
154       vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
155       this->Reader->UpdateInformation();
156       this->Reader->UpdateTimeStep(time);
157       vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
158       if (i + 1 == nFiles)
159       {
160         // Last reader, just use the reader output directly
161         output->SetBlock(i + offFile, outputReader);
162       }
163       else
164       {
165         // Need to deep copy as the reader will be reused
166         vtkSmartPointer<vtkDataObject> outputLeaf = vtkSmartPointer<vtkDataObject>::Take(outputReader->NewInstance());
167         outputLeaf->DeepCopy(outputReader);
168         output->SetBlock(i + offFile, outputLeaf);
169       }
170     }
171   }
172   return 1;
173 }
174
175 //------------------------------------------------------------------------------
176 int vtkFileSeriesGroupReader::FillOutputPortInformation(
177   int vtkNotUsed(port), vtkInformation* info)
178 {
179   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
180   return 1;
181 }
182
183 //-----------------------------------------------------------------------------
184 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
185 {
186   this->Superclass::PrintSelf(os, indent);
187
188   os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")
189      << endl;
190 }