#ifndef OERSTED_BOUNDARYCONDITION_H #define OERSTED_BOUNDARYCONDITION_H #include #include #include #include #include "Quadrature.hpp" #include "MatrixGroup.h" #include "FiniteElementMesh.h" // TODO: DiscreteBoundaryCondition versus ContinuousBoundaryCondition? Somehow need to apply to top level model and have that be translated to the discrete model // TODO: Boundary conditions should represent simple containers that know how to perform actions on matrices, parsing of boundaries to extract nodes should take place at a higher level class BoundaryCondition { public: virtual ~BoundaryCondition() {}; virtual void apply(std::vector> &triplets) const = 0; virtual void reduce(std::set> &index) const = 0; }; template class ZeroDirichlet : public BoundaryCondition {}; template class ZeroDirichlet<2, ElementOrder, QuadratureOrder> : public BoundaryCondition { public: ZeroDirichlet(std::vector>> boundaries) : Boundaries{boundaries} {}; void apply(std::vector> &triplets) const override {}; void reduce(std::set> &index) const override { for (auto const &b : Boundaries) { for (auto const &i : b->nodes()) { index.insert(i); } } }; protected: std::vector>> Boundaries; }; // TODO: Unify interface between PeriodicBoundary and SlidingBoundary (inherit a common interface/data members) template class PeriodicBoundaryCondition : public BoundaryCondition {}; template class PeriodicBoundaryCondition<2, ElementOrder, QuadratureOrder> : public BoundaryCondition { public: PeriodicBoundaryCondition(std::vector map, bool antiperiodic) : Map{map}, Antiperiodic{antiperiodic} {}; void apply(std::vector> &triplets) const override { double sign{1.0 - 2.0 * Antiperiodic}; for (BoundaryMap const &b : Map) { for (VariableMap const &v : b.map()) { triplets.push_back(Eigen::Triplet(v.first(), v.second(), sign * v.value())); } } } void reduce(std::set> &index) const override { for (BoundaryMap const &b : Map) { for (VariableMap const &v : b.map()) { index.insert(v.second()); } } } protected: std::vector Map; bool Antiperiodic; }; template class SlidingInterface : public BoundaryCondition {}; template class SlidingInterface<2,ElementOrder,QuadratureOrder> : public BoundaryCondition { public: SlidingInterface(std::vector first_vars, std::vector second_vars, std::vector vals, bool antiperiodic = false) : First{first_vars}, Second{second_vars}, Value{vals}, Antiperiodic{antiperiodic} {}; SlidingInterface& operator++() { std::rotate(Second.begin(), Second.begin() + 1, Second.end()); if (Antiperiodic) { std::rotate(Value.begin(), Value.begin() + 1, Value.end()); *(Value.end()) = -*(Value.end()); } } // TODO: SlidingInterface& operator--() {...}; void apply(std::vector> &triplets) const override { for(size_t i = 0; i!=Value.size();++i){ triplets.push_back(Eigen::Triplet(First[i],Second[i],Value[i])); } } void reduce(std::set> &index) const override { for (size_t i = 0; i!=Second.size();++i){ index.insert(Second[i]); } } protected: std::vector First; std::vector Second; std::vector Value; bool Antiperiodic; }; #endif //OERSTED_BOUNDARYCONDITION_H