Exporting data works. However requires specification of what axis is what to differentiate XData and TData.

This commit is contained in:
Anne de Jong 2017-01-29 20:49:08 +01:00
parent c81e17cecc
commit a6a76f65d7
12 changed files with 431 additions and 13 deletions

View File

@ -62,6 +62,8 @@ add_library(tasmet_src
material/solid.cpp material/solid.cpp
material/adiabatictemp.cpp material/adiabatictemp.cpp
export/export.cpp
# sys/enginesystem.cpp # sys/enginesystem.cpp
sys/globalconf.cpp sys/globalconf.cpp
sys/tasmet_variable.cpp sys/tasmet_variable.cpp
@ -73,4 +75,4 @@ add_library(tasmet_src
add_subdirectory(gui) add_subdirectory(gui)
add_subdirectory(protobuf) add_subdirectory(protobuf)
target_link_libraries(tasmet_src Qt5::Widgets superlu dl pthread) target_link_libraries(tasmet_src Qt5::Widgets hdf5 hdf5_hl dl superlu pthread)

View File

@ -10,6 +10,7 @@
#include "tasmet_assert.h" #include "tasmet_assert.h"
#include "tasmet_evalscript.h" #include "tasmet_evalscript.h"
#include "perfectgas.h" #include "perfectgas.h"
#include "../export/export.h"
Duct::Duct(const TaSystem& sys, Duct::Duct(const TaSystem& sys,
const us id, const us id,
@ -47,7 +48,7 @@ Duct::Duct(const TaSystem& sys,const Duct& other):
_Tsprescribed(other._Tsprescribed) _Tsprescribed(other._Tsprescribed)
{ {
// Do something with the equations here // Do something with the equations here
TRACE(15,"Duct::~Duct"); TRACE(15,"Duct::Duct");
} }
@ -109,6 +110,8 @@ void Duct::residualJac(SegPositionMapper& residual,
pp = getvart(constants::p,gp+1); pp = getvart(constants::p,gp+1);
cont = ((rhop%up)-(rho%u))/dx; cont = ((rhop%up)-(rho%u))/dx;
// cont += sys.DDTtd()*rho;
*residual.at(i) = cont; *residual.at(i) = cont;
jacrows.at(i)[{_id,gp*nvars_per_gp+constants::u}] = jacrows.at(i)[{_id,gp*nvars_per_gp+constants::u}] =
@ -119,7 +122,7 @@ void Duct::residualJac(SegPositionMapper& residual,
diagmat(up)/dx; diagmat(up)/dx;
jacrows.at(i)[{_id,(gp+1)*nvars_per_gp+constants::u}] = jacrows.at(i)[{_id,(gp+1)*nvars_per_gp+constants::u}] =
diagmat(rhop)/dx; diagmat(rhop)/dx;
TRACE(15,"SFSG");
i++; i++;
mom = (rhop%up%up - rho%u%u + pp - p)/dx; mom = (rhop%up%up - rho%u%u + pp - p)/dx;
@ -136,7 +139,7 @@ void Duct::residualJac(SegPositionMapper& residual,
jacrows.at(i)[{_id,(gp+1)*nvars_per_gp+constants::p}] = jacrows.at(i)[{_id,(gp+1)*nvars_per_gp+constants::p}] =
eye(Ns,Ns)/dx; eye(Ns,Ns)/dx;
*residual.at(i) = mom; *residual.at(i) = mom;
TRACE(15,"SFSG");
i++; i++;
switch (_ductpb.htmodel()) { switch (_ductpb.htmodel()) {
@ -155,7 +158,7 @@ void Duct::residualJac(SegPositionMapper& residual,
eye(Ns,Ns)/p0; eye(Ns,Ns)/p0;
jacrows.at(i)[{_id,gp*nvars_per_gp+constants::rho}] = jacrows.at(i)[{_id,gp*nvars_per_gp+constants::rho}] =
-(gamma0/rho0)*diagmat(pow(rho/rho0,gamma0-1)); -(gamma0/rho0)*diagmat(pow(rho/rho0,gamma0-1));
TRACE(15,"SFSG");
} }
break; break;
default: default:
@ -163,10 +166,10 @@ void Duct::residualJac(SegPositionMapper& residual,
} }
i++; i++;
TRACE(15,"SFSG");
// Equation of state // Equation of state
st = gas.rho(T,p) - rho; st = gas.rho(T,p) - rho;
TRACE(15,"SFSG");
jacrows.at(i)[{_id,gp*nvars_per_gp+constants::rho}] = jacrows.at(i)[{_id,gp*nvars_per_gp+constants::rho}] =
-eye(Ns,Ns); -eye(Ns,Ns);
jacrows.at(i)[{_id,gp*nvars_per_gp+constants::p}] = jacrows.at(i)[{_id,gp*nvars_per_gp+constants::p}] =
@ -175,7 +178,7 @@ void Duct::residualJac(SegPositionMapper& residual,
diagmat(gas.drhodT(T,p)); diagmat(gas.drhodT(T,p));
*residual.at(i) = st; *residual.at(i) = st;
TRACE(15,"SFSG");
i++; i++;
} }
@ -330,5 +333,78 @@ void Duct::show(us verbosity_level) const {
} }
void Duct::exportHDF5(const hid_t group_id) const {
TRACE(15,"Duct::exportHDF5");
PosData x;
x.name = "Position";
x.unit = "m";
x.symbol = "x";
x.x = this->x;
x.exportHDF5(group_id);
PosData S;
S.name = "Cross-sectional area";
S.unit = "m^2";
S.symbol = "S";
S.x = this->S;
S.exportHDF5(group_id);
PosData phi;
phi.name = "Porosity";
phi.unit = "-";
phi.symbol = "phi";
phi.x = this->phi;
phi.exportHDF5(group_id);
PosData rh;
rh.name = "Hydraulic radius";
rh.unit = "m";
rh.symbol = "rh";
rh.x = this->rh;
rh.exportHDF5(group_id);
TXData u;
u.name = "Velocity";
u.unit = "m/s";
u.symbol = "u";
u.x = dmat(sys.Ns(),ngp());
for(us gp=0;gp<ngp();gp++){
u.x.col(gp) = ut(gp);
}
u.exportHDF5(group_id);
TXData T;
T.name = "Fluid temperature";
T.unit = "K";
T.symbol = "T";
T.x = dmat(sys.Ns(),ngp());
for(us gp=0;gp<ngp();gp++){
T.x.col(gp) = Tt(gp);
}
T.exportHDF5(group_id);
TXData p;
p.name = "Fluid pressure";
p.unit = "Pa";
p.symbol = "p";
p.x = dmat(sys.Ns(),ngp());
for(us gp=0;gp<ngp();gp++){
p.x.col(gp) = pt(gp);
}
p.exportHDF5(group_id);
TXData Ts;
Ts.name = "Solid temperature";
Ts.unit = "K";
Ts.symbol = "Ts";
Ts.x = dmat(sys.Ns(),ngp());
for(us gp=0;gp<ngp();gp++){
p.x.col(gp) = Tst(gp);
}
Ts.exportHDF5(group_id);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -93,6 +93,7 @@ public:
// Reset amplitude data in higher harmonics // Reset amplitude data in higher harmonics
// void resetHarmonics(); // void resetHarmonics();
void exportHDF5(const hid_t group_id) const;
}; };
#endif // DUCT_H #endif // DUCT_H

154
src/export/export.cpp Normal file
View File

@ -0,0 +1,154 @@
// export.cpp
//
// last-edit-by: J.A. de Jong
//
// Description:
//
//////////////////////////////////////////////////////////////////////
#include "export.h"
#include "tasmet_exception.h"
#include "tasmet_tracer.h"
// Lite version of the library
#include <hdf5_hl.h>
#if TASMET_FLOAT == 64
#define make_dataset H5LTmake_dataset_double
#elif TASMET_FLOAT == 32
#define make_dataset H5LTmake_dataset_float
#else
#error "Invalid TASMET_FLOAT"
#endif
namespace {
/**
* Set the attributes of a dataset
*
* @param data the data from which to take the name, unit, symbol
* @param dsetname the dataset name to add the attributes to
* @param hfgroup the group
*/
void setAttributes(const ExportData& data,
const string& dsetname,
const hid_t hfgroup) {
H5LTset_attribute_string(hfgroup,
dsetname.c_str(),
"name",
data.name.c_str());
H5LTset_attribute_string(hfgroup,
dsetname.c_str(),
"unit",
data.unit.c_str());
H5LTset_attribute_string(hfgroup,
dsetname.c_str(),
"symbol",
data.symbol.c_str());
}
}
void PointData::exportHDF5(hid_t hfgroup) {
// We use the lite API for setting the data
hsize_t dims[] = {1}; // First dimension has lenght 1
hsize_t rank = 1;
herr_t status;
string dsetname = (string("/") + symbol); // name
status = make_dataset(hfgroup, // Group
dsetname.c_str(),
rank,
dims,
&x);
setAttributes(*this,dsetname,hfgroup);
}
void TimeData::exportHDF5(hid_t hfgroup) {
// We use the lite API for setting the data
hsize_t dims[] = {x.size()}; // First dimension has lenght 1
hsize_t rank = 1;
string dsetname = (string("/") + symbol); // name
herr_t status;
status = make_dataset(hfgroup, // Group
dsetname.c_str(), // Dataset name
rank,
dims,
x.memptr());
setAttributes(*this,dsetname,hfgroup);
}
void PosData::exportHDF5(hid_t hfgroup) {
TRACE(15,"PosData::exportHDF5");
// We use the lite API for setting the data
hsize_t dims[] = {x.size()}; // First dimension has lenght 1
hsize_t rank = 1;
string dsetname = (string("/") + symbol); // name
herr_t status;
status = make_dataset(hfgroup, // Group
dsetname.c_str(),
rank,
dims,
x.memptr());
setAttributes(*this,dsetname,hfgroup);
H5Eprint(status,0);
}
void TXData::exportHDF5(hid_t hfgroup) {
// We use the lite API for setting the data
// HDF5 Stores data in row-major ordering. Armadillo uses
// column-major ordering. Therefore, we store the transpose of the data.
dmat x = this->x.t();
hsize_t dims[] = {x.n_cols,x.n_rows}; // First dimension has lenght 1
hsize_t rank = 2;
d* xptr = x.memptr();
std::vector<d*> col_ptrs(x.n_cols);
for(us col=0;col<x.n_cols;col++) {
col_ptrs[col] = &xptr[col*x.n_rows];
}
string dsetname = (string("/") + symbol); // name
make_dataset(hfgroup, // Group
dsetname.c_str(), // name
rank,
dims,
&col_ptrs[0][0]);
setAttributes(*this,
dsetname,
hfgroup);
}
//////////////////////////////////////////////////////////////////////

122
src/export/export.h Normal file
View File

@ -0,0 +1,122 @@
// export.h
//
// Author: J.A. de Jong
//
// Description:
// Data structure used for exporting
//////////////////////////////////////////////////////////////////////
#pragma once
#ifndef EXPORT_H
#define EXPORT_H
#define TASMET_HDF5
#include "tasmet_enum.h"
#include "tasmet_types.h"
#ifdef TASMET_HDF5
#include <hdf5.h>
#endif
DECLARE_ENUM(FileType,FileTypeTXT)
struct ExportData
{
string name; /**< Full name of the quantity */
string unit; /**< Unit of the quantity */
string symbol; /**< Used symbol / abbreviation */
/**
* Export the data to a text file
*
* @param FileType
* @param filename
* @param group
*
*
*/
// void export(const string& filename)=0;
/**
* Export the result to an existing HDF5
*
* @param hfgroup
*/
#ifdef TASMET_HDF5
virtual void exportHDF5(hid_t hfgroup)=0;
#endif
// void show() const = 0;
virtual ~ExportData(){}
};
/**
* A physical quantity result, not a function of time or position
*
*/
struct PointData: public ExportData {
d x; /**< The value */
#ifdef TASMET_HDF5
void exportHDF5(hid_t hfgroup);
#endif
};
/**
* A physical quantity at a single position, as a function of time.
*
*/
struct TimeData: public ExportData
{
vd t; /**< The time instances of the
record */
vd x; /**< The quantity at the time
instance */
#ifdef TASMET_HDF5
void exportHDF5(hid_t hfgroup);
#endif
};
/**
* A physical quantity at a single time instance, as a function of
* position.
*
*/
struct PosData: public ExportData
{
vd X; /**< The positions of the
record */
vd x; /**< The quantity as function of the
position */
#ifdef TASMET_HDF5
void exportHDF5(hid_t hfgroup);
#endif
};
/**
* A physical quantity at a single position, as a function of time and
* position (X)
*
*/
struct TXData : public ExportData
{
vd t; /**< The time instances of the
record */
vd X; /**< The positions of the record */
dmat x; /**< The quantity at the time and position instance. Note:
the first axis denotes time, the second axis denotes
position! */
#ifdef TASMET_HDF5
void exportHDF5(hid_t hfgroup);
#endif
};
#endif // EXPORT_H
//////////////////////////////////////////////////////////////////////

View File

@ -83,7 +83,7 @@ public:
virtual vd getSolution() const=0; virtual vd getSolution() const=0;
virtual void updateSolution(const vd& new_guess)=0; virtual void updateSolution(const vd& new_guess)=0;
virtual ~GradientNonlinearSystem(){}
}; };

View File

@ -74,7 +74,7 @@ void GlobalConf::setomg(d omg){
_DDTfd(2*i-1,2*i )=-double(i)*_omg; _DDTfd(2*i-1,2*i )=-double(i)*_omg;
_DDTfd(2*i ,2*i-1)=double(i)*_omg; _DDTfd(2*i ,2*i-1)=double(i)*_omg;
} }
_DDTtd = _iDFT * _DDTfd * _fDFT;
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -22,7 +22,7 @@ class GlobalConf{
d _omg; // The "base" frequency in rad/s d _omg; // The "base" frequency in rad/s
us _Nf; // Number of frequencies to solve for us _Nf; // Number of frequencies to solve for
dmat _fDFT,_iDFT,_DDTfd; dmat _fDFT,_iDFT,_DDTfd,_DDTtd;
// d Wfo_=0; // First order 'upwind' factor. If // d Wfo_=0; // First order 'upwind' factor. If
// Wfo=-1, interpolation is done from // Wfo=-1, interpolation is done from
// the left side. If Wfo=0, // the left side. If Wfo=0,
@ -35,6 +35,7 @@ public:
const dmat& iDFT = _iDFT; //inverse discrete Fourier transform matrix const dmat& iDFT = _iDFT; //inverse discrete Fourier transform matrix
const dmat& fDFT = _fDFT; //forward discrete Fourier transform matrix const dmat& fDFT = _fDFT; //forward discrete Fourier transform matrix
const dmat& DDTfd = _DDTfd; //Derivative in frequency domain const dmat& DDTfd = _DDTfd; //Derivative in frequency domain
const dmat& DDTtd = _DDTtd; //Derivative in time domain
us Nf() const {return _Nf;} us Nf() const {return _Nf;}
us Ns() const {return 2*_Nf+1;} us Ns() const {return 2*_Nf+1;}

View File

@ -12,13 +12,12 @@
#pragma once #pragma once
#ifndef SEGMENT_H #ifndef SEGMENT_H
#define SEGMENT_H #define SEGMENT_H
#include <hdf5.h>
#include "tasmet_types.h" #include "tasmet_types.h"
#include "tasmet_exception.h" #include "tasmet_exception.h"
#include "jacobian.h" #include "jacobian.h"
// #include "phaseconstraint.h" // #include "phaseconstraint.h"
class GlobalConf; class GlobalConf;
class TaSystem; class TaSystem;
@ -83,6 +82,8 @@ public:
// Reset amplitude data in higher harmonics // Reset amplitude data in higher harmonics
// virtual void resetHarmonics() = 0; // virtual void resetHarmonics() = 0;
virtual void exportHDF5(const hid_t group_id) const {}
}; };

