OpenLB 1.8.1
Loading...
Searching...
No Matches
olb::uq Namespace Reference

Namespaces

namespace  MatrixOperations
 
namespace  Polynomials
 
namespace  Quadrature
 

Classes

struct  Distribution
 
struct  FieldGeometryInfo
 
class  GeneralizedPolynomialChaos
 
class  LatinHypercubeSampling
 
class  MonteCarlo
 
class  QuasiMonteCarlo
 
class  UncertaintyQuantification
 

Enumerations

enum class  DistributionType { Uniform , Normal }
 
enum class  GeneratorType { Sobol , Halton }
 
enum class  UQMethod { GPC , MonteCarlo , QuasiMonteCarlo , LatinHypercubeSampling }
 

Functions

template<typename T >
Distribution< T > uniform (T min, T max)
 
template<typename T >
Distribution< T > normal (T mean, T stddev)
 
template<typename T >
std::vector< Distribution< T > > joint (const std::vector< Distribution< T > > &dists)
 
template<typename T >
affine (T x, const Distribution< T > &dist)
 
template<typename T , typename DESCRIPTOR >
void readData (int samples_number, const std::string &uqFolder, const std::string &name, const std::string &dataName, const std::vector< std::size_t > &iT, std::size_t rank, std::vector< std::vector< std::vector< T > > > &data, FieldGeometryInfo< DESCRIPTOR::d, T > &info)
 Read data from multiple samples' .vti files into a 4D vector.
 
template<typename T , unsigned D>
void computeMeanAndStd (UncertaintyQuantification< T > &uq, const std::vector< std::vector< std::vector< T > > > &data, const FieldGeometryInfo< D, T > &info, BlockData< D, T, T > &blockDataMean, BlockData< D, T, T > &blockDataStd)
 Compute mean and std dev for each lattice node across samples.
 
template<typename T , typename DESCRIPTOR >
void computeMeanAndStdAndWriteVTI (UncertaintyQuantification< T > &uq, const std::string &uqFolder, const std::string &name, const std::string &dataName, CuboidDecomposition< T, DESCRIPTOR::d > &cuboidDecomposition, SuperGeometry< T, DESCRIPTOR::d > &sGeometry)
 Compute mean, std dev, and write them out to VTI for postprocessing.
 

Enumeration Type Documentation

◆ DistributionType

enum class olb::uq::DistributionType
strong
Enumerator
Uniform 
Normal 

Definition at line 35 of file distribution.h.

35 {
36 Uniform,
37 Normal,
38 // MultivariateNormal
39};

◆ GeneratorType

enum class olb::uq::GeneratorType
strong
Enumerator
Sobol 
Halton 

Definition at line 39 of file quasiMonteCarlo.h.

◆ UQMethod

enum class olb::uq::UQMethod
strong
Enumerator
GPC 
MonteCarlo 
QuasiMonteCarlo 
LatinHypercubeSampling 

Definition at line 49 of file uncertaintyQuantification.h.

Function Documentation

◆ affine()

template<typename T >
T olb::uq::affine ( T x,
const Distribution< T > & dist )

Definition at line 80 of file distribution.h.

81{
82 switch (dist.type) {
83 case DistributionType::Uniform:
84 return 0.5 * (dist.param2 - dist.param1) * x + 0.5 * (dist.param1 + dist.param2);
85 case DistributionType::Normal:
86 return dist.param1 + dist.param2 * x;
87 default:
88 throw std::runtime_error("Unsupported distribution type for affine transformation.");
89 }
90}
DistributionType type

References Normal, olb::uq::Distribution< T >::param1, olb::uq::Distribution< T >::param2, olb::uq::Distribution< T >::type, and Uniform.

+ Here is the caller graph for this function:

◆ computeMeanAndStd()

template<typename T , unsigned D>
void olb::uq::computeMeanAndStd ( UncertaintyQuantification< T > & uq,
const std::vector< std::vector< std::vector< T > > > & data,
const FieldGeometryInfo< D, T > & info,
BlockData< D, T, T > & blockDataMean,
BlockData< D, T, T > & blockDataStd )

