#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AMDiS { // Forward declarations template class ParallelGlobalBasis; /// \brief The basic container that stores a base vector and a corresponding basis /** * \tparam GB Basis of the vector * \tparam T Type of the coefficients * \tparam TraitsType Collection of parameter for the linear-algebra backend **/ template > class DOFVector : public VectorFacade , private Observer , private Observer , private Observer { using Self = DOFVector; using Coefficients = VectorFacade; public: using GlobalBasis = GB; /// The index/size - type using size_type = typename GlobalBasis::size_type; /// The type of the elements of the DOFVector using value_type = T; /// Wrapper for the implementation of the transfer of data during grid adaption using DataTransfer = DataTransferWrapper; /// Collection of parameter for the linear-algebra backend using Traits = TraitsType; public: /// (1) Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer. DOFVector(std::shared_ptr const& basis, DataTransferOperation op = DataTransferOperation::INTERPOLATE) : Coefficients(*basis) , Observer(basis->gridView().grid()) , Observer(*basis) , Observer(basis->gridView().grid()) , dataTransfer_(op, basis) , basis_(basis) {} /// (2) Constructor. Forwards to (1) by wrapping reference into non-destroying /// shared_ptr, see \ref Dune::wrap_or_move. template )> DOFVector(GB_&& basis, DataTransferOperation op = DataTransferOperation::INTERPOLATE) : DOFVector(Dune::wrap_or_move(FWD(basis)), op) {} /// (3) Constructor. Forwards to (1) by creating a new basis from a dune-functions pre-basis factory. template >)> DOFVector(GV const& gridView, PBF const& preBasisFactory, DataTransferOperation op = DataTransferOperation::INTERPOLATE) : DOFVector(std::make_shared(gridView, preBasisFactory), op) {} std::shared_ptr const& basis() const { return basis_; } template auto child(TreePath const& path = {}) { auto&& tp = makeTreePath(path); return makeDiscreteFunction(coefficients(), *basis_, tp); } template auto child(TreePath const& path = {}) const { auto&& tp = makeTreePath(path); return makeDiscreteFunction(coefficients(), *basis_, tp); } /// Interpolation of GridFunction to DOFVector, assuming that there is no /// reference to this DOFVector in the expression. /// See \ref DiscreteFunction::interpolate_noalias template void interpolate_noalias(Expr&& expr, Tag strategy = {}) { child().interpolate_noalias(FWD(expr), strategy); } /// Interpolation of GridFunction to DOFVector. /// See \ref DiscreteFunction::interpolate template void interpolate(Expr&& expr, Tag strategy = {}) { child().interpolate(FWD(expr), strategy); } /// Interpolation of GridFunction to DOFVector. /// See \ref DiscreteFunction::interpolate template DOFVector& operator<<(Expr&& expr) { child().interpolate(FWD(expr)); return *this; } Coefficients const& coefficients() const { return static_cast(*this); } Coefficients& coefficients() { return static_cast(*this); } /// Write DOFVector to file void backup(std::string const& filename); /// Read backup data from file void restore(std::string const& filename); void resize() { Coefficients::resize(sizeInfo(*basis_)); } using Coefficients::resize; void resizeZero() { Coefficients::resizeZero(sizeInfo(*basis_)); } using Coefficients::resizeZero; /// Return the associated DataTransfer object DataTransfer const& dataTransfer() const { return dataTransfer_; } /// Return the associated DataTransfer object DataTransfer& dataTransfer() { return dataTransfer_; } /// Assign the DataTransfer object void setDataTransfer(DataTransfer const& dataTransfer) { dataTransfer_ = dataTransfer; } void setDataTransfer(DataTransfer&& dataTransfer) { dataTransfer_ = std::move(dataTransfer); } /// Create a new DataTransfer object based on the operation type void setDataTransfer(DataTransferOperation op) { setDataTransfer(DataTransfer(op, basis_)); } protected: /// Override of Observer update(event::preAdapt) method. Redirects to preAdapt method of the /// \ref DataTransfer object. void updateImpl(event::preAdapt e) override { dataTransfer_.preAdapt(*this, e.value); } /// Override of Observer update(event::adapt) method. Redirects to adapt method of the /// \ref DataTransfer object. void updateImpl(event::adapt e) override { assert(e.value); resize(); dataTransfer_.adapt(*this); } /// Override of Observer update(event::postAdapt) method. Redirects to postAdapt method of the /// \ref DataTransfer object. void updateImpl(event::postAdapt) override { dataTransfer_.postAdapt(*this); } private: /// Data interpolation when the grid changes, set by default /// to \ref DataTransferOperation::INTERPOLATE. DataTransfer dataTransfer_; std::shared_ptr basis_; }; // deduction guides template DOFVector(GB&& basis, DataTransferOperation op = DataTransferOperation::INTERPOLATE) -> DOFVector>; template DOFVector(GV const& gridView, PBF const& pbf, DataTransferOperation op = DataTransferOperation::INTERPOLATE) -> DOFVector; /// \brief Create a DOFVector from a basis. /** * This generator function accepts the basis as reference, temporary, or * shared_ptr. Internally the reference is wrapped into a non-destroying * shared_ptr and the temporary is moved into a new shared_ptr. * * The DataTransferOperation controls what is done during grid changes with the * DOFVector. The default is interpolation of the data to the new grid. See * \ref DataTransferOperation for more options. **/ template DOFVector, ValueType> makeDOFVector(GB&& basis, DataTransferOperation op = DataTransferOperation::INTERPOLATE) { return {FWD(basis), op}; } /// A Generator for a mutable \ref DiscreteFunction template auto makeDiscreteFunction(DOFVector& dofVec, Path const& path = {}) { return dofVec.child(path); } /// A Generator for a mutable \ref DiscreteFunction template auto makeDiscreteFunction(DOFVector const& dofVec, Path const& path = {}) { return dofVec.child(path); } } // end namespace AMDiS #include