1 // Copyright (C) 2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "vtkFileSeriesGroupReader.h"
22 #include <vtkInformation.h>
23 #include <vtkInformationVector.h>
24 #include <vtkMultiBlockDataSet.h>
25 #include <vtkMultiProcessController.h>
26 #include <vtkObjectFactory.h>
27 #include <vtkSmartPointer.h>
28 #include <vtkStreamingDemandDrivenPipeline.h>
30 #include "vtkMEDReader.h"
35 vtkStandardNewMacro(vtkFileSeriesGroupReader);
37 //=============================================================================
38 struct vtkFileSeriesGroupReaderInternals
40 std::vector<std::string> FileNames;
43 //=============================================================================
44 vtkFileSeriesGroupReader::vtkFileSeriesGroupReader()
45 : Internals(new vtkFileSeriesGroupReaderInternals())
47 this->SetNumberOfInputPorts(0);
48 this->SetNumberOfOutputPorts(1);
51 //-----------------------------------------------------------------------------
52 vtkFileSeriesGroupReader::~vtkFileSeriesGroupReader() = default;
54 //----------------------------------------------------------------------------
55 void vtkFileSeriesGroupReader::AddFileName(const char* name)
57 // Make sure the reader always has a filename set
58 this->ReaderSetFileName(name);
60 this->AddFileNameInternal(name);
64 //----------------------------------------------------------------------------
65 void vtkFileSeriesGroupReader::RemoveAllFileNames()
67 this->RemoveAllFileNamesInternal();
71 //----------------------------------------------------------------------------
72 void vtkFileSeriesGroupReader::RemoveAllFileNamesInternal()
74 this->Internals->FileNames.clear();
77 //----------------------------------------------------------------------------
78 void vtkFileSeriesGroupReader::AddFileNameInternal(const char* name)
80 this->Internals->FileNames.emplace_back(name);
83 //----------------------------------------------------------------------------
84 unsigned int vtkFileSeriesGroupReader::GetNumberOfFileNames()
86 return static_cast<unsigned int>(this->Internals->FileNames.size());
89 //----------------------------------------------------------------------------
90 const char* vtkFileSeriesGroupReader::GetFileName(unsigned int idx)
92 if (idx >= this->Internals->FileNames.size())
96 return this->Internals->FileNames[idx].c_str();
99 //----------------------------------------------------------------------------
100 int vtkFileSeriesGroupReader::CanReadFile(const char* filename)
107 return this->ReaderCanReadFile(filename);
110 //----------------------------------------------------------------------------
111 int vtkFileSeriesGroupReader::RequestInformation(
112 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
114 return this->Reader->ProcessRequest(request, inputVector, outputVector);
117 //----------------------------------------------------------------------------
118 int vtkFileSeriesGroupReader::RequestData(vtkInformation* vtkNotUsed(request),
119 vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
121 auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
122 unsigned int nBlock = this->GetNumberOfFileNames();
123 output->SetNumberOfBlocks(nBlock);
125 vtkInformation* info = outputVector->GetInformationObject(0);
126 double time = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
128 vtkMultiProcessController *vmpc(vtkMultiProcessController::GetGlobalController());
129 unsigned int iProc = vmpc ? vmpc->GetLocalProcessId() : 0;
130 unsigned int nProc = vmpc ? vmpc->GetNumberOfProcesses() : 1;
132 // Simple case, one file/block per proc
133 if (nBlock == 1 || (nBlock <= nProc && iProc < nBlock))
135 // Distribute in MEDReader only when reading a single file in a single block
136 iProc = nBlock == 1 ? 0 : iProc;
137 vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(nBlock == 1);
139 this->ReaderSetFileName(this->GetFileName(iProc));
141 // Needed only when reading a different file on each proc
144 vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
145 this->Reader->UpdateInformation();
148 this->Reader->UpdateTimeStep(time);
149 vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
150 output->SetBlock(iProc, outputReader);
152 // Copy the GAUSS_DATA info key
153 vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
154 if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
156 info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
161 // Multiple files/block per proc
162 unsigned int nFiles = nBlock / nProc;
163 unsigned int offFile = iProc * nFiles;
164 unsigned int supFiles = nBlock % nProc;
166 // Last proc handle remaining files/block
167 if (iProc + 1 == nProc)
172 for (unsigned int i = 0; i < nFiles; i++)
174 this->ReaderSetFileName(this->GetFileName(i + offFile));
175 vtkMEDReader::SafeDownCast(this->Reader)->SetDistributeWithMPI(false);
176 vtkMEDReader::SafeDownCast(this->Reader)->ReloadInternals();
177 this->Reader->UpdateInformation();
178 this->Reader->UpdateTimeStep(time);
179 vtkDataObject* outputReader = vtkMultiBlockDataSet::SafeDownCast(this->Reader->GetOutputDataObject(0))->GetBlock(0);
182 // Last reader, just use the reader output directly
183 output->SetBlock(i + offFile, outputReader);
187 // Need to deep copy as the reader will be reused
188 vtkSmartPointer<vtkDataObject> outputLeaf = vtkSmartPointer<vtkDataObject>::Take(outputReader->NewInstance());
189 outputLeaf->DeepCopy(outputReader);
190 output->SetBlock(i + offFile, outputLeaf);
194 // Copy the GAUSS_DATA info key for the last reader
195 vtkInformation* mInfo = this->Reader->GetOutputInformation(0);
196 if (mInfo->Has(vtkMEDReader::GAUSS_DATA()))
198 info->CopyEntry(mInfo, vtkMEDReader::GAUSS_DATA());
204 //------------------------------------------------------------------------------
205 int vtkFileSeriesGroupReader::FillOutputPortInformation(
206 int vtkNotUsed(port), vtkInformation* info)
208 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
212 //-----------------------------------------------------------------------------
213 void vtkFileSeriesGroupReader::PrintSelf(ostream& os, vtkIndent indent)
215 this->Superclass::PrintSelf(os, indent);
217 os << indent << "MetaFileName: " << (this->_MetaFileName ? this->_MetaFileName : "(none)")