Compute mean and std dev for each lattice node across samples.

Definition at line 126 of file postprocessing.h.

130{
131 if constexpr (D == 2) {
132 for (int iy = 0; iy < info.dims[1]; ++iy) {
133 for (int ix = 0; ix < info.dims[0]; ++ix) {
134 int nodeIndex = ix + info.dims[0] * iy;
135 // std::array<int, 2> coords = {ix, iy};
136
137 for (unsigned iSize = 0; iSize < info.size; ++iSize) {
138 const auto& samples = data[nodeIndex][iSize];
139 blockDataMean.get({ix, iy}, iSize) = uq.mean(samples);
140 blockDataStd.get({ix, iy}, iSize) = uq.std(samples);
141 }
142 }
143 }
144 }
145 else if constexpr (D == 3) {
146 for (int iz = 0; iz < info.dims[2]; ++iz) {
147 for (int iy = 0; iy < info.dims[1]; ++iy) {
148 for (int ix = 0; ix < info.dims[0]; ++ix) {
149 int nodeIndex = ix + info.dims[0] * (iy + info.dims[1] * iz);
150 // std::array<int, 3> coords = {ix, iy, iz};
151
152 for (unsigned iSize = 0; iSize < info.size; ++iSize) {
153 const auto& samples = data[nodeIndex][iSize];
154 blockDataMean.get({ix, iy, iz}, iSize) = uq.mean(samples);
155 blockDataStd.get({ix, iy, iz}, iSize) = uq.std(samples);
156 }
157 }
158 }
159 }
160 }
161}
U & get(std::size_t iCell, int iD=0)
Definition blockData.hh:94
T mean(const std::vector< T > &samples)
T std(const std::vector< T > &samples)
std::array< int, D > dims

References olb::uq::FieldGeometryInfo< D, T >::dims, olb::BlockData< D, T, U >::get(), olb::uq::UncertaintyQuantification< T >::mean(), olb::uq::FieldGeometryInfo< D, T >::size, and olb::uq::UncertaintyQuantification< T >::std().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ computeMeanAndStdAndWriteVTI()

template<typename T , typename DESCRIPTOR >
void olb::uq::computeMeanAndStdAndWriteVTI ( UncertaintyQuantification< T > & uq,
const std::string & uqFolder,
const std::string & name,
const std::string & dataName,
CuboidDecomposition< T, DESCRIPTOR::d > & cuboidDecomposition,
SuperGeometry< T, DESCRIPTOR::d > & sGeometry )

Compute mean, std dev, and write them out to VTI for postprocessing.

Definition at line 167 of file postprocessing.h.

