Salome HOME
Fix initial state of checkboxes in MEDReader
[modules/paravis.git] / src / Plugins / MEDReader / plugin / MEDReaderIO / vtkFileSeriesGroupReader.cxx
1 // Copyright (C) 2022  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "vtkFileSeriesGroupReader.h"
21
22 #include <vtkCollection.h>
23 #include <vtkInformation.h>
24 #include <vtkInformationVector.h>
25 #include <vtkMultiBlockDataSet.h>
26 #include <vtkMultiProcessController.h>
27 #include <vtkObjectFactory.h>
28 #include <vtkSmartPointer.h>
29 #include <vtkStreamingDemandDrivenPipeline.h>
30
31 #include "vtkMEDReader.h"
32
33 #include <vector>
34 #include <string>
35
36 vtkStandardNewMacro(vtkFileSeriesGroupReader);
37
38 //=============================================================================
39 struct vtkFileSeriesGroupReaderInternals
40 {
41   std::vector<std::string> FileNames;
42   vtkNew<vtkCollection> ReaderCollection;
43 };
44
45 //=============================================================================
46 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
47   : Internals(new vtkFileSeriesGroupReaderInternals())
48 {
49   this->SetNumberOfInputPorts(0);
50   this->SetNumberOfOutputPorts(1);
51 }
52
53 //-----------------------------------------------------------------------------
54 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
55
56 //----------------------------------------------------------------------------
57 void vtkFileSeriesGroupReader::AddFileName(const char* name)
58 {
59   // Make sure the reader always has a filename set
60   this->ReaderSetFileName(name);
61
62   this->AddFileNameInternal(name);
63   this->Modified();
64 }
65
66 //----------------------------------------------------------------------------
67 void vtkFileSeriesGroupReader::RemoveAllFileNames()
68 {
69   this->RemoveAllFileNamesInternal();
70   this->Modified();
71 }
72
73 //----------------------------------------------------------------------------
74 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
75 {
76   this->Internals->FileNames.clear();
77 }
78
79 //----------------------------------------------------------------------------
80 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
81 {
82   this->Internals->FileNames.emplace_back(name);
83 }
84
85 //----------------------------------------------------------------------------
86 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
87 {
88   return static_cast<unsigned int>(this->Internals->FileNames.size());
89 }
90
91 //----------------------------------------------------------------------------
92 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
93 {
94   if (idx >= this->Internals->FileNames.size())
95   {
96     return nullptr;
97   }
98   return this->Internals->FileNames[idx].c_str();
99 }
100
101 //----------------------------------------------------------------------------
102 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
103 {
104   if (!this->Reader)
105   {
106     return 0;
107   }
108
109   return this->ReaderCanReadFile(filename);
110 }
111
112 //----------------------------------------------------------------------------
113 int vtkFileSeriesGroupReader::RequestInformation(
114   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
115 {
116   return this->Reader->ProcessRequest(request, inputVector, outputVector);
117 }
118
119 //----------------------------------------------------------------------------
120 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
121   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
122 {
123   auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
124   unsigned int nBlock = this->GetNumberOfFileNames();
125   output->SetNumberOfBlocks(nBlock);
126
127   vtkInformation* info = outputVector->GetInformationObject(0);
128   double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
129
130   vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
131   unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
132   unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
133
134   // Simple case, one file/bloc for n proc
135   if (nBlock == 1)
136   {
137     // Make sure the information is up to date
138     this->ReaderSetFileName(this->GetFileName(0));
139     vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
140     this->Reader->UpdateInformation();
141
142     this->Reader->UpdateTimeStep(time);
143     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
144     output->SetBlock(0, outputReader);
145
146     // Copy the GAUSS_DATA info key
147     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
148     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
149     {
150       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
151     }
152   }
153   // N file/block read by m proc, with n <= m, means 0/1 file/block per proc
154   else if (nBlock <= nProc && iProc < nBlock)
155   {
156     // Distribute in MEDReader only when reading a single file in a single block
157     vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
158
159     // Needed as the MEDReader do not support changing its filename
160     // without reloading everything.
161     this->ReaderSetFileName(this->GetFileName(iProc));
162     vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
163     this->Reader->UpdateInformation();
164
165     this->Reader->UpdateTimeStep(time);
166     vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
167     output->SetBlock(iProc, outputReader);
168
169     // Copy the GAUSS_DATA info key
170     vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
171     if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
172     {
173       info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
174     }
175   }
176   // Multiple files/block per proc
177   else
178   {
179     unsigned int nFiles = nBlock / nProc;
180     unsigned int offFile = iProc * nFiles;
181     unsigned int supFiles = nBlock % nProc;
182
183     // Last proc handle remaining files/block
184     if (iProc + 1 == nProc)
185     {
186       nFiles += supFiles;
187     }
188
189     vtkMEDReader* exposedReader = vtkMEDReader::SafeDownCast(this->Reader);
190     this->Internals->ReaderCollection->RemoveAllItems();
191     for (unsigned int i = 0; i < nFiles; i++)
192     {
193       // Create as many MEDReader as we need to avoid deep copy
194       vtkNew<vtkMEDReader> localReader;
195       this->Internals->ReaderCollection->AddItem(localReader.Get());
196
197       for (int iField = 0; iField < exposedReader->GetNumberOfFieldsTreeArrays(); iField++)
198       {
199         const char* name = exposedReader->GetFieldsTreeArrayName(iField);
200         localReader->SetFieldsStatus(name, exposedReader->GetFieldsTreeArrayStatus(name));
201       }
202       for (int iTimes = 0; iTimes < exposedReader->GetNumberOfTimesFlagsArrays(); iTimes++)
203       {
204         const char* name = exposedReader->GetTimesFlagsArrayName(iTimes);
205         localReader->SetTimesFlagsStatus(name, exposedReader->GetTimesFlagsArrayStatus(name));
206       }
207       localReader->GenerateVectors(exposedReader->GetGenerateVect());
208       localReader->ChangeMode(exposedReader->GetIsStdOrMode());
209       localReader->GhostCellGeneratorCallForPara(exposedReader->GetGCGCP());
210
211       // Configure the localReader for usage with the files
212       localReader->SetFileName(this->GetFileName(i + offFile));
213       localReader->SetDistributeWithMPI(false);
214       localReader->UpdateInformation();
215       localReader->UpdateTimeStep(time);
216
217       vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(localReader->GetOutputDataObject(0))->GetBlock(0);
218       output->SetBlock(i + offFile, outputReader);
219
220       if (i == 0)
221       {
222         // Copy the GAUSS_DATA info key of the first filename
223         vtkInformation* mInfo = localReader->GetOutputInformation(0);
224         if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
225         {
226           info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
227         }
228       }
229     }
230   }
231   return 1;
232 }
233
234 //------------------------------------------------------------------------------
235 int vtkFileSeriesGroupReader::FillOutputPortInformation(
236   int vtkNotUsed(port), vtkInformation* info)
237 {
238   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
239   return 1;
240 }
241
242 //-----------------------------------------------------------------------------
243 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
244 {
245   this->Superclass::PrintSelf(os, indent);
246
247   os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")
248      << endl;
249 }