POD basis computation using voloctree. This example.
POD basis computation using voloctree. This example
#include <array>
#include <vector>
#if BITPIT_ENABLE_MPI
#include <mpi.h>
#endif
#include "pod.hpp"
#include "pod_voloctree.hpp"
#include "pod_kernel.hpp"
#include "piercedStorage.hpp"
using namespace bitpit;
{
errorField.
vector->fill(std::array<double, 3>{{0.0, 0.0, 0.0}});
errorField.
mask->fill(0.0);
for (long id : listActIds) {
for (std::size_t isf = 0; isf < 2; ++isf) {
double field1s = field1.
scalar->at(
id, isf);
double field2s = field2.
scalar->at(
id, isf);
errorField.
scalar->at(
id, isf) += field1s-field2s;
}
std::array<double,3> field1sv = field1.
vector->at(
id,0);
std::array<double,3> field2sv = field2.
vector->at(
id,0);
errorField.
vector->at(
id, 0) += field1sv-field2sv;
errorField.
mask->at(
id) = 1;
}
return errorField;
}
{
errorField.
vector->fill(std::array<double, 3>{{0.0, 0.0, 0.0}});
errorField.
mask->fill(0.0);
std::vector<double> vec;
if (norm_type == "L2") {
}
else if (norm_type == "Linf") {
}
for (long id : listActIds) {
for (std::size_t isf = 0; isf < 2; ++isf) {
double field1s = field1.
scalar->at(
id, isf);
double field2s = field2.
scalar->at(
id, isf);
errorField.
scalar->at(
id, isf) += (field1s-field2s)/vec[isf];
}
std::array<double,3> field1sv = field1.
vector->at(
id,0);
std::array<double,3> field2sv = field2.
vector->at(
id,0);
errorField.
vector->at(
id, 0) += (field1sv-field2sv)/vec[2];
errorField.
mask->at(
id) = 1;
}
return errorField;
}
{
std::vector<std::array<std::string,3>> vectorNames= pod.
getVectorNames();
int N = scalarNames.size();
for (int i=0; i<N; i++) {
std::cout << "L2 norm of " << field_name << " " << scalarNames[i] << " is "<< vecL2[i] << std::endl;
}
int M = vectorNames.size();
for (int i=N; i<N+M; i++) {
std::cout << "L2 norm of " << field_name << " " << vectorNames[i-N][0].substr(0,vectorNames[i-N][0].size()-2) << " is "<< vecL2[i] << std::endl;
}
}
{
std::vector<double> vecLinf = pod.
fieldsMax(field);
std::vector<std::array<std::string,3>> vectorNames= pod.
getVectorNames();
int N = scalarNames.size();
for (int i=0; i<N; i++) {
std::cout << "L infinity norm of " << field_name << " " << scalarNames[i] << " is "<< vecLinf[i] << std::endl;
}
int M = vectorNames.size();
for (int i=N; i<N+M; i++) {
std::cout << "L infinity norm of " << field_name << " " << vectorNames[i-N][0].substr(0,vectorNames[i-N][0].size()-2) << " is "<< vecLinf[i] << std::endl;
}
}
void printMat (std::vector<std::vector<double>> mat)
{
std::cout << "mat = " << std::endl;
size_t M = mat.size();
size_t N = mat[0].size();
for (size_t i=0; i<M; i++) {
for (size_t j=0; j<N; j++) {
if (j == 0) {
std::cout << "[ "<< mat[i][j] ;
}
else if (j==(N-1)) {
std::cout << " , " << mat[i][j] << " ]" << std::endl;
}
else {
std::cout << " , " << mat[i][j] ;
}
if (N==1) {
std::cout << " ]" << std::endl;
}
}
}
}
void run()
{
for (int i=0; i<6; i++) {
pod.
addSnapshot(
"./data",
"test_set2."+std::to_string(i));
}
pod.
write(solution0,
"solution0");
std::vector<std::vector<double>> recostructionCoeffs = pod.
projectField(solution0);
std::cout << "POD coefficients of the first snapshot " << std::endl;
printMat(recostructionCoeffs);
pod.
write(recon0,
"reconstruction0");
pod::PODField error0 = buildErrorField(solution0, recon0, listActIds);
pod::PODField error0relL2 = buildRelErrorField(solution0, recon0, pod,
"L2");
pod::PODField error0relLinf = buildRelErrorField(solution0, recon0, pod,
"Linf");
printL2norm(solution0,pod,"solution");
printLinfnorm(solution0,pod,"solution");
printL2norm(error0,pod,"reconstruction error");
printLinfnorm(error0,pod,"reconstruction error");
printL2norm(error0relL2,pod,"relative error");
printLinfnorm(error0relLinf,pod,"relative error");
std::cout <<
"the number of modes of pod 2 is " << pod2.
getModeCount() << std::endl;
std::cout <<
"the number of modes of pod is " << pod.
getModeCount() << std::endl;
const std::vector<pod::PODMode> &vec_pod_modes = pod2.
getModes();
std::cout << "Number of active cells for pod2 object = ";
std::cout << listActIds_2.size() << std::endl;
std::cout << "Number of active cells for pod object = ";
std::cout << listActIds.size() << std::endl;
double coeff11 = recostructionCoeffs[0][0];
double coeff12 = recostructionCoeffs[0][1];
double coeff21 = recostructionCoeffs[1][0];
double coeff22 = recostructionCoeffs[1][1];
double coeff31 = recostructionCoeffs[2][0];
double coeff32 = recostructionCoeffs[2][1];
double scalar1_diff = 0;
double scalar2_diff = 0;
double vector1_diff = 0;
for (long id : listActIds_2) {
double mode1 = vec_pod_modes[0].scalar->at(id, 0);
double mode2 = vec_pod_modes[1].scalar->at(id, 0);
scalar1_diff += coeff11*mode1+coeff12*mode2-recon0.
scalar->at(
id, 0);
mode1 = vec_pod_modes[0].scalar->at(id, 1);
mode2 = vec_pod_modes[1].scalar->at(id, 1);
scalar2_diff += coeff21*mode1+coeff22*mode2-recon0.
scalar->at(
id, 1);
std::array<double,3> mode1v = vec_pod_modes[0].vector->at(id, 0);
std::array<double,3> mode2v = vec_pod_modes[1].vector->at(id, 0);
std::array<double,3> diffv = recon0.
vector->at(
id, 0);
diffv -= coeff31*mode1v+coeff32*mode2v;
vector1_diff += std::sqrt(
dotProduct((diffv),(diffv)));
}
std::cout << " " << std::endl;
std::cout << "The absolute error between the reconstruction and the linear combination of the restored modes is " << std::endl;
std::cout << scalar1_diff << " for the first scalar field, " << std::endl;
std::cout << scalar2_diff << " for the second scalar field, "<< std::endl;
std::cout << vector1_diff << " for the first vector field. "<< std::endl;
}
int main(int argc, char *argv[])
{
#if BITPIT_ENABLE_MPI
MPI_Init(&argc,&argv);
#endif
try {
run();
} catch (const std::exception &exception) {
log::cout() << exception.what();
exit(1);
}
#if BITPIT_ENABLE_MPI
MPI_Finalize();
#endif
}
The POD (Proper Orthogonal Decomposition) class provides an interface for defining POD object.
std::size_t getModeCount()
std::vector< std::array< std::string, 3 > > getVectorNames()
const std::vector< pod::PODMode > & getModes()
std::vector< double > fieldsMax(pod::PODField &snap)
std::vector< std::string > getScalarNames()
const std::unordered_set< long int > & getListActiveIDs()
void setMeshType(MeshType type)
void setStaticMesh(bool flag)
std::vector< double > fieldsl2norm(pod::PODField &snap)
void setMemoryMode(MemoryMode mode)
void write(const pod::PODField &snap, std::string file_name) const
void setDirectory(const std::string &directory)
void readSnapshot(const pod::SnapshotFile &snap, pod::PODField &fieldr)
void reconstructFields(pod::PODField &field, pod::PODField &recon)
void setUseMean(bool flag)
std::vector< std::vector< double > > projectField(pod::PODField &field)
void setWriteMode(WriteMode mode)
void setEnergyLevel(double energy)
void setName(const std::string &name)
void setErrorMode(ErrorMode mode)
void addSnapshot(const std::string &directory, const std::string &name)
PiercedVector< Cell > & getCells()
T dotProduct(const std::array< T, d > &x, const std::array< T, d > &y)
The PODfield structure is used to store the fields inside POD classes.
std::unique_ptr< pod::ScalarStorage > scalar
std::unique_ptr< PiercedStorage< bool > > mask
std::unique_ptr< pod::VectorStorage > vector
void setMesh(VolumeKernel *lmesh)
The SnapFile structure is used to store the file names inside POD classes.