171{
172 constexpr unsigned D = DESCRIPTOR::d;
173
174 OstreamManager clout(std::cout, "computeMeanAndStdAndWriteVTI");
175
176 // Build a super lattice for reading/writing the final data
177 SuperLattice<T, DESCRIPTOR> sLattice(sGeometry);
178 sLattice.template defineDynamics<NoDynamics>(sGeometry, /*material=*/0);
179 sLattice.initialize();
180
181 // Load iteration logs for each sample
182 std::vector<std::vector<size_t>> iTList(uq.getSamplesNumber());
183 size_t numIterations = std::numeric_limits<size_t>::max();
184
185 for (size_t n = 0; n < uq.getSamplesNumber(); ++n) {
186 std::string filePath = uqFolder + std::to_string(n) + "/tmp/iteration_log.txt";
187 std::ifstream inFile(filePath);
188 if (inFile.is_open()) {
189 size_t iVal;
190 while (inFile >> iVal) {
191 iTList[n].push_back(iVal);
192 }
193 inFile.close();
194 numIterations = std::min(numIterations, iTList[n].size());
195 }
196 else {
197 clout << "Could not open file: " << filePath << std::endl;
198 }
199 }
200
201 SuperVTMwriter<T, D> vtmWriter(name);
202
203#ifdef PARALLEL_MODE_MPI
204 const int noOfCuboids = singleton::mpi().getSize();
205#else
206 const int noOfCuboids = 1;
207#endif
208
209 // Rename materials for visualization
210 for (int rank = 0; rank < noOfCuboids; ++rank) {
211 Cuboid<T, D>& cuboid = cuboidDecomposition.get(rank);
212 Vector<T, D> origin = cuboid.getOrigin();
213 origin[0] -= cuboid.getDeltaR();
214 origin[1] -= cuboid.getDeltaR();
215 if constexpr (DESCRIPTOR::d == 3) {
216 origin[2] -= cuboid.getDeltaR();
217 }
218
219 Vector<T, D> extent = cuboid.getExtent() * cuboid.getDeltaR();
220 extent[0] += cuboid.getDeltaR();
221 extent[1] += cuboid.getDeltaR();
222 if constexpr (DESCRIPTOR::d == 3) {
223 extent[2] += cuboid.getDeltaR();
224 }
225
226 IndicatorCuboid<T, D> readCuboid(extent, origin);
227 sGeometry.rename(/*fromMaterial=*/0, /*toMaterial=*/10 + rank, readCuboid);
228 }
229
230 // Process each iteration
231 singleton::directories().setOutputDir("./tmp/");
232 SuperLatticeCuboid<T, DESCRIPTOR> cuboid(sLattice);
233 SuperLatticeRank<T, DESCRIPTOR> rankFunctor(sLattice);
234
235 vtmWriter.write(cuboid);
236 vtmWriter.write(rankFunctor);
237 vtmWriter.createMasterFile();
238
239 for (size_t iter = 0; iter < numIterations; ++iter) {
240 // Collect the iteration index from each sample
241 std::vector<size_t> iT;
242 iT.reserve(iTList.size());
243 for (const auto& list : iTList) {
244 iT.push_back(list[iter]);
245 }
246
247 clout << "Processing iteration " << iT[0] << std::endl;
248
249 // Process data for each cuboid/rank
250 for (int rank = 0; rank < noOfCuboids; ++rank) {
251 std::string basePath = uqFolder + "0/tmp/";
252 singleton::directories().setOutputDir(basePath);
253
254 std::string fileName =
255 singleton::directories().getVtkOutDir() + "data/" + createFileName(name, iT[0], rank) + ".vti";
256
257 // We'll read the block data from the 0th sample's file,
258 // then overwrite it with the mean/std from all samples.
259 BlockVTIreader<T, T, D> readerMean(fileName, dataName);
260 BlockVTIreader<T, T, D> readerStd(fileName, dataName);
261
262 BlockData<D, T, T>& blockDataMean = readerMean.getBlockData();
263 BlockData<D, T, T>& blockDataStd = readerStd.getBlockData();
264
265 // Gather all samples' data
266 std::vector<std::vector<std::vector<T>>> data;
267 FieldGeometryInfo<D, T> info;
268
269 readData<T, DESCRIPTOR>(uq.getSamplesNumber(), uqFolder, name, dataName, iT, rank, data, info);
270
271 // Overwrite blockDataMean, blockDataStd with computed mean, std
272 computeMeanAndStd<T, D>(uq, data, info, blockDataMean, blockDataStd);
273
274 // Create AnalyticalF2D wrappers to map blockData -> a lattice function
275 BlockDataF<T, T, D> blockDataFMean(blockDataMean);
276 BlockDataF<T, T, D> blockDataFStd(blockDataStd);
277
278 SpecialAnalyticalFfromBlockF<T, T, D> meanField(blockDataFMean, cuboidDecomposition.get(rank), info.spacing,
279 /*scale=*/1.0);
280 SpecialAnalyticalFfromBlockF<T, T, D> stdField(blockDataFStd, cuboidDecomposition.get(rank), info.spacing,
281 /*scale=*/1.0);
282
283 // Define the newly computed fields on the lattice
284 auto materialIndicator = sGeometry.getMaterialIndicator({10 + rank});
285 for (int iBalancer = 0; iBalancer < sGeometry.getLoadBalancer().size(); ++iBalancer) {
286 sLattice.getBlock(iBalancer).template defineField<descriptors::VELOCITY>(
287 materialIndicator->getBlockIndicatorF(iBalancer), meanField);
288 sLattice.getBlock(iBalancer).template defineField<descriptors::VELOCITY2>(
289 materialIndicator->getBlockIndicatorF(iBalancer), stdField);
290 }
291 }
292
293 // Write data to VTM file
294 SuperLatticePhysField<T, DESCRIPTOR, descriptors::VELOCITY> meanPhysField(sLattice,
295 /*scale=*/1.0, dataName + "Mean");
296 vtmWriter.addFunctor(meanPhysField);
297
298 SuperLatticePhysField<T, DESCRIPTOR, descriptors::VELOCITY2> stdPhysField(sLattice,
299 /*scale=*/1.0, dataName + "Std");
300 vtmWriter.addFunctor(stdPhysField);
301
302 // Finally, write the iteration data
303 singleton::directories().setOutputDir("./tmp/");
304 vtmWriter.write(iT[0]);
305 } // end for (iter)
306}
const Cuboid< T, D > & get(int iC) const
Read access to a single cuboid.
class for marking output with some text
void rename(int fromM, int toM)
replace one material with another
std::unique_ptr< SuperIndicatorF< T, D > > getMaterialIndicator(std::vector< int > &&materials)
Returns a material indicator using the given vector of materials.
Super class maintaining block lattices for a cuboid decomposition.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
std::string createFileName(std::string name)
for .pvd masterFile
Definition fileName.hh:34

