// This file is part of GOAST, a C++ library for variational methods in Geometry Processing
//
// Copyright (C) 2021 Behrend Heeren & Josua Sassen, University of Bonn <goast@ins.uni-bonn.de>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef SHELL_SHELL_ENERGY_H
#define SHELL_SHELL_ENERGY_H

#include "bending_energy.h"
#include "membrane_energy.h"

namespace shell{
  double shell_energy( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def, const Eigen::MatrixXi &F,
                       const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                       const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI,
                       double bendingWeight, double mu = 1., double lambda = 1. );

  void shell_deformed_gradient( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def,
                                const Eigen::MatrixXi &F, const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                                const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double bendingWeight,
                                Eigen::MatrixXd &grad,
                                double mu = 1., double lambda = 1. );

  void shell_undeformed_gradient( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def,
                                  const Eigen::MatrixXi &F, const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                                  const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double bendingWeight,
                                  Eigen::MatrixXd &grad,
                                  double mu = 1., double lambda = 1. );

  void shell_deformed_hessian( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def,
                               const Eigen::MatrixXi &F, const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                               const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double bendingWeight,
                               Eigen::SparseMatrix<double> &Hess,
                               double mu = 1., double lambda = 1. );

  void shell_undeformed_hessian( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def,
                                 const Eigen::MatrixXi &F, const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                                 const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double bendingWeight,
                                 Eigen::SparseMatrix<double> &Hess,
                                 double mu = 1., double lambda = 1. );

  void shell_mixed_hessian( const Eigen::MatrixXd &V_undef, const Eigen::MatrixXd &V_def,
                            const Eigen::MatrixXi &F, const Eigen::MatrixXi &uE, const Eigen::VectorXi &EMAP,
                            const Eigen::MatrixXi &EF, const Eigen::MatrixXi &EI, double bendingWeight,
                            Eigen::SparseMatrix<double> &Hess,
                            bool FirstDerivativeWRTDef = true, double mu = 1., double lambda = 1. );
}
#endif //SHELL_SHELL_ENERGY_H