View File

@ -5,6 +5,8 @@
// Description: // Description:
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
#include <hdf5.h>
#include "segment.h" #include "segment.h"
#include "tasystem.h" #include "tasystem.h"
#include "triplets.h" #include "triplets.h"
@ -16,6 +18,7 @@
#include "duct.h" #include "duct.h"
#include "ductbc.h" #include "ductbc.h"
TaSystem::TaSystem(const pb::System& sys): TaSystem::TaSystem(const pb::System& sys):
GlobalConf(sys.nf(),sys.freq()) GlobalConf(sys.nf(),sys.freq())
{ {
@ -413,4 +416,42 @@ void TaSystem::cleanup() {
} }
void TaSystem::exportHDF5(const string& filename) const {
TRACE(15,"TaSystem::exportHDF5");
hid_t file_id;
herr_t status;
file_id = H5Fcreate (filename.c_str(),
H5F_ACC_TRUNC,
H5P_DEFAULT,
H5P_DEFAULT);
for(const auto& seg_ : _segs) {
// Create a group for each segment
hid_t grp_id = H5Gcreate(file_id,
(string("/") + std::to_string(seg_.first)).c_str(),
H5P_DEFAULT,
H5P_DEFAULT,
H5P_DEFAULT);
seg_.second->exportHDF5(grp_id);
H5Gclose(grp_id);
// ^^ uncommenting above results in segfault. Why?
// seg_.second->exportHDF5(file_id);
}
status = H5Fclose(file_id);
H5Eprint(status,0);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -112,6 +112,17 @@ public:
const Segment& getSegment(const us id) const {return *_segs.at(id);} const Segment& getSegment(const us id) const {return *_segs.at(id);}
/**
* Store the current results to a HDF5 file. For each segment, a
* group is created with the name corresponding to the segment
* ID. Then, the group contents is filled based on what the
* segment wants to store as result data. *Warning*: overwrites
* existing files without confirmation!
*
* @param filename The filename of the output file
*/
void exportHDF5(const string& filename) const;
protected: protected:
virtual int getArbitrateMassEq(const vus& neqs) const; virtual int getArbitrateMassEq(const vus& neqs) const;
private: private:

View File

@ -58,6 +58,15 @@ int main(int argc, char *argv[]) {
progress_callback cb = simple_progress_callback(1e-6,1e-6); progress_callback cb = simple_progress_callback(1e-6,1e-6);
solver.start(&cb); solver.start(&cb);
vd sol = solver.getSolution();
// Put solution in our copy of system
system->updateSolution(sol);
system->exportHDF5(filename+".h5");
} }