References computeMeanAndStd(), olb::createFileName(), olb::singleton::directories(), olb::CuboidDecomposition< T, D >::get(), olb::SuperLattice< T, DESCRIPTOR >::getBlock(), olb::Cuboid< T, D >::getDeltaR(), olb::Cuboid< T, D >::getExtent(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::SuperGeometry< T, D >::getMaterialIndicator(), olb::Cuboid< T, D >::getOrigin(), olb::uq::UncertaintyQuantification< T >::getSamplesNumber(), olb::singleton::MpiManager::getSize(), olb::singleton::Directories::getVtkOutDir(), olb::SuperLattice< T, DESCRIPTOR >::initialize(), olb::singleton::mpi(), readData(), olb::SuperGeometry< T, D >::rename(), olb::singleton::Directories::setOutputDir(), and olb::uq::FieldGeometryInfo< D, T >::spacing.

+ Here is the call graph for this function:

◆ joint()

template<typename T >
std::vector< Distribution< T > > olb::uq::joint ( const std::vector< Distribution< T > > & dists)
inline

Definition at line 73 of file distribution.h.

74{
75 return dists;
76}

◆ normal()

template<typename T >
Distribution< T > olb::uq::normal ( T mean,
T stddev )
inline

Definition at line 66 of file distribution.h.

67{
68 return Distribution(DistributionType::Normal, mean, stddev);
69}

References Normal.

◆ readData()

template<typename T , typename DESCRIPTOR >
void olb::uq::readData ( int samples_number,
const std::string & uqFolder,
const std::string & name,
const std::string & dataName,
const std::vector< std::size_t > & iT,
std::size_t rank,
std::vector< std::vector< std::vector< T > > > & data,
FieldGeometryInfo< DESCRIPTOR::d, T > & info )

Read data from multiple samples' .vti files into a 4D vector.

Definition at line 47 of file postprocessing.h.

50{
51 // Read the first sample's VTI file to get geometry information
52 std::string basePath = uqFolder + "0/tmp/";
53 singleton::directories().setOutputDir(basePath);
54
55 std::string fileName = singleton::directories().getVtkOutDir() + "data/" + createFileName(name, iT[0], rank) + ".vti";
56
57 BlockVTIreader<T, T, DESCRIPTOR::d> reader0(fileName, dataName);
58 BlockData<DESCRIPTOR::d, T, T>& blockDataSample0 = reader0.getBlockData();
59
60 // Read spacing from VTI file via XML
61 XMLreader xmlConfig(fileName);
62 std::stringstream spacingStream(xmlConfig["ImageData"].getAttribute("Spacing"));
63
64 for (int i = 0; i < DESCRIPTOR::d; ++i) {
65 spacingStream >> info.spacing[i];
66 }
67
68 info.dims[0] = blockDataSample0.getNx();
69 info.dims[1] = blockDataSample0.getNy();
70 if constexpr (DESCRIPTOR::d == 3) {
71 info.dims[2] = blockDataSample0.getNz();
72 }
73 info.nodeCount = std::accumulate(info.dims.begin(), info.dims.end(), 1, std::multiplies<> {});
74
75 info.size = blockDataSample0.getSize();
76
77 // Initialize data vector: data[nx*ny][size][samples_number] or data[nx*ny*nz][size][samples_number]
78 // data[nodeIndex][iSize][iSample]
79 data.assign(info.nodeCount, std::vector<std::vector<T>>(info.size, std::vector<T>(samples_number)));
80
81 // Read data from each sample's .vti
82 for (int iSample = 0; iSample < samples_number; ++iSample) {
83 std::string samplePath = uqFolder + std::to_string(iSample) + "/tmp/";
84 singleton::directories().setOutputDir(samplePath);
85
86 std::string sampleFileName =
87 singleton::directories().getVtkOutDir() + "data/" + createFileName(name, iT[iSample], rank) + ".vti";
88
89 BlockVTIreader<T, T, DESCRIPTOR::d> reader(sampleFileName, dataName);
90 BlockData<DESCRIPTOR::d, T, T>& blockDataSample = reader.getBlockData();
91
92 // Extract data for each lattice point
93 if constexpr (DESCRIPTOR::d == 2) {
94 for (int iy = 0; iy < info.dims[1]; ++iy) {
95 for (int ix = 0; ix < info.dims[0]; ++ix) {
96 int nodeIndex = ix + info.dims[0] * iy;
97 // std::array<int, 2> coords = {ix, iy};
98
99 for (unsigned iSize = 0; iSize < info.size; ++iSize) {
100 data[nodeIndex][iSize][iSample] = blockDataSample.get({ix, iy}, iSize);
101 }
102 }
103 }
104 }
105 else if constexpr (DESCRIPTOR::d == 3) {
106 for (int iz = 0; iz < info.dims[2]; ++iz) {
107 for (int iy = 0; iy < info.dims[1]; ++iy) {
108 for (int ix = 0; ix < info.dims[0]; ++ix) {
109 int nodeIndex = ix + info.dims[0] * (iy + info.dims[1] * iz);
110 // std::array<int, 3> coords = {ix, iy, iz};
111
112 for (unsigned iSize = 0; iSize < info.size; ++iSize) {
113 data[nodeIndex][iSize][iSample] = blockDataSample.get({ix, iy, iz}, iSize);
114 }
115 }
116 }
117 }
118 }
119 }
120}
unsigned getSize() const
Definition blockData.hh:118
int getNy() const
Read only access to block height.
int getNx() const
Read only access to block width.
int getNz() const
Read only access to block height.
std::conditional_t< D==2, BlockVTIreader2D< T, BaseType >, BlockVTIreader3D< T, BaseType > > BlockVTIreader
Definition aliases.h:381

References olb::createFileName(), olb::uq::FieldGeometryInfo< D, T >::dims, olb::singleton::directories(), olb::BlockData< D, T, U >::get(), olb::BlockStructureD< D >::getNx(), olb::BlockStructureD< D >::getNy(), olb::BlockStructureD< D >::getNz(), olb::BlockData< D, T, U >::getSize(), olb::singleton::Directories::getVtkOutDir(), olb::uq::FieldGeometryInfo< D, T >::nodeCount, olb::singleton::Directories::setOutputDir(), olb::uq::FieldGeometryInfo< D, T >::size, and olb::uq::FieldGeometryInfo< D, T >::spacing.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ uniform()

template<typename T >
Distribution< T > olb::uq::uniform ( T min,
T max )
inline

Definition at line 60 of file distribution.h.

61{
62 return Distribution(DistributionType::Uniform, min, max);
63}

References Uniform.