Skip to content

Commit

Permalink
Change writing output from pull to push model
Browse files Browse the repository at this point in the history
Until now, the unit model exposed information on the structure of its
internal state vector slice to the SolutionRecorder via the
SolutionExporter interface. The SolutionRecorder then pulls the
requested information from the state vector slice using the given
structural information (e.g., orderings).

This is changed in favor of a push interface. Now, the SolutionExporter
writes the requested state vector parts directly into a given buffer.
The SolutionRecorder is responsible for allocating enough memory for
this operation. To this end, the SolutionExporter still provides some
information about the structure, but only to allow allocation of the
necessary memory (i.e., it does not provide ordering information). In
order to compensate, each unit's SolutionExporter has to write the data
in a prescribed standardized ordering:

Bulk: Axial/Primary coord - Radial/Secondary coord - Component

Particle mobile phase:
    Particle type - Axial/Primary coord - Radial/Secondary coord -
    Particle shell - Component

Solid phase:
    Particle type - Axial/Primary coord - Radial/Secondary coord -
    Particle shell - Bound states

    Here, the bound states are in component-major format:
    All bound states of component 0, all bound states of component 1,
    etc.

Bulk-particle flux: Particle type - Axial/Primary coord -
    Radial/Secondary coord - Component
  • Loading branch information
sleweke committed Mar 25, 2022
1 parent c42d27d commit c32c426
Show file tree
Hide file tree
Showing 17 changed files with 1,042 additions and 756 deletions.
281 changes: 154 additions & 127 deletions include/cadet/SolutionExporter.hpp

Large diffs are not rendered by default.

395 changes: 146 additions & 249 deletions include/common/SolutionRecorderImpl.hpp

Large diffs are not rendered by default.

118 changes: 118 additions & 0 deletions src/libcadet/model/GeneralRateModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2983,6 +2983,124 @@ bool GeneralRateModel::hasParameter(const ParameterId& pId) const
return UnitOperationBase::hasParameter(pId);
}


int GeneralRateModel::Exporter::writeMobilePhase(double* buffer) const
{
const int blockSize = numMobilePhaseDofs();
std::copy_n(_idx.c(_data), blockSize, buffer);
return blockSize;
}

int GeneralRateModel::Exporter::writeSolidPhase(double* buffer) const
{
int numWritten = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
{
const int n = writeParticleMobilePhase(i, buffer);
buffer += n;
numWritten += n;
}
return numWritten;
}

int GeneralRateModel::Exporter::writeParticleMobilePhase(double* buffer) const
{
int numWritten = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
{
const int n = writeParticleMobilePhase(i, buffer);
buffer += n;
numWritten += n;
}
return numWritten;
}

int GeneralRateModel::Exporter::writeSolidPhase(unsigned int parType, double* buffer) const
{
cadet_assert(parType < _disc.nParType);

const unsigned int stride = _disc.nComp + _disc.strideBound[parType];
double const* ptr = _data + _idx.offsetCp(ParticleTypeIndex{parType}) + _disc.nComp;
for (unsigned int i = 0; i < _disc.nCol; ++i)
{
for (unsigned int j = 0; j < _disc.nParCell[parType]; ++j)
{
std::copy_n(ptr, _disc.strideBound[parType], buffer);
buffer += _disc.strideBound[parType];
ptr += stride;
}
}
return _disc.nCol * _disc.nParCell[parType] * _disc.strideBound[parType];
}

int GeneralRateModel::Exporter::writeParticleMobilePhase(unsigned int parType, double* buffer) const
{
cadet_assert(parType < _disc.nParType);

const unsigned int stride = _disc.nComp + _disc.strideBound[parType];
double const* ptr = _data + _idx.offsetCp(ParticleTypeIndex{parType});
for (unsigned int i = 0; i < _disc.nCol; ++i)
{
for (unsigned int j = 0; j < _disc.nParCell[parType]; ++j)
{
std::copy_n(ptr, _disc.nComp, buffer);
buffer += _disc.nComp;
ptr += stride;
}
}
return _disc.nCol * _disc.nParCell[parType] * _disc.nComp;
}

int GeneralRateModel::Exporter::writeParticleFlux(double* buffer) const
{
const int blockSize = numParticleFluxDofs();
std::copy_n(_idx.jf(_data), blockSize, buffer);
return blockSize;
}

int GeneralRateModel::Exporter::writeParticleFlux(unsigned int parType, double* buffer) const
{
const unsigned int blockSize = _disc.nComp * _disc.nCol;
std::copy_n(_idx.jf(_data) + blockSize * parType, blockSize, buffer);
return blockSize;
}

int GeneralRateModel::Exporter::writeInlet(unsigned int port, double* buffer) const
{
cadet_assert(port == 0);
std::copy_n(_data, _disc.nComp, buffer);
return _disc.nComp;
}

int GeneralRateModel::Exporter::writeInlet(double* buffer) const
{
std::copy_n(_data, _disc.nComp, buffer);
return _disc.nComp;
}

int GeneralRateModel::Exporter::writeOutlet(unsigned int port, double* buffer) const
{
cadet_assert(port == 0);

if (_model._convDispOp.currentVelocity() >= 0)
std::copy_n(&_idx.c(_data, _disc.nCol - 1, 0), _disc.nComp, buffer);
else
std::copy_n(&_idx.c(_data, 0, 0), _disc.nComp, buffer);

return _disc.nComp;
}

int GeneralRateModel::Exporter::writeOutlet(double* buffer) const
{
if (_model._convDispOp.currentVelocity() >= 0)
std::copy_n(&_idx.c(_data, _disc.nCol - 1, 0), _disc.nComp, buffer);
else
std::copy_n(&_idx.c(_data, 0, 0), _disc.nComp, buffer);

return _disc.nComp;
}


void registerGeneralRateModel(std::unordered_map<std::string, std::function<IUnitOperation*(UnitOpIdx)>>& models)
{
models[GeneralRateModel::identifier()] = [](UnitOpIdx uoId) { return new GeneralRateModel(uoId); };
Expand Down
97 changes: 37 additions & 60 deletions src/libcadet/model/GeneralRateModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ class GeneralRateModel : public UnitOperationBase
inline int strideParShell(int parType) const CADET_NOEXCEPT { return strideParLiquid() + strideParBound(parType); }
inline int strideParBlock(int parType) const CADET_NOEXCEPT { return static_cast<int>(_disc.nParCell[parType]) * strideParShell(parType); }

inline int strideFluxCell() const CADET_NOEXCEPT { return static_cast<int>(_disc.nComp) * static_cast<int>(_disc.nParType); }
inline int strideFluxParType() const CADET_NOEXCEPT { return static_cast<int>(_disc.nComp); }
inline int strideFluxCell() const CADET_NOEXCEPT { return static_cast<int>(_disc.nComp); }
inline int strideFluxParType() const CADET_NOEXCEPT { return static_cast<int>(_disc.nComp * _disc.nCol); }
inline int strideFluxComp() const CADET_NOEXCEPT { return 1; }

// Offsets
Expand Down Expand Up @@ -432,90 +432,67 @@ class GeneralRateModel : public UnitOperationBase
virtual bool hasVolume() const CADET_NOEXCEPT { return false; }

virtual unsigned int numComponents() const CADET_NOEXCEPT { return _disc.nComp; }
virtual unsigned int numAxialCells() const CADET_NOEXCEPT { return _disc.nCol; }
virtual unsigned int numRadialCells() const CADET_NOEXCEPT { return 0; }
virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT { return _disc.nCol; }
virtual unsigned int numSecondaryCoordinates() const CADET_NOEXCEPT { return 0; }
virtual unsigned int numInletPorts() const CADET_NOEXCEPT { return 1; }
virtual unsigned int numOutletPorts() const CADET_NOEXCEPT { return 1; }
virtual unsigned int numParticleTypes() const CADET_NOEXCEPT { return _disc.nParType; }
virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return _disc.nParCell[parType]; }
virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT { return _disc.strideBound[parType]; }
virtual unsigned int numBulkDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; }
virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nParCell[parType] * _disc.nComp; }
virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nParCell[parType] * _disc.strideBound[parType]; }
virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nParType; }
virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; }

virtual double const* concentration() const { return _idx.c(_data); }
virtual double const* flux() const { return _idx.jf(_data); }
virtual double const* particleMobilePhase(unsigned int parType) const { return _data + _idx.offsetCp(ParticleTypeIndex{parType}); }
virtual double const* solidPhase(unsigned int parType) const { return _data + _idx.offsetCp(ParticleTypeIndex{parType}) + _idx.strideParLiquid(); }
virtual double const* volume() const { return nullptr; }
virtual double const* inlet(unsigned int port, unsigned int& stride) const
{
stride = _idx.strideColComp();
return _data;
}
virtual double const* outlet(unsigned int port, unsigned int& stride) const
virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; }
virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT
{
stride = _idx.strideColComp();
if (_model._convDispOp.currentVelocity() >= 0)
return &_idx.c(_data, _disc.nCol - 1, 0);
else
return &_idx.c(_data, 0, 0);
unsigned int nDofPerParType = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
nDofPerParType += _disc.nParCell[i];
return _disc.nCol * nDofPerParType * _disc.nComp;
}

virtual StateOrdering const* concentrationOrdering(unsigned int& len) const
{
len = _concentrationOrdering.size();
return _concentrationOrdering.data();
}

virtual StateOrdering const* fluxOrdering(unsigned int& len) const
{
len = _fluxOrdering.size();
return _fluxOrdering.data();
}

virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const
{
len = _particleOrdering.size();
return _particleOrdering.data();
}

virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const
virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nParCell[parType] * _disc.nComp; }
virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT
{
len = _solidOrdering.size();
return _solidOrdering.data();
unsigned int nDofPerParType = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
nDofPerParType += _disc.nParCell[i] * _disc.strideBound[i];
return _disc.nCol * nDofPerParType;
}
virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nParCell[parType] * _disc.strideBound[parType]; }
virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nParType; }
virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; }

virtual unsigned int bulkMobilePhaseStride() const { return _idx.strideColCell(); }
virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return _idx.strideParShell(parType); }
virtual unsigned int solidPhaseStride(unsigned int parType) const { return _idx.strideParShell(parType); }

virtual void axialCoordinates(double* coords) const
virtual int writeMobilePhase(double* buffer) const;
virtual int writeSolidPhase(double* buffer) const;
virtual int writeParticleMobilePhase(double* buffer) const;
virtual int writeSolidPhase(unsigned int parType, double* buffer) const;
virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const;
virtual int writeParticleFlux(double* buffer) const;
virtual int writeParticleFlux(unsigned int parType, double* buffer) const;
virtual int writeVolume(double* buffer) const { return 0; }
virtual int writeInlet(unsigned int port, double* buffer) const;
virtual int writeInlet(double* buffer) const;
virtual int writeOutlet(unsigned int port, double* buffer) const;
virtual int writeOutlet(double* buffer) const;

virtual int writePrimaryCoordinates(double* coords) const
{
const double h = static_cast<double>(_model._convDispOp.columnLength()) / static_cast<double>(_disc.nCol);
for (unsigned int i = 0; i < _disc.nCol; ++i)
coords[i] = (i + 0.5) * h;
return _disc.nCol;
}
virtual void radialCoordinates(double* coords) const { }
virtual void particleCoordinates(unsigned int parType, double* coords) const
virtual int writeSecondaryCoordinates(double* coords) const { return 0; }
virtual int writeParticleCoordinates(unsigned int parType, double* coords) const
{
active const* const pcr = _model._parCenterRadius.data() + _disc.nParCellsBeforeType[parType];
for (unsigned int i = 0; i < _disc.nParCell[parType]; ++i)
coords[i] = static_cast<double>(pcr[i]);
return _disc.nParCell[parType];
}

protected:
const Discretization& _disc;
const Indexer _idx;
const GeneralRateModel& _model;
double const* const _data;

const std::array<StateOrdering, 2> _concentrationOrdering = { { StateOrdering::AxialCell, StateOrdering::Component } };
const std::array<StateOrdering, 4> _particleOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::ParticleShell, StateOrdering::Component } };
const std::array<StateOrdering, 5> _solidOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::ParticleShell, StateOrdering::Component, StateOrdering::BoundState } };
const std::array<StateOrdering, 3> _fluxOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::Component } };
};
};

Expand Down
118 changes: 118 additions & 0 deletions src/libcadet/model/GeneralRateModel2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,124 @@ bool GeneralRateModel2D::setSensitiveParameter(const ParameterId& pId, unsigned
return result;
}


int GeneralRateModel2D::Exporter::writeMobilePhase(double* buffer) const
{
const int blockSize = numMobilePhaseDofs();
std::copy_n(_idx.c(_data), blockSize, buffer);
return blockSize;
}

int GeneralRateModel2D::Exporter::writeSolidPhase(double* buffer) const
{
int numWritten = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
{
const int n = writeParticleMobilePhase(i, buffer);
buffer += n;
numWritten += n;
}
return numWritten;
}

int GeneralRateModel2D::Exporter::writeParticleMobilePhase(double* buffer) const
{
int numWritten = 0;
for (unsigned int i = 0; i < _disc.nParType; ++i)
{
const int n = writeParticleMobilePhase(i, buffer);
buffer += n;
numWritten += n;
}
return numWritten;
}

int GeneralRateModel2D::Exporter::writeSolidPhase(unsigned int parType, double* buffer) const
{
cadet_assert(parType < _disc.nParType);

const unsigned int stride = _disc.nComp + _disc.strideBound[parType];
double const* ptr = _data + _idx.offsetCp(ParticleTypeIndex{parType}) + _disc.nComp;
for (unsigned int i = 0; i < _disc.nCol * _disc.nRad; ++i)
{
for (unsigned int j = 0; j < _disc.nParCell[parType]; ++j)
{
std::copy_n(ptr, _disc.strideBound[parType], buffer);
buffer += _disc.strideBound[parType];
ptr += stride;
}
}
return _disc.nCol * _disc.nRad * _disc.nParCell[parType] * _disc.strideBound[parType];
}

int GeneralRateModel2D::Exporter::writeParticleMobilePhase(unsigned int parType, double* buffer) const
{
cadet_assert(parType < _disc.nParType);

const unsigned int stride = _disc.nComp + _disc.strideBound[parType];
double const* ptr = _data + _idx.offsetCp(ParticleTypeIndex{parType});
for (unsigned int i = 0; i < _disc.nCol * _disc.nRad; ++i)
{
for (unsigned int j = 0; j < _disc.nParCell[parType]; ++j)
{
std::copy_n(ptr, _disc.nComp, buffer);
buffer += _disc.nComp;
ptr += stride;
}
}
return _disc.nCol * _disc.nRad * _disc.nParCell[parType] * _disc.nComp;
}

int GeneralRateModel2D::Exporter::writeParticleFlux(double* buffer) const
{
const int blockSize = numParticleFluxDofs();
std::copy_n(_idx.jf(_data), blockSize, buffer);
return blockSize;
}

int GeneralRateModel2D::Exporter::writeParticleFlux(unsigned int parType, double* buffer) const
{
const unsigned int blockSize = _disc.nComp * _disc.nRad * _disc.nCol;
std::copy_n(_idx.jf(_data) + blockSize * parType, blockSize, buffer);
return blockSize;
}

int GeneralRateModel2D::Exporter::writeInlet(unsigned int port, double* buffer) const
{
cadet_assert(port < _disc.nRad);
std::copy_n(_data + port * _disc.nComp, _disc.nComp, buffer);
return _disc.nComp;
}

int GeneralRateModel2D::Exporter::writeInlet(double* buffer) const
{
std::copy_n(_data, _disc.nComp * _disc.nRad, buffer);
return _disc.nComp * _disc.nRad;
}

int GeneralRateModel2D::Exporter::writeOutlet(unsigned int port, double* buffer) const
{
cadet_assert(port < _disc.nRad);

if (_model._convDispOp.currentVelocity(port) >= 0)
std::copy_n(&_idx.c(_data, _disc.nCol - 1, port, 0), _disc.nComp, buffer);
else
std::copy_n(&_idx.c(_data, 0, port, 0), _disc.nComp, buffer);

return _disc.nComp;
}

int GeneralRateModel2D::Exporter::writeOutlet(double* buffer) const
{
for (int i = 0; i < _disc.nRad; ++i)
{
writeOutlet(i, buffer);
buffer += _disc.nComp;
}
return _disc.nComp * _disc.nRad;
}


void registerGeneralRateModel2D(std::unordered_map<std::string, std::function<IUnitOperation*(UnitOpIdx)>>& models)
{
models[GeneralRateModel2D::identifier()] = [](UnitOpIdx uoId) { return new GeneralRateModel2D(uoId); };
Expand Down
Loading

0 comments on commit c32c426

Please sign in to comment.