diff --git a/include/cadet/SolutionExporter.hpp b/include/cadet/SolutionExporter.hpp index 6c340da99..0472a21b3 100644 --- a/include/cadet/SolutionExporter.hpp +++ b/include/cadet/SolutionExporter.hpp @@ -26,19 +26,6 @@ namespace cadet { -/** - * @brief Elements of state vector ordering - */ -enum class StateOrdering : uint8_t -{ - Component, - AxialCell, - RadialCell, - ParticleType, - ParticleShell, - BoundState -}; - /** * @brief Interface providing functionality for exporting the solution to the user space */ @@ -78,16 +65,18 @@ class CADET_API ISolutionExporter virtual unsigned int numComponents() const CADET_NOEXCEPT = 0; /** - * @brief Returns the number of axial column cells - * @return Number of axial column cells + * @brief Returns the number of primary coordinates / points + * @details For axial flow columns, this is the number of axial points + * @return Number of primary coordinates / points */ - virtual unsigned int numAxialCells() const CADET_NOEXCEPT = 0; + virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT = 0; /** - * @brief Returns the number of radial column cells - * @return Number of radial column cells + * @brief Returns the number of secondary coordinates / points + * @details For axial flow columns, this is the number of radial points + * @return Number of secondary coordinates / points */ - virtual unsigned int numRadialCells() const CADET_NOEXCEPT = 0; + virtual unsigned int numSecondaryCoordinates() const CADET_NOEXCEPT = 0; /** * @brief Returns the number of inlet ports @@ -122,186 +111,224 @@ class CADET_API ISolutionExporter virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT = 0; /** - * @brief Returns the total number of DOFs in the interstitial bulk volume - * @return Number of main / bulk DOFs + * @brief Returns the total number of DOFs in the main mobile phase (e.g., bulk volume) + * @return Total number of mobile phase DOFs */ - virtual unsigned int numBulkDofs() const CADET_NOEXCEPT = 0; + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT = 0; /** - * @brief Returns the total number of mobile phase DOFs in the particles, if particles are supported - * @details The total number of DOFs is returned, i.e., the sum of all particle cells' mobile phase DOFs. - * This includes all particle types. - * + * @brief Returns the total number of mobile phase DOFs in the particles of the given type if particles are supported * @param [in] parType Particle type index * @return Total number of particle mobile phase DOFs */ virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT = 0; /** - * @brief Returns the total number of solid phase DOFs - * @details The total number of DOFs is returned, i.e., the sum of all column and particle cells' solid phase DOFs. - * This includes all particle types. - * + * @brief Returns the total number of mobile phase DOFs in the particles of the given type if particles are supported + * @details This includes all particle types. + * @return Total number of particle mobile phase DOFs + */ + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT = 0; + + /** + * @brief Returns the total number of solid phase DOFs for the given particle type * @param [in] parType Particle type index * @return Total number of solid phase DOFs */ virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT = 0; /** - * @brief Returns the number of bulk-bead flux DOFs, if particle fluxes are supported + * @brief Returns the total number of solid phase DOFs + * @details This includes all particle types. + * @return Total number of solid phase DOFs + */ + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT = 0; + + /** + * @brief Returns the number of bulk-bead flux DOFs if particle fluxes are supported * @return Total number of particle flux DOFs */ - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT = 0; + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT = 0; /** - * @brief Returns the number of volume DOFs, if volume DOFs are supported + * @brief Returns the number of volume DOFs if volume DOFs are supported * @return Number of volume DOFs */ virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT = 0; /** - * @brief Provides direct access to the underlying main mobile phase state vector - * @details The ordering of the data inside the state vector is provided by concentrationOrdering() - * @return Pointer to the first element of the state vector - */ - virtual double const* concentration() const = 0; - - /** - * @brief Provides direct access to the underlying flux state vector - * @details The ordering of the data inside the state vector is provided by fluxOrdering() - * @return Pointer to the first element of the state vector or @c NULL if the model does not support it - */ - virtual double const* flux() const = 0; - - /** - * @brief Provides direct access to the underlying particle mobile phase state vector part of the given particle type - * @details The ordering of the (full) data inside the state vector is provided by mobilePhaseOrdering() - * @param [in] parType Particle type index - * @return Pointer to the first element of the state vector or @c NULL if the model does not support it + * @brief Writes the solution of the (bulk) mobile phase to the given buffer + * @details The data is written in the order primary-secondary-component, + * where the last index changes the fastest. + * + * For a system with 3 primary coordinates, 2 secondary coordinates, + * and 4 components, the data is written as + * p0s0c0, p0s0c1, p0s0c2, p0s0c3, + * p0s1c0, p0s1c1, p0s1c2, p0s1c3, + * p1s0c0, p1s0c1, p1s0c2, p1s0c3, + * p1s1c0, p1s1c1, p1s1c2, p1s1c3, ... + * + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual double const* particleMobilePhase(unsigned int parType) const = 0; + virtual int writeMobilePhase(double* buffer) const = 0; /** - * @brief Provides direct access to the underlying solid phase state vector part of the given particle type - * @details The ordering of the (full) data inside the state vector is provided by solidPhaseOrdering() - * @param [in] parType Particle type index - * @return Pointer to the first element of the state vector or @c NULL if the model does not support it + * @brief Writes the solution of the solid phase to the given buffer + * @details The data is written in the order particletype-primary-secondary-particle-component-boundstate, + * where the last index changes the fastest. + * The solution is written for all particle types. + * + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual double const* solidPhase(unsigned int parType) const = 0; + virtual int writeSolidPhase(double* buffer) const = 0; /** - * @brief Provides direct access to the underlying volume slice of the state vector - * @return Pointer to the first element of the volume slice or @c NULL if the model does not support volume DOFs + * @brief Writes the solution of the particle mobile phase to the given buffer + * @details The data is written in the order particletype-primary-secondary-particle-component, + * where the last index changes the fastest. + * The solution is written for all particle types. + * + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual double const* volume() const = 0; + virtual int writeParticleMobilePhase(double* buffer) const = 0; /** - * @brief Provides direct access to the inlet state vector - * @details The inlet state vector only contains one value for each main mobile phase component (see numComponents()). - * The stride required for the access is returned in @p stride. - * @param [in] port Index of the port - * @param [out] stride Stride of the vector access - * @return Pointer to the first element of the inlet state vector + * @brief Writes the solution of the solid phase to the given buffer + * @details The data is written in the order primary-secondary-particle-component-boundstate, + * where the last index changes the fastest. + * The solution is written for the given particle type only. + * + * For a system with 2 primary coordinates, 2 secondary coordinates, 2 particle + * coordinates, 2 components, and 2 bound states per component, the data is written as + * p0s0p0c0s0, p0s0p0c0s1, p0s0p0c1s0, p0s0p0c1s1, + * p0s0p1c0s0, p0s0p1c0s1, p0s0p1c1s0, p0s0p1c1s1, + * p0s1p0c0s0, p0s1p0c0s1, p0s1p0c1s0, p0s1p0c1s1, + * p0s1p1c0s0, p0s1p1c0s1, p0s1p1c1s0, p0s1p1c1s1, + * p1s0p0c0s0, p1s0p0c0s1, p1s0p0c1s0, p1s0p0c1s1, + * p1s0p1c0s0, p1s0p1c0s1, p1s0p1c1s0, p1s0p1c1s1, + * p1s1p0c0s0, p1s1p0c0s1, p1s1p0c1s0, p1s1p0c1s1, + * p1s1p1c0s0, p1s1p1c0s1, p1s1p1c1s0, p1s1p1c1s1, ... + * + * @param [in] parType Index of the particle type to be written + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual double const* inlet(unsigned int port, unsigned int& stride) const = 0; + virtual int writeSolidPhase(unsigned int parType, double* buffer) const = 0; /** - * @brief Provides direct access to the outlet state vector - * @details The outlet state vector only contains one value for each main mobile phase component (see numComponents()). - * The stride required for the access is returned in @p stride. - * @param [in] port Index of the port - * @param [out] stride Stride of the vector access - * @return Pointer to the first element of the outlet state vector + * @brief Writes the solution of the particle mobile phase to the given buffer + * @details The data is written in the order primary-secondary-particle-component, + * where the last index changes the fastest. + * The solution is written for the given particle type only. + * + * For a system with 2 primary coordinates, 2 secondary coordinates, 2 particle + * coordinates, 2 components, and 2 bound states per component, the data is written as + * p0s0p0c0s0, p0s0p0c0s1, p0s0p0c1s0, p0s0p0c1s1, + * p0s0p1c0s0, p0s0p1c0s1, p0s0p1c1s0, p0s0p1c1s1, + * p0s1p0c0s0, p0s1p0c0s1, p0s1p0c1s0, p0s1p0c1s1, + * p0s1p1c0s0, p0s1p1c0s1, p0s1p1c1s0, p0s1p1c1s1, + * p1s0p0c0s0, p1s0p0c0s1, p1s0p0c1s0, p1s0p0c1s1, + * p1s0p1c0s0, p1s0p1c0s1, p1s0p1c1s0, p1s0p1c1s1, + * p1s1p0c0s0, p1s1p0c0s1, p1s1p0c1s0, p1s1p0c1s1, + * p1s1p1c0s0, p1s1p1c0s1, p1s1p1c1s0, p1s1p1c1s1, ... + * + * @param [in] parType Index of the particle type to be written + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual double const* outlet(unsigned int port, unsigned int& stride) const = 0; - + virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const = 0; /** - * @brief Returns an array describing the ordering of the main mobile phase state vector - * @details A pointer to the first element of the state vector ordering array is returned. The length - * of the array is returned in the parameter @p len. The elements of the array indicate the - * order of loops required to extract the data. + * @brief Writes the solution of the flux between primary mobile phase and particle mobile phase to the given buffer + * @details The data is written in the order particletype-primary-secondary-component, + * where the last index changes the fastest. + * The solution is written for all particle types. * - * @param [out] len Length of the returned ordering vector - * @return Pointer to first element of the ordering vector + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const = 0; + virtual int writeParticleFlux(double* buffer) const = 0; /** - * @brief Returns an array describing the ordering of the flux state vector - * @details A pointer to the first element of the state vector ordering array is returned. The length - * of the array is returned in the parameter @p len. The elements of the array indicate the - * order of loops required to extract the data. + * @brief Writes the solution of the flux between primary mobile phase and particle mobile phase of the selected particle type to the given buffer + * @details The data is written in the order particletype-primary-secondary-component, + * where the last index changes the fastest. * - * @param [out] len Length of the returned ordering vector - * @return Pointer to first element of the ordering vector or @c NULL if fluxes are not supported + * @param [in] parType Index of the particle type to be written + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual StateOrdering const* fluxOrdering(unsigned int& len) const = 0; + virtual int writeParticleFlux(unsigned int parType, double* buffer) const = 0; /** - * @brief Returns an array describing the ordering of the mobile phase state vector - * @details A pointer to the first element of the state vector ordering array is returned. The length - * of the array is returned in the parameter @p len. The elements of the array indicate the - * order of loops required to extract the data. - * - * @param [out] len Length of the returned ordering vector - * @return Pointer to first element of the ordering vector or @c NULL if mobile phases are not supported + * @brief Writes the solution of the volume to the given buffer + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const = 0; + virtual int writeVolume(double* buffer) const = 0; /** - * @brief Returns an array describing the ordering of the solid phase state vector - * @details A pointer to the first element of the state vector ordering array is returned. The length - * of the array is returned in the parameter @p len. The elements of the array indicate the - * order of loops required to extract the data. + * @brief Writes the solution of the inlet at the given port into the provided buffer + * @details Writes all components of the selected port to the provided buffer. * - * @param [out] len Length of the returned ordering vector - * @return Pointer to first element of the ordering vector or @c NULL if solid phases are not supported + * @param [in] port Index of the port + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const = 0; + virtual int writeInlet(unsigned int port, double* buffer) const = 0; /** - * @brief Returns the number of elements between two bulk mobile phase DOF blocks - * @details Stride between two bulk mobile phase DOF blocks. - * @return Number of elements between two bulk mobile phase DOF blocks + * @brief Writes the solution of the inlet at all ports into the provided buffer + * @details Writes all components of all ports to the provided buffer in port-component order. + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual unsigned int bulkMobilePhaseStride() const = 0; + virtual int writeInlet(double* buffer) const = 0; /** - * @brief Returns the number of elements between two particle mobile phase DOF blocks - * @details Stride between two particle mobile phase DOF blocks of the given particle type. - * @param [in] parType Particle type index - * @return Number of elements between two particle mobile phase DOF blocks + * @brief Writes the solution of the outlet at the given port into the provided buffer + * @details Writes all components of the selected port to the provided buffer. + * + * @param [in] port Index of the port + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const = 0; + virtual int writeOutlet(unsigned int port, double* buffer) const = 0; /** - * @brief Returns the number of elements between two solid phase DOF blocks - * @details Stride between two solid phase DOF blocks of the given particle type. - * @param [in] parType Particle type index - * @return Number of elements between two solid phase DOF blocks + * @brief Writes the solution of the outlet at all ports into the provided buffer + * @details Writes all components of all ports to the provided buffer in port-component order. + * @param [out] buffer Pointer to buffer that receives the data + * @return Number of written items */ - virtual unsigned int solidPhaseStride(unsigned int parType) const = 0; + virtual int writeOutlet(double* buffer) const = 0; + /** - * @brief Returns axial coordinates of the DOFs - * @param [out] Pointer to array that is filled with axial coordinates of DOFs + * @brief Returns primary coordinates (e.g., axial for axial flow columns) + * @param [out] coords Pointer to array that is filled with primary coordinates + * @return Number of written items */ - virtual void axialCoordinates(double* coords) const = 0; + virtual int writePrimaryCoordinates(double* coords) const = 0; /** - * @brief Returns radial coordinates of the DOFs - * @param [out] Pointer to array that is filled with radial coordinates of DOFs + * @brief Returns secondary coordinates (e.g., radial for axial flow columns) + * @param [out] coords Pointer to array that is filled with secondary coordinates + * @return Number of written items */ - virtual void radialCoordinates(double* coords) const = 0; + virtual int writeSecondaryCoordinates(double* coords) const = 0; /** - * @brief Returns particle coordinates of the DOFs + * @brief Returns particle coordinates of the selected particle type * @param [in] parType Particle type index - * @param [out] Pointer to array that is filled with particle coordinates of DOFs + * @param [out] coords Pointer to array that is filled with particle coordinates of DOFs + * @return Number of written items */ - virtual void particleCoordinates(unsigned int parType, double* coords) const = 0; + virtual int writeParticleCoordinates(unsigned int parType, double* coords) const = 0; }; } // namespace cadet diff --git a/include/common/SolutionRecorderImpl.hpp b/include/common/SolutionRecorderImpl.hpp index a2e6e0361..c786560a8 100644 --- a/include/common/SolutionRecorderImpl.hpp +++ b/include/common/SolutionRecorderImpl.hpp @@ -58,8 +58,8 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder InternalStorageUnitOpRecorder(UnitOpIdx idx) : _cfgSolution({false, false, false, true, false, false, false}), _cfgSolutionDot({false, false, false, false, false, false, false}), _cfgSensitivity({false, false, false, true, false, false, false}), _cfgSensitivityDot({false, false, false, true, false, false, false}), _storeTime(false), _storeCoordinates(false), _splitComponents(true), _splitPorts(true), - _singleAsMultiPortUnitOps(false), _curCfg(nullptr), _nComp(0), _nVolumeDof(0), _numTimesteps(0), _numSens(0), _unitOp(idx), _needsReAlloc(false), - _axialCoords(0), _radialCoords(0), _particleCoords(0) + _singleAsMultiPortUnitOps(false), _curCfg(nullptr), _nComp(0), _nVolumeDof(0), _nAxialCells(0), _nRadialCells(0), _nInletPorts(0), _nOutletPorts(0), + _numTimesteps(0), _numSens(0), _unitOp(idx), _needsReAlloc(false), _axialCoords(0), _radialCoords(0), _particleCoords(0) { } @@ -124,6 +124,9 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder _nInletPorts = exporter.numInletPorts(); _nOutletPorts = exporter.numOutletPorts(); + _nAxialCells = exporter.numPrimaryCoordinates(); + _nRadialCells = exporter.numSecondaryCoordinates(); + // Query particle type specific structure const unsigned int numParTypes = exporter.numParticleTypes(); _nParShells.resize(numParTypes, 0u); @@ -134,195 +137,21 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder _nBoundStates[i] = exporter.numBoundStates(i); } - // Query structure - unsigned int len = 0; - StateOrdering const* order = exporter.concentrationOrdering(len); - _bulkLayout.clear(); - _bulkLayout.reserve(len + 1); // First slot is time - _bulkLayout.push_back(0); - _bulkCount = 1; - for (unsigned int i = 0; i < len; ++i) - { - switch (order[i]) - { - case StateOrdering::Component: - _bulkLayout.push_back(exporter.numComponents()); - break; - case StateOrdering::AxialCell: - _bulkLayout.push_back(exporter.numAxialCells()); - _bulkCount *= exporter.numAxialCells(); - break; - case StateOrdering::RadialCell: - _bulkLayout.push_back(exporter.numRadialCells()); - _bulkCount *= exporter.numRadialCells(); - case StateOrdering::ParticleType: - case StateOrdering::ParticleShell: - case StateOrdering::BoundState: - break; - } - } - - order = exporter.mobilePhaseOrdering(len); - _particleLayout.clear(); - _particleLayout.resize(numParTypes, std::vector(len + 1, 0)); // First slot is time - _particleCount = std::vector(numParTypes, 1u); - unsigned int idxLayout = 1; - for (unsigned int i = 0; i < len; ++i) - { - switch (order[i]) - { - case StateOrdering::Component: - { - for (unsigned int j = 0; j < numParTypes; ++j) - _particleLayout[j][idxLayout] = exporter.numComponents(); - - ++idxLayout; - break; - } - case StateOrdering::AxialCell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _particleLayout[j][idxLayout] = exporter.numAxialCells(); - _particleCount[j] *= exporter.numAxialCells(); - } - - ++idxLayout; - break; - } - case StateOrdering::RadialCell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _particleLayout[j][idxLayout] = exporter.numRadialCells(); - _particleCount[j] *= exporter.numRadialCells(); - } - - ++idxLayout; - break; - } - case StateOrdering::ParticleType: - break; - case StateOrdering::ParticleShell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _particleLayout[j][idxLayout] = _nParShells[j]; - _particleCount[j] *= _nParShells[j]; - } - - ++idxLayout; - break; - } - case StateOrdering::BoundState: - break; - } - } - - for (unsigned int j = 0; j < numParTypes; ++j) - _particleLayout[j].resize(idxLayout); - - order = exporter.solidPhaseOrdering(len); - _solidLayout.clear(); - _solidLayout.resize(numParTypes, std::vector(len + 1, 0)); // First slot is time - _solidCount = std::vector(numParTypes, 1u); - idxLayout = 1; - for (unsigned int i = 0; i < len; ++i) - { - switch (order[i]) - { - case StateOrdering::Component: - break; - case StateOrdering::AxialCell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _solidLayout[j][idxLayout] = exporter.numAxialCells(); - _solidCount[j] *= exporter.numAxialCells(); - } - - ++idxLayout; - break; - } - case StateOrdering::RadialCell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _solidLayout[j][idxLayout] = exporter.numRadialCells(); - _solidCount[j] *= exporter.numRadialCells(); - } - - ++idxLayout; - break; - } - case StateOrdering::ParticleType: - break; - case StateOrdering::ParticleShell: - { - for (unsigned int j = 0; j < numParTypes; ++j) - { - _solidLayout[j][idxLayout] = _nParShells[j]; - _solidCount[j] *= _nParShells[j]; - } - - ++idxLayout; - break; - } - case StateOrdering::BoundState: - { - for (unsigned int j = 0; j < numParTypes; ++j) - _solidLayout[j][idxLayout] = _nBoundStates[j]; - - ++idxLayout; - break; - } - } - } - - for (unsigned int j = 0; j < numParTypes; ++j) - _solidLayout[j].resize(idxLayout); - - order = exporter.fluxOrdering(len); - _fluxLayout.clear(); - _fluxLayout.reserve(len + 1); // First slot is time - _fluxLayout.push_back(0); - for (unsigned int i = 0; i < len; ++i) - { - switch (order[i]) - { - case StateOrdering::Component: - _fluxLayout.push_back(exporter.numComponents()); - break; - case StateOrdering::AxialCell: - _fluxLayout.push_back(exporter.numAxialCells()); - break; - case StateOrdering::ParticleType: - _fluxLayout.push_back(numParTypes); - break; - case StateOrdering::RadialCell: - _fluxLayout.push_back(exporter.numRadialCells()); - break; - case StateOrdering::ParticleShell: - case StateOrdering::BoundState: - break; - } - } - // Obtain coordinates if (_storeCoordinates) { - _axialCoords.resize(exporter.numAxialCells()); - _radialCoords.resize(exporter.numRadialCells()); + _axialCoords.resize(exporter.numPrimaryCoordinates()); + _radialCoords.resize(exporter.numSecondaryCoordinates()); const unsigned int numShells = std::accumulate(_nParShells.begin(), _nParShells.end(), 0u); _particleCoords.resize(numShells); - exporter.axialCoordinates(_axialCoords.data()); - exporter.radialCoordinates(_radialCoords.data()); + exporter.writePrimaryCoordinates(_axialCoords.data()); + exporter.writeSecondaryCoordinates(_radialCoords.data()); unsigned int offset = 0; for (unsigned int i = 0; i < numParTypes; ++i) { - exporter.particleCoordinates(i, _particleCoords.data() + offset); + exporter.writeParticleCoordinates(i, _particleCoords.data() + offset); offset += _nParShells[i]; } } @@ -387,54 +216,42 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder if ((idx != _unitOp) || !_curCfg) return; - unsigned int stride = 0; - if (_curCfg->storeOutlet) { + const unsigned int sliceSize = _nComp * _nOutletPorts; std::vector& v = _curStorage->outlet; - for (unsigned int j = 0; j < _nOutletPorts; ++j) - { - double const* outlet = exporter.outlet(j, stride); - for (unsigned int i = 0; i < _nComp; ++i) - v.push_back(outlet[i * stride]); - } + + v.resize(v.size() + sliceSize); + exporter.writeOutlet(v.data() + v.size() - sliceSize); } if (_curCfg->storeInlet) { + const unsigned int sliceSize = _nComp * _nInletPorts; std::vector& v = _curStorage->inlet; - for (unsigned int j = 0; j < _nInletPorts; ++j) - { - double const* inlet = exporter.inlet(j, stride); - for (unsigned int i = 0; i < _nComp; ++i) - v.push_back(inlet[i * stride]); - } + + v.resize(v.size() + sliceSize); + exporter.writeInlet(v.data() + v.size() - sliceSize); } if (_curCfg->storeBulk) { + const int sliceSize = exporter.numMobilePhaseDofs(); std::vector& v = _curStorage->bulk; - double const* data = exporter.concentration(); - stride = exporter.bulkMobilePhaseStride(); - const unsigned int blockSize = exporter.numBulkDofs() / _bulkCount; - for (unsigned int i = 0; i < _bulkCount; ++i, data += stride) - { - v.insert(v.end(), data, data + blockSize); - } + + v.resize(v.size() + sliceSize); + exporter.writeMobilePhase(v.data() + v.size() - sliceSize); } if (_curCfg->storeParticle) { for (std::size_t parType = 0; parType < _nParShells.size(); ++parType) { + const int sliceSize = exporter.numParticleMobilePhaseDofs(parType); std::vector& cp = _curStorage->particle[parType]; - double const* data = exporter.particleMobilePhase(parType); - stride = exporter.particleMobilePhaseStride(parType); - const unsigned int blockSize = exporter.numParticleMobilePhaseDofs(parType) / _particleCount[parType]; - for (unsigned int i = 0; i < _particleCount[parType]; ++i, data += stride) - { - cp.insert(cp.end(), data, data + blockSize); - } + + cp.resize(cp.size() + sliceSize); + exporter.writeMobilePhase(cp.data() + cp.size() - sliceSize); } } @@ -442,27 +259,30 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder { for (std::size_t parType = 0; parType < _nParShells.size(); ++parType) { + const int sliceSize = exporter.numSolidPhaseDofs(parType); std::vector& cs = _curStorage->solid[parType]; - double const* data = exporter.solidPhase(parType); - stride = exporter.solidPhaseStride(parType); - const unsigned int blockSize = exporter.numSolidPhaseDofs(parType) / _solidCount[parType]; - for (unsigned int i = 0; i < _solidCount[parType]; ++i, data += stride) - { - cs.insert(cs.end(), data, data + blockSize); - } + + cs.resize(cs.size() + sliceSize); + exporter.writeSolidPhase(cs.data() + cs.size() - sliceSize); } } if (_curCfg->storeFlux) { - double const* const data = exporter.flux(); - _curStorage->flux.insert(_curStorage->flux.end(), data, data + exporter.numFluxDofs()); + const int sliceSize = exporter.numParticleFluxDofs(); + std::vector& v = _curStorage->flux; + + v.resize(v.size() + sliceSize); + exporter.writeParticleFlux(v.data() + v.size() - sliceSize); } if (_curCfg->storeVolume) { - double const* const data = exporter.volume(); - _curStorage->volume.insert(_curStorage->volume.end(), data, data + exporter.numVolumeDofs()); + const int sliceSize = exporter.numVolumeDofs(); + std::vector& v = _curStorage->volume; + + v.resize(v.size() + sliceSize); + exporter.writeVolume(v.data() + v.size() - sliceSize); } } @@ -709,15 +529,15 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder _curStorage->inlet.reserve(nAllocTimesteps * _nComp * _nInletPorts); if (_curCfg->storeBulk) - _curStorage->bulk.reserve(nAllocTimesteps * exporter.numBulkDofs()); - + _curStorage->bulk.reserve(nAllocTimesteps * exporter.numMobilePhaseDofs()); + if (_curCfg->storeParticle) { _curStorage->particle.resize(_nParShells.size()); for (std::size_t i = 0; i < _nParShells.size(); ++i) _curStorage->particle[i].reserve(nAllocTimesteps * exporter.numParticleMobilePhaseDofs(i)); } - + if (_curCfg->storeSolid) { _curStorage->solid.resize(_nParShells.size()); @@ -726,8 +546,8 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder } if (_curCfg->storeFlux) - _curStorage->flux.reserve(nAllocTimesteps * exporter.numFluxDofs()); - + _curStorage->flux.reserve(nAllocTimesteps * exporter.numParticleFluxDofs()); + if (_curCfg->storeVolume) _curStorage->volume.reserve(nAllocTimesteps * exporter.numVolumeDofs()); } @@ -795,11 +615,13 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder if ((_nOutletPorts == 1) && !_singleAsMultiPortUnitOps) { const std::vector layout = {_numTimesteps, _nComp}; + debugCheckTensorLayout(layout, _curStorage->outlet.size()); writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->outlet.data()); } else { const std::vector layout = {_numTimesteps, _nOutletPorts, _nComp}; + debugCheckTensorLayout(layout, _curStorage->outlet.size()); writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->outlet.data()); } } @@ -866,11 +688,13 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder if ((_nInletPorts == 1) && !_singleAsMultiPortUnitOps) { const std::vector layout = {_numTimesteps, _nComp}; + debugCheckTensorLayout(layout, _curStorage->inlet.size()); writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->inlet.data()); } else { const std::vector layout = {_numTimesteps, _nInletPorts, _nComp}; + debugCheckTensorLayout(layout, _curStorage->inlet.size()); writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->inlet.data()); } } @@ -881,67 +705,135 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder { oss.str(""); oss << prefix << "_BULK"; - _bulkLayout[0] = _numTimesteps; - writer.template tensor(oss.str(), _bulkLayout.size(), _bulkLayout.data(), _curStorage->bulk.data()); + + std::vector layout(0); + layout.reserve(4); + layout.push_back(_numTimesteps); + + if (_nAxialCells > 0) + layout.push_back(_nAxialCells); + if (_nRadialCells > 0) + layout.push_back(_nRadialCells); + layout.push_back(_nComp); + + debugCheckTensorLayout(layout, _curStorage->bulk.size()); + + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->bulk.data()); } if (_curCfg->storeParticle) { + std::vector layout(0); + layout.reserve(5); + layout.push_back(_numTimesteps); + + if (_nAxialCells > 0) + layout.push_back(_nAxialCells); + if (_nRadialCells > 0) + layout.push_back(_nRadialCells); + if (_nParShells.size() <= 1) { + if (_nParShells[0] >= 1) + layout.push_back(_nParShells[0]); + layout.push_back(_nComp); + + debugCheckTensorLayout(layout, _curStorage->particle[0].size()); + oss.str(""); oss << prefix << "_PARTICLE"; - _particleLayout[0][0] = _numTimesteps; - writer.template tensor(oss.str(), _particleLayout[0].size(), _particleLayout[0].data(), _curStorage->particle[0].data()); + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->particle[0].data()); } else { + const bool hasParticleShells = std::any_of(_nParShells.begin(), _nParShells.end(), [](unsigned int x) { return x >= 1; }); + if (hasParticleShells) + layout.push_back(0); + layout.push_back(_nComp); + for (std::size_t parType = 0; parType < _nParShells.size(); ++parType) { - std::vector& pl = _particleLayout[parType]; + if (hasParticleShells) + layout[layout.size() - 2] = _nParShells[parType]; + + debugCheckTensorLayout(layout, _curStorage->particle[parType].size()); + oss.str(""); oss << prefix << "_PARTICLE_PARTYPE_" << std::setfill('0') << std::setw(3) << std::setprecision(0) << parType; - pl[0] = _numTimesteps; - writer.template tensor(oss.str(), pl.size(), pl.data(), _curStorage->particle[parType].data()); + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->particle[parType].data()); } } } if (_curCfg->storeSolid) { + std::vector layout(0); + layout.reserve(5); + layout.push_back(_numTimesteps); + + if (_nAxialCells > 0) + layout.push_back(_nAxialCells); + if (_nRadialCells > 0) + layout.push_back(_nRadialCells); + if (_nParShells.size() <= 1) { + if (_nParShells[0] >= 1) + layout.push_back(_nParShells[0]); + layout.push_back(_nBoundStates[0]); + + debugCheckTensorLayout(layout, _curStorage->solid[0].size()); + oss.str(""); oss << prefix << "_SOLID"; - _solidLayout[0][0] = _numTimesteps; - writer.template tensor(oss.str(), _solidLayout[0].size(), _solidLayout[0].data(), _curStorage->solid[0].data()); + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->solid[0].data()); } else { + const bool hasParticleShells = std::any_of(_nParShells.begin(), _nParShells.end(), [](unsigned int x) { return x >= 1; }); + if (hasParticleShells) + layout.push_back(0); + layout.push_back(0); + for (std::size_t parType = 0; parType < _nParShells.size(); ++parType) { - std::vector& pl = _solidLayout[parType]; + if (hasParticleShells) + layout[layout.size() - 2] = _nParShells[parType]; + layout[layout.size() - 1] = _nBoundStates[parType]; + + debugCheckTensorLayout(layout, _curStorage->solid[parType].size()); + oss.str(""); oss << prefix << "_SOLID_PARTYPE_" << std::setfill('0') << std::setw(3) << std::setprecision(0) << parType; - pl[0] = _numTimesteps; - writer.template tensor(oss.str(), pl.size(), pl.data(), _curStorage->solid[parType].data()); + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->solid[parType].data()); } } } if (_curCfg->storeFlux) { + std::vector layout(0); + layout.reserve(5); + + layout.push_back(_numTimesteps); + layout.push_back(_nParShells.size()); + if (_nAxialCells > 0) + layout.push_back(_nAxialCells); + if (_nRadialCells > 0) + layout.push_back(_nRadialCells); + layout.push_back(_nComp); + + debugCheckTensorLayout(layout, _curStorage->flux.size()); + oss.str(""); oss << prefix << "_FLUX"; - _fluxLayout[0] = _numTimesteps; - writer.template tensor(oss.str(), _fluxLayout.size(), _fluxLayout.data(), _curStorage->flux.data()); + writer.template tensor(oss.str(), layout.size(), layout.data(), _curStorage->flux.data()); } if (_curCfg->storeVolume) { oss.str(""); oss << prefix << "_VOLUME"; - _fluxLayout[0] = _numTimesteps; writer.template matrix(oss.str(), _numTimesteps, _nVolumeDof, _curStorage->volume.data(), 1); } } @@ -962,6 +854,18 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder s.volume.clear(); } + template + void debugCheckTensorLayout(const std::vector& layout, std::size_t numElems) + { +#ifdef CADET_DEBUG + std::size_t layoutElems = 1; + for (T item : layout) + layoutElems *= item; + + cadet_assert(numElems == layoutElems); +#endif + } + StorageConfig _cfgSolution; StorageConfig _cfgSolutionDot; StorageConfig _cfgSensitivity; @@ -981,13 +885,10 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder std::vector _sens; std::vector _sensDot; - std::vector _bulkLayout; - std::vector> _particleLayout; - std::vector> _solidLayout; - std::vector _fluxLayout; - unsigned int _nComp; unsigned int _nVolumeDof; + unsigned int _nAxialCells; + unsigned int _nRadialCells; unsigned int _nInletPorts; unsigned int _nOutletPorts; std::vector _nParShells; @@ -998,10 +899,6 @@ class InternalStorageUnitOpRecorder : public ISolutionRecorder bool _needsReAlloc; - unsigned int _bulkCount; //!< Number of bulk mobile phase DOF blocks - std::vector _particleCount; //!< Number of particle mobile phase DOF blocks per particle type - std::vector _solidCount; //!< Number of solid phase DOF blocks per particle type - std::vector _axialCoords; std::vector _radialCoords; std::vector _particleCoords; diff --git a/src/libcadet/model/GeneralRateModel.cpp b/src/libcadet/model/GeneralRateModel.cpp index 50269aba8..1d184705c 100644 --- a/src/libcadet/model/GeneralRateModel.cpp +++ b/src/libcadet/model/GeneralRateModel.cpp @@ -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>& models) { models[GeneralRateModel::identifier()] = [](UnitOpIdx uoId) { return new GeneralRateModel(uoId); }; diff --git a/src/libcadet/model/GeneralRateModel.hpp b/src/libcadet/model/GeneralRateModel.hpp index 2772348eb..e27472351 100644 --- a/src/libcadet/model/GeneralRateModel.hpp +++ b/src/libcadet/model/GeneralRateModel.hpp @@ -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(_disc.nParCell[parType]) * strideParShell(parType); } - inline int strideFluxCell() const CADET_NOEXCEPT { return static_cast(_disc.nComp) * static_cast(_disc.nParType); } - inline int strideFluxParType() const CADET_NOEXCEPT { return static_cast(_disc.nComp); } + inline int strideFluxCell() const CADET_NOEXCEPT { return static_cast(_disc.nComp); } + inline int strideFluxParType() const CADET_NOEXCEPT { return static_cast(_disc.nComp * _disc.nCol); } inline int strideFluxComp() const CADET_NOEXCEPT { return 1; } // Offsets @@ -432,78 +432,60 @@ 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(_model._convDispOp.columnLength()) / static_cast(_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(pcr[i]); + return _disc.nParCell[parType]; } protected: @@ -511,11 +493,6 @@ class GeneralRateModel : public UnitOperationBase const Indexer _idx; const GeneralRateModel& _model; double const* const _data; - - const std::array _concentrationOrdering = { { StateOrdering::AxialCell, StateOrdering::Component } }; - const std::array _particleOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::ParticleShell, StateOrdering::Component } }; - const std::array _solidOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::ParticleShell, StateOrdering::Component, StateOrdering::BoundState } }; - const std::array _fluxOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::Component } }; }; }; diff --git a/src/libcadet/model/GeneralRateModel2D.cpp b/src/libcadet/model/GeneralRateModel2D.cpp index daee49dbb..410907df2 100644 --- a/src/libcadet/model/GeneralRateModel2D.cpp +++ b/src/libcadet/model/GeneralRateModel2D.cpp @@ -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>& models) { models[GeneralRateModel2D::identifier()] = [](UnitOpIdx uoId) { return new GeneralRateModel2D(uoId); }; diff --git a/src/libcadet/model/GeneralRateModel2D.hpp b/src/libcadet/model/GeneralRateModel2D.hpp index 71bd28c0b..80596e619 100644 --- a/src/libcadet/model/GeneralRateModel2D.hpp +++ b/src/libcadet/model/GeneralRateModel2D.hpp @@ -412,83 +412,66 @@ class GeneralRateModel2D : 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 _disc.nRad; } + virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT { return _disc.nCol; } + virtual unsigned int numSecondaryCoordinates() const CADET_NOEXCEPT { return _disc.nRad; } virtual unsigned int numInletPorts() const CADET_NOEXCEPT { return _disc.nRad; } virtual unsigned int numOutletPorts() const CADET_NOEXCEPT { return _disc.nRad; } 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 * _disc.nRad; } + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nRad; } virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nRad * _disc.nParCell[parType] * _disc.nComp; } - virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nRad * _disc.nParCell[parType] * _disc.strideBound[parType]; } - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nRad * _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 + port * _disc.nComp; - } - virtual double const* outlet(unsigned int port, unsigned int& stride) const + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { - stride = _idx.strideColComp(); - if (_model._convDispOp.currentVelocity(port) >= 0) - return &_idx.c(_data, _disc.nCol - 1, port, 0); - else - return &_idx.c(_data, 0, port, 0); + unsigned int nDofPerParType = 0; + for (unsigned int i = 0; i < _disc.nParType; ++i) + nDofPerParType += _disc.nParCell[i]; + return _disc.nCol * _disc.nRad * _disc.nComp * nDofPerParType; } - - 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 numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nCol * _disc.nRad * _disc.nParCell[parType] * _disc.strideBound[parType]; } + 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 * _disc.nRad * nDofPerParType; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nRad * _disc.nParType; } + virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; } - virtual unsigned int bulkMobilePhaseStride() const { return _idx.strideColRadialCell(); } - 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(_model._convDispOp.columnLength()) / static_cast(_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 int writeSecondaryCoordinates(double* coords) const { active const* const rc = _model._convDispOp.radialCenters(); for (unsigned int i = 0; i < _disc.nRad; ++i) coords[i] = static_cast(rc[i]); + return _disc.nRad; } - virtual void particleCoordinates(unsigned int parType, double* coords) const + 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(pcr[i]); + return _disc.nParCell[parType]; } protected: @@ -496,11 +479,6 @@ class GeneralRateModel2D : public UnitOperationBase const Indexer _idx; const GeneralRateModel2D& _model; double const* const _data; - - const std::array _concentrationOrdering = { { StateOrdering::AxialCell, StateOrdering::RadialCell, StateOrdering::Component } }; - const std::array _particleOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::RadialCell, StateOrdering::ParticleShell, StateOrdering::Component } }; - const std::array _solidOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::RadialCell, StateOrdering::ParticleShell, StateOrdering::Component, StateOrdering::BoundState } }; - const std::array _fluxOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::RadialCell, StateOrdering::Component } }; }; }; diff --git a/src/libcadet/model/InletModel.cpp b/src/libcadet/model/InletModel.cpp index 37feb689d..851dc44db 100644 --- a/src/libcadet/model/InletModel.cpp +++ b/src/libcadet/model/InletModel.cpp @@ -416,6 +416,34 @@ void InletModel::multiplyWithDerivativeJacobian(const SimulationTime& simTime, c std::fill_n(ret, numDofs(), 0.0); } + +int InletModel::Exporter::writeInlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int InletModel::Exporter::writeInlet(double* buffer) const +{ + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int InletModel::Exporter::writeOutlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int InletModel::Exporter::writeOutlet(double* buffer) const +{ + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + + void registerInletModel(std::unordered_map>& models) { models[InletModel::identifier()] = [](UnitOpIdx uoId) { return new InletModel(uoId); }; diff --git a/src/libcadet/model/InletModel.hpp b/src/libcadet/model/InletModel.hpp index 53878a15c..5ec4583b1 100644 --- a/src/libcadet/model/InletModel.hpp +++ b/src/libcadet/model/InletModel.hpp @@ -177,72 +177,41 @@ class InletModel : public IUnitOperation virtual bool hasVolume() const CADET_NOEXCEPT { return false; } virtual unsigned int numComponents() const CADET_NOEXCEPT { return _nComp; } - virtual unsigned int numAxialCells() const CADET_NOEXCEPT { return 0; } - virtual unsigned int numRadialCells() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT { return 0; } + 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 0; } virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 0; } virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT { return 0; } - virtual unsigned int numBulkDofs() const CADET_NOEXCEPT { return _nComp; } + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; } - virtual double const* concentration() const { return _data; } - virtual double const* flux() const { return nullptr; } - virtual double const* particleMobilePhase(unsigned int parType) const { return nullptr; } - virtual double const* solidPhase(unsigned int parType) const { return nullptr; } - virtual double const* volume() const { return nullptr; } - virtual double const* inlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data; - } - virtual double const* outlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data; - } - - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const - { - len = _concentrationOrdering.size(); - return _concentrationOrdering.data(); - } - - virtual StateOrdering const* fluxOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual unsigned int bulkMobilePhaseStride() const { return _nComp; } - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return 0; } - virtual unsigned int solidPhaseStride(unsigned int parType) const { return 0; } - - virtual void axialCoordinates(double* coords) const { } - virtual void radialCoordinates(double* coords) const { } - virtual void particleCoordinates(unsigned int parType, double* coords) const { } + virtual int writeMobilePhase(double* buffer) const { return 0; } + virtual int writeSolidPhase(double* buffer) const { return 0; } + virtual int writeParticleMobilePhase(double* buffer) const { return 0; } + virtual int writeSolidPhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleFlux(double* buffer) const { return 0; } + virtual int writeParticleFlux(unsigned int parType, double* buffer) const { return 0; } + 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 { return 0; } + virtual int writeSecondaryCoordinates(double* coords) const { return 0; } + virtual int writeParticleCoordinates(unsigned int parType, double* coords) const { return 0; } protected: double const* const _data; unsigned int _nComp; - - const std::array _concentrationOrdering = { { StateOrdering::Component } }; }; }; diff --git a/src/libcadet/model/LumpedRateModelWithPores.cpp b/src/libcadet/model/LumpedRateModelWithPores.cpp index 31644817c..3b18cb8eb 100644 --- a/src/libcadet/model/LumpedRateModelWithPores.cpp +++ b/src/libcadet/model/LumpedRateModelWithPores.cpp @@ -1513,6 +1513,118 @@ bool LumpedRateModelWithPores::setSensitiveParameter(const ParameterId& pId, uns return UnitOperationBase::setSensitiveParameter(pId, adDirection, adValue); } + +int LumpedRateModelWithPores::Exporter::writeMobilePhase(double* buffer) const +{ + const int blockSize = _disc.nComp * _disc.nCol; + std::copy_n(_idx.c(_data), blockSize, buffer); + return blockSize; +} + +int LumpedRateModelWithPores::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 LumpedRateModelWithPores::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 LumpedRateModelWithPores::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}) + _idx.strideParLiquid(); + for (unsigned int i = 0; i < _disc.nCol; ++i) + { + std::copy_n(ptr, _disc.strideBound[parType], buffer); + buffer += _disc.strideBound[parType]; + ptr += stride; + } + return _disc.nCol * _disc.strideBound[parType]; +} + +int LumpedRateModelWithPores::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) + { + std::copy_n(ptr, _disc.nComp, buffer); + buffer += _disc.nComp; + ptr += stride; + } + return _disc.nCol * _disc.nComp; +} + +int LumpedRateModelWithPores::Exporter::writeParticleFlux(double* buffer) const +{ + const int blockSize = numParticleFluxDofs(); + std::copy_n(_idx.jf(_data), blockSize, buffer); + return blockSize; +} + +int LumpedRateModelWithPores::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 LumpedRateModelWithPores::Exporter::writeInlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _disc.nComp, buffer); + return _disc.nComp; +} + +int LumpedRateModelWithPores::Exporter::writeInlet(double* buffer) const +{ + std::copy_n(_data, _disc.nComp, buffer); + return _disc.nComp; +} + +int LumpedRateModelWithPores::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 LumpedRateModelWithPores::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 registerLumpedRateModelWithPores(std::unordered_map>& models) { models[LumpedRateModelWithPores::identifier()] = [](UnitOpIdx uoId) { return new LumpedRateModelWithPores(uoId); }; diff --git a/src/libcadet/model/LumpedRateModelWithPores.hpp b/src/libcadet/model/LumpedRateModelWithPores.hpp index 4c601e646..47b2082bf 100644 --- a/src/libcadet/model/LumpedRateModelWithPores.hpp +++ b/src/libcadet/model/LumpedRateModelWithPores.hpp @@ -362,76 +362,52 @@ class LumpedRateModelWithPores : 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 1u; } + 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 1u; } + virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 1; } 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 numMobilePhaseDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; } virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; } + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nParType; } virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.strideBound[parType] * _disc.nCol; } - 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 - { - stride = _idx.strideColComp(); - if (_model._convDispOp.currentVelocity() >= 0) - return &_idx.c(_data, _disc.nCol - 1, 0); - else - return &_idx.c(_data, 0, 0); - } - - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const - { - len = _concentrationOrdering.size(); - return _concentrationOrdering.data(); - } - - virtual StateOrdering const* fluxOrdering(unsigned int& len) const + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT { - len = _fluxOrdering.size(); - return _fluxOrdering.data(); + unsigned int nDofPerParType = 0; + for (unsigned int i = 0; i < _disc.nParType; ++i) + nDofPerParType += _disc.strideBound[i]; + return _disc.nCol * nDofPerParType; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol * _disc.nParType; } + virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; } - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const - { - len = _particleOrdering.size(); - return _particleOrdering.data(); - } - - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const - { - len = _solidOrdering.size(); - return _solidOrdering.data(); - } - - virtual unsigned int bulkMobilePhaseStride() const { return _idx.strideColCell(); } - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return _idx.strideParBlock(parType); } - virtual unsigned int solidPhaseStride(unsigned int parType) const { return _idx.strideParBlock(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(_model._convDispOp.columnLength()) / static_cast(_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 { coords[0] = static_cast(_model._parRadius[parType]) * 0.5; + return 1; } protected: @@ -439,11 +415,6 @@ class LumpedRateModelWithPores : public UnitOperationBase const Indexer _idx; const LumpedRateModelWithPores& _model; double const* const _data; - - const std::array _concentrationOrdering = { { StateOrdering::AxialCell, StateOrdering::Component } }; - const std::array _particleOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::Component } }; - const std::array _solidOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::Component, StateOrdering::BoundState } }; - const std::array _fluxOrdering = { { StateOrdering::ParticleType, StateOrdering::AxialCell, StateOrdering::Component } }; }; }; diff --git a/src/libcadet/model/LumpedRateModelWithoutPores.cpp b/src/libcadet/model/LumpedRateModelWithoutPores.cpp index 828a36c36..b753a1564 100644 --- a/src/libcadet/model/LumpedRateModelWithoutPores.cpp +++ b/src/libcadet/model/LumpedRateModelWithoutPores.cpp @@ -1790,6 +1790,75 @@ bool LumpedRateModelWithoutPores::setSensitiveParameter(const ParameterId& pId, return UnitOperationBase::setSensitiveParameter(pId, adDirection, adValue); } + +int LumpedRateModelWithoutPores::Exporter::writeMobilePhase(double* buffer) const +{ + const int stride = _idx.strideColCell(); + double const* ptr = _data + _idx.offsetC(); + for (unsigned int i = 0; i < _disc.nCol; ++i) + { + std::copy_n(ptr, _disc.nComp, buffer); + buffer += _disc.nComp; + ptr += stride; + } + return _disc.nCol * _disc.nComp; +} + +int LumpedRateModelWithoutPores::Exporter::writeSolidPhase(double* buffer) const +{ + const int stride = _idx.strideColCell(); + double const* ptr = _data + _idx.offsetC() + _idx.strideColLiquid(); + for (unsigned int i = 0; i < _disc.nCol; ++i) + { + std::copy_n(ptr, _disc.strideBound, buffer); + buffer += _disc.strideBound; + ptr += stride; + } + return _disc.nCol * _disc.strideBound; +} + +int LumpedRateModelWithoutPores::Exporter::writeSolidPhase(unsigned int parType, double* buffer) const +{ + cadet_assert(parType == 0); + return writeSolidPhase(buffer); +} + +int LumpedRateModelWithoutPores::Exporter::writeInlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _disc.nComp, buffer); + return _disc.nComp; +} + +int LumpedRateModelWithoutPores::Exporter::writeInlet(double* buffer) const +{ + std::copy_n(_data, _disc.nComp, buffer); + return _disc.nComp; +} + +int LumpedRateModelWithoutPores::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 LumpedRateModelWithoutPores::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 registerLumpedRateModelWithoutPores(std::unordered_map>& models) { models[LumpedRateModelWithoutPores::identifier()] = [](UnitOpIdx uoId) { return new LumpedRateModelWithoutPores(uoId); }; diff --git a/src/libcadet/model/LumpedRateModelWithoutPores.hpp b/src/libcadet/model/LumpedRateModelWithoutPores.hpp index 729e690f5..b1716254c 100644 --- a/src/libcadet/model/LumpedRateModelWithoutPores.hpp +++ b/src/libcadet/model/LumpedRateModelWithoutPores.hpp @@ -278,18 +278,33 @@ class LumpedRateModelWithoutPores : 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 1u; } - virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 0u; } + virtual unsigned int numParticleTypes() const CADET_NOEXCEPT { return 1; } + virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 0; } virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT { return _disc.strideBound; } - virtual unsigned int numBulkDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; } - virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0u; } + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return _disc.nComp * _disc.nCol; } + virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _disc.strideBound * _disc.nCol; } - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return 0u; } - virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0u; } + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT { return _disc.strideBound * _disc.nCol; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return 0u; } + virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; } + + virtual int writeMobilePhase(double* buffer) const; + virtual int writeSolidPhase(double* buffer) const; + virtual int writeParticleMobilePhase(double* buffer) const { return 0; } + virtual int writeSolidPhase(unsigned int parType, double* buffer) const; + virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleFlux(double* buffer) const { return 0; } + virtual int writeParticleFlux(unsigned int parType, double* buffer) const { return 0; } + 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 double const* concentration() const { return _idx.c(_data); } virtual double const* flux() const { return nullptr; } @@ -310,51 +325,21 @@ class LumpedRateModelWithoutPores : public UnitOperationBase return &_idx.c(_data, 0, 0); } - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const - { - len = _concentrationOrdering.size(); - return _concentrationOrdering.data(); - } - - virtual StateOrdering const* fluxOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const - { - len = _solidOrdering.size(); - return _solidOrdering.data(); - } - - virtual unsigned int bulkMobilePhaseStride() const { return _idx.strideColCell(); } - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return 0; } - virtual unsigned int solidPhaseStride(unsigned int parType) const { return _idx.strideColCell(); } - - virtual void axialCoordinates(double* coords) const + virtual int writePrimaryCoordinates(double* coords) const { const double h = static_cast(_model._convDispOp.columnLength()) / static_cast(_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 { return 0; } protected: const Discretization& _disc; const Indexer _idx; const LumpedRateModelWithoutPores& _model; double const* const _data; - - const std::array _concentrationOrdering = { { StateOrdering::AxialCell, StateOrdering::Component } }; - const std::array _solidOrdering = { { StateOrdering::AxialCell, StateOrdering::Component, StateOrdering::BoundState } }; }; }; diff --git a/src/libcadet/model/OutletModel.cpp b/src/libcadet/model/OutletModel.cpp index 2ba53de96..b486e313d 100644 --- a/src/libcadet/model/OutletModel.cpp +++ b/src/libcadet/model/OutletModel.cpp @@ -228,6 +228,34 @@ void OutletModel::multiplyWithDerivativeJacobian(const SimulationTime& simTime, std::fill_n(ret, numDofs(), 0.0); } + +int OutletModel::Exporter::writeInlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int OutletModel::Exporter::writeInlet(double* buffer) const +{ + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int OutletModel::Exporter::writeOutlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int OutletModel::Exporter::writeOutlet(double* buffer) const +{ + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + + void registerOutletModel(std::unordered_map>& models) { models[OutletModel::identifier()] = [](UnitOpIdx uoId) { return new OutletModel(uoId); }; diff --git a/src/libcadet/model/OutletModel.hpp b/src/libcadet/model/OutletModel.hpp index 042b735f4..98e7f7690 100644 --- a/src/libcadet/model/OutletModel.hpp +++ b/src/libcadet/model/OutletModel.hpp @@ -159,72 +159,41 @@ class OutletModel : public IUnitOperation virtual bool hasVolume() const CADET_NOEXCEPT { return false; } virtual unsigned int numComponents() const CADET_NOEXCEPT { return _nComp; } - virtual unsigned int numAxialCells() const CADET_NOEXCEPT { return 0; } - virtual unsigned int numRadialCells() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT { return 0; } + 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 0; } virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 0; } virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT { return 0; } - virtual unsigned int numBulkDofs() const CADET_NOEXCEPT { return _nComp; } + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 0; } - virtual double const* concentration() const { return _data; } - virtual double const* flux() const { return nullptr; } - virtual double const* particleMobilePhase(unsigned int parType) const { return nullptr; } - virtual double const* solidPhase(unsigned int parType) const { return nullptr; } - virtual double const* volume() const { return nullptr; } - virtual double const* inlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data; - } - virtual double const* outlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data; - } - - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const - { - len = _concentrationOrdering.size(); - return _concentrationOrdering.data(); - } - - virtual StateOrdering const* fluxOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual unsigned int bulkMobilePhaseStride() const { return _nComp; } - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return 0; } - virtual unsigned int solidPhaseStride(unsigned int parType) const { return 0; } - - virtual void axialCoordinates(double* coords) const { } - virtual void radialCoordinates(double* coords) const { } - virtual void particleCoordinates(unsigned int parType, double* coords) const { } + virtual int writeMobilePhase(double* buffer) const { return 0; } + virtual int writeSolidPhase(double* buffer) const { return 0; } + virtual int writeParticleMobilePhase(double* buffer) const { return 0; } + virtual int writeSolidPhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleFlux(double* buffer) const { return 0; } + virtual int writeParticleFlux(unsigned int parType, double* buffer) const { return 0; } + 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 { return 0; } + virtual int writeSecondaryCoordinates(double* coords) const { return 0; } + virtual int writeParticleCoordinates(unsigned int parType, double* coords) const { return 0; } protected: double const* const _data; unsigned int _nComp; - - const std::array _concentrationOrdering = { { StateOrdering::Component } }; }; }; diff --git a/src/libcadet/model/StirredTankModel.cpp b/src/libcadet/model/StirredTankModel.cpp index eca14aecf..3e6cf83a8 100644 --- a/src/libcadet/model/StirredTankModel.cpp +++ b/src/libcadet/model/StirredTankModel.cpp @@ -1953,6 +1953,76 @@ void CSTRModel::checkAnalyticJacobianAgainstAd(active const* const adRes, unsign #endif + +unsigned int CSTRModel::Exporter::numSolidPhaseDofs() const CADET_NOEXCEPT +{ + return _totalBound; +} + +int CSTRModel::Exporter::writeMobilePhase(double* buffer) const +{ + std::copy_n(_data + _nComp, _nComp, buffer); + return _nComp; +} + +int CSTRModel::Exporter::writeSolidPhase(double* buffer) const +{ + if (_totalBound == 0) + return 0; + + std::copy_n(_data + 2 * _nComp, _totalBound, buffer); + return _totalBound; +} + +int CSTRModel::Exporter::writeSolidPhase(unsigned int parType, double* buffer) const +{ + if (_totalBound == 0) + return 0; + + cadet_assert(parType < _nParType); + + unsigned int offset = 0; + for (int i = 0; i < parType; ++i) + offset += _strideBound[i]; + + std::copy_n(_data + 2 * _nComp + offset, _strideBound[parType], buffer); + return _strideBound[parType]; +} + +int CSTRModel::Exporter::writeVolume(double* buffer) const +{ + *buffer = _data[2 * _nComp + _totalBound]; + return 1; +} + +int CSTRModel::Exporter::writeInlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int CSTRModel::Exporter::writeInlet(double* buffer) const +{ + std::copy_n(_data, _nComp, buffer); + return _nComp; +} + +int CSTRModel::Exporter::writeOutlet(unsigned int port, double* buffer) const +{ + cadet_assert(port == 0); + std::copy_n(_data + _nComp, _nComp, buffer); + return _nComp; +} + +int CSTRModel::Exporter::writeOutlet(double* buffer) const +{ + std::copy_n(_data + _nComp, _nComp, buffer); + return _nComp; +} + + + void registerCSTRModel(std::unordered_map>& models) { models[CSTRModel::identifier()] = [](UnitOpIdx uoId) { return new CSTRModel(uoId); }; diff --git a/src/libcadet/model/StirredTankModel.hpp b/src/libcadet/model/StirredTankModel.hpp index 950a85f47..d71bb5b53 100644 --- a/src/libcadet/model/StirredTankModel.hpp +++ b/src/libcadet/model/StirredTankModel.hpp @@ -183,66 +183,39 @@ class CSTRModel : public UnitOperationBase virtual bool hasVolume() const CADET_NOEXCEPT { return true; } virtual unsigned int numComponents() const CADET_NOEXCEPT { return _nComp; } - virtual unsigned int numAxialCells() const CADET_NOEXCEPT { return 0; } - virtual unsigned int numRadialCells() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numPrimaryCoordinates() const CADET_NOEXCEPT { return 0; } + 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 _nParType; } - virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 1u; } + virtual unsigned int numParticleShells(unsigned int parType) const CADET_NOEXCEPT { return 1; } virtual unsigned int numBoundStates(unsigned int parType) const CADET_NOEXCEPT { return _strideBound[parType]; } - virtual unsigned int numBulkDofs() const CADET_NOEXCEPT { return _nComp; } + virtual unsigned int numMobilePhaseDofs() const CADET_NOEXCEPT { return _nComp; } + virtual unsigned int numParticleMobilePhaseDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numParticleMobilePhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return 0; } + virtual unsigned int numSolidPhaseDofs() const CADET_NOEXCEPT; virtual unsigned int numSolidPhaseDofs(unsigned int parType) const CADET_NOEXCEPT { return _strideBound[parType]; } - virtual unsigned int numFluxDofs() const CADET_NOEXCEPT { return 0; } + virtual unsigned int numParticleFluxDofs() const CADET_NOEXCEPT { return 0; } virtual unsigned int numVolumeDofs() const CADET_NOEXCEPT { return 1; } - virtual double const* concentration() const { return _data + _nComp; } - virtual double const* flux() const { return nullptr; } - virtual double const* particleMobilePhase(unsigned int parType) const { return nullptr; } + virtual int writeMobilePhase(double* buffer) const; + virtual int writeSolidPhase(double* buffer) const; + virtual int writeSolidPhase(unsigned int parType, double* buffer) const; + virtual int writeParticleMobilePhase(double* buffer) const { return 0; } + virtual int writeParticleMobilePhase(unsigned int parType, double* buffer) const { return 0; } + virtual int writeParticleFlux(double* buffer) const { return 0; } + virtual int writeParticleFlux(unsigned int parType, double* buffer) const { return 0; } + virtual int writeVolume(double* buffer) const; + 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 double const* solidPhase(unsigned int parType) const { return _data + 2 * _nComp; } - virtual double const* volume() const { return _data + 2 * _nComp + _totalBound; } - virtual double const* inlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data; - } - virtual double const* outlet(unsigned int port, unsigned int& stride) const - { - stride = 1; - return _data + _nComp; - } - - virtual StateOrdering const* concentrationOrdering(unsigned int& len) const - { - len = _concentrationOrdering.size(); - return _concentrationOrdering.data(); - } - - virtual StateOrdering const* fluxOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* mobilePhaseOrdering(unsigned int& len) const - { - len = 0; - return nullptr; - } - - virtual StateOrdering const* solidPhaseOrdering(unsigned int& len) const - { - len = _solidOrdering.size(); - return _solidOrdering.data(); - } - - virtual unsigned int bulkMobilePhaseStride() const { return _nComp; } - virtual unsigned int particleMobilePhaseStride(unsigned int parType) const { return 0; } - virtual unsigned int solidPhaseStride(unsigned int parType) const { return _strideBound[parType]; } - - virtual void axialCoordinates(double* coords) const { } - virtual void radialCoordinates(double* coords) const { } - virtual void particleCoordinates(unsigned int parType, double* coords) const { } + + virtual int writePrimaryCoordinates(double* coords) const { return 0; } + virtual int writeSecondaryCoordinates(double* coords) const { return 0; } + virtual int writeParticleCoordinates(unsigned int parType, double* coords) const { return 0; } protected: double const* const _data; @@ -252,9 +225,6 @@ class CSTRModel : public UnitOperationBase unsigned int const* _strideBound; unsigned int const* _boundOffset; unsigned int _totalBound; - - const std::array _concentrationOrdering = { { StateOrdering::Component } }; - const std::array _solidOrdering = { { StateOrdering::ParticleType, StateOrdering::Component, StateOrdering::BoundState } }; }; }; diff --git a/test/ColumnTests.cpp b/test/ColumnTests.cpp index 85c55e10e..aea03e488 100644 --- a/test/ColumnTests.cpp +++ b/test/ColumnTests.cpp @@ -98,14 +98,14 @@ namespace virtual void unitOperationStructure(cadet::UnitOpIdx idx, const cadet::IModel& model, const cadet::ISolutionExporter& exporter) { - _fluxOffset = exporter.numComponents() * exporter.numInletPorts() + exporter.numBulkDofs(); + _fluxOffset = exporter.numComponents() * exporter.numInletPorts() + exporter.numMobilePhaseDofs(); const unsigned int nParType = exporter.numParticleTypes(); for (unsigned int i = 0; i < nParType; ++i) _fluxOffset += exporter.numParticleMobilePhaseDofs(i) + exporter.numSolidPhaseDofs(i); // Make sure this is correct - const unsigned int nFluxes = exporter.numComponents() * exporter.numAxialCells() * nParType * std::max(exporter.numRadialCells(), 1u); + const unsigned int nFluxes = exporter.numComponents() * exporter.numPrimaryCoordinates() * nParType * std::max(exporter.numSecondaryCoordinates(), 1u); REQUIRE(reinterpret_cast(&model)->numDofs() - nFluxes == _fluxOffset); }