Skip to content
Snippets Groups Projects
functionalfactory.hh 2.98 KiB
Newer Older
#ifndef DUNE_TECTONIC_SPATIAL_SOLVING_GLOBALPROBLEM_HH
#define DUNE_TECTONIC_SPATIAL_SOLVING_GLOBALPROBLEM_HH

#include <vector>
#include <memory>

#include "tnnmg/functional.hh"

template <class NBodyAssembler, class Nonlinearity, class MatrixType, class VectorType>
class FunctionalFactory {
    using Vector = VectorType;
    using Matrix = MatrixType;

    const static int dims = Vector::block_type::dimension;

public:
    using Functional = Functional<Matrix&, Vector&, Nonlinearity&, Vector&, Vector&, typename Matrix::field_type>;

    FunctionalFactory(const NBodyAssembler& nBodyAssembler, const Nonlinearity& nonlinearity, const std::vector<Matrix>& matrices, const std::vector<Vector>& rhs) :
        nBodyAssembler_(nBodyAssembler),
        nonlinearity_(nonlinearity),
        rhs_(rhs) {

        const auto nBodies = nBodyAssembler_.nGrids();

        matrices_.resize(nBodies);
        for (int i=0; i<nBodies; i++) {
            matrices_[i] = &matrices[i];
        }
    }

    FunctionalFactory(const NBodyAssembler& nBodyAssembler, const Nonlinearity& nonlinearity, const std::vector<std::shared_ptr<Matrix>>& matrices, const std::vector<Vector>& rhs) :
        nBodyAssembler_(nBodyAssembler),
        nonlinearity_(nonlinearity),
        rhs_(rhs) {

        const auto nBodies = nBodyAssembler_.nGrids();

        matrices_.resize(nBodies);
        for (size_t i=0; i<nBodies; i++) {
            matrices_[i] = matrices[i].get();
      }
    }

    void build() {
        // assemble full global contact problem
        nBodyAssembler_.assembleJacobian(matrices_, bilinearForm_);
        nBodyAssembler_.assembleRightHandSide(rhs_, totalRhs_);

        // get lower and upper obstacles
        const auto& totalObstacles = nBodyAssembler_.totalObstacles_;
        lower_.resize(totalObstacles.size());
        upper_.resize(totalObstacles.size());

        for (size_t j=0; j<totalObstacles.size(); ++j) {
            const auto& totalObstaclesj = totalObstacles[j];
            auto& lowerj = lower_[j];
            auto& upperj = upper_[j];
          for (size_t d=0; d<dims; ++d) {
              lowerj[d] = totalObstaclesj[d][0];
              upperj[d] = totalObstaclesj[d][1];
          }
        }

        // set up functional
        functional_ = std::make_shared<Functional>(bilinearForm_, totalRhs_, nonlinearity_, lower_, upper_);
    }

    std::shared_ptr<Functional> functional() const {
        return functional_;
    }

    const Matrix& bilinearForm() const {
        return bilinearForm_;
    }

    const Vector& rhs() const {
        return totalRhs_;
    }

    const Vector& lower() const {
        return lower_;
    }

    const Vector& upper() const {
        return upper_;
    }

private:
    const NBodyAssembler nBodyAssembler_;
    const Nonlinearity& nonlinearity_;
    std::vector<const Matrix*> matrices_;
    const std::vector<Vector>& rhs_;

    Matrix bilinearForm_;
    Vector totalRhs_;
    Vector lower_;
    Vector upper_;

    std::shared_ptr<Functional> functional_;
};
#endif