#ifndef GUARD_898de4ae138e0ed305ef1399c66aa10a
#define GUARD_898de4ae138e0ed305ef1399c66aa10a

#define USING_DUNE_PYTHON 1
#include <config.h>
#include <dune/alugrid/dgf.hh>
#include <dune/alugrid/grid.hh>
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>
#include <dune/fem/gridpart/filter/simple.hh>
#include <dune/fem/gridpart/filteredgridpart.hh>
#include <dune/fempy/py/gridview.hh>
#include <dune/python/grid/gridview.hh>
#include <dune/python/grid/hierarchical.hh>
#include <dune/fem/function/localfunction/bindable.hh>
#include <dune/fem/common/intersectionside.hh>
#include <dune/python/pybind11/pybind11.h>
#include <dune/python/pybind11/extensions.h>
#include <dune/fempy/py/grid/gridpart.hh>
#include <dune/common/exceptions.hh>
#include <dune/fempy/function/virtualizedgridfunction.hh>
#include <dune/fempy/py/ufllocalfunction.hh>

namespace UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a
{

  // UFLLocalFunction
// ----------------

template< class GridPart, class Coeffu_h >
struct UFLLocalFunction
  : public Dune::Fem::BindableGridFunctionWithSpace<GridPart,Dune::Dim<1>>
{
  typedef GridPart GridPartType;
  typedef typename GridPartType::GridViewType GridView;
  typedef typename GridView::ctype ctype;
  typedef Dune::Fem::BindableGridFunctionWithSpace<GridPart,Dune::Dim<1>> BaseType;
  typedef Dune::Fem::GridFunctionSpace<GridPartType,Dune::Dim<1>> FunctionSpaceType;
  typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
  typedef typename GridPartType::IntersectionType IntersectionType;
  typedef typename EntityType::Geometry Geometry;
  typedef typename Geometry::GlobalCoordinate GlobalCoordinateType;
  typedef Dune::Fem::IntersectionSide Side;
  typedef double ConLame_1;
  typedef double ConLame_2;
  typedef std::tuple< std::shared_ptr< ConLame_1 >, std::shared_ptr< ConLame_2 > > ConstantTupleType;
  template< std::size_t i >
  using ConstantsRangeType = typename std::tuple_element_t< i, ConstantTupleType >::element_type;
  typedef std::tuple< Dune::Fem::GridFunctionSpace< GridPartType, Dune::FieldVector< double, 2 > > > CoefficientFunctionSpaceTupleType;
  typedef std::tuple< Coeffu_h > CoefficientTupleType;
  template< std::size_t i >
  using CoefficientFunctionSpaceType = std::tuple_element_t< i, CoefficientFunctionSpaceTupleType >;
  template< std::size_t i >
  using CoefficientRangeType = typename CoefficientFunctionSpaceType< i >::RangeType;
  template< std::size_t i >
  using CoefficientJacobianRangeType = typename CoefficientFunctionSpaceType< i >::JacobianRangeType;
  static constexpr bool gridPartValid = Dune::Fem::checkGridPartValid<GridPartType,Dune::Fem::ConstLocalFunction<Coeffu_h>>();
  template< std::size_t i >
  using CoefficientType = std::tuple_element_t< i, CoefficientTupleType >;
  template< std::size_t i >
  using ConstantType = typename std::tuple_element_t< i, ConstantTupleType >::element_type;
  using BaseType::entity;
  using BaseType::geometry;

  UFLLocalFunction ( const GridPartType &gridPart, const std::string &name, int order, const Coeffu_h &coeffu_h, const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
    : BaseType(gridPart,name,order),
      coefficients_( Dune::Fem::ConstLocalFunction< Coeffu_h >( coeffu_h ) )
  {
    std::get< 0 >( constants_ ) = std::make_shared< ConLame_1 >( (ConLame_1(0)) );
    std::get< 1 >( constants_ ) = std::make_shared< ConLame_2 >( (ConLame_2(0)) );
  }

  void bind ( const IntersectionType &intersection, Side side )
  {
    BaseType::bind(intersection, side);
    std::get< 0 >( coefficients_ ).bind( this->entity() );
  }

  void bind ( const EntityType &entity )
  {
    BaseType::bind(entity);
    std::get< 0 >( coefficients_ ).bind( this->entity() );
  }

  void unbind ()
  {
    BaseType::unbind();
    std::get< 0 >( coefficients_ ).unbind();
  }

  template< class Point >
  void evaluate ( const Point &x, typename FunctionSpaceType::RangeType &result ) const
  {
    using std::sqrt;
    typename CoefficientFunctionSpaceType< 0 >::JacobianRangeType tmp0 = jacobianCoefficient< 0 >( x );
    const auto tmp1 = (tmp0[ 0 ])[ 1 ] + (tmp0[ 1 ])[ 0 ];
    const auto tmp2 = tmp1 / 2;
    double tmp3 = constant< 1 >();
    const auto tmp4 = 2 * tmp3;
    const auto tmp5 = tmp4 * tmp2;
    const auto tmp6 = tmp5 * tmp5;
    const auto tmp7 = (tmp0[ 1 ])[ 1 ] + (tmp0[ 1 ])[ 1 ];
    const auto tmp8 = tmp7 / 2;
    const auto tmp9 = tmp4 * tmp8;
    const auto tmp10 = (tmp0[ 0 ])[ 0 ] + (tmp0[ 0 ])[ 0 ];
    const auto tmp11 = tmp10 / 2;
    const auto tmp12 = tmp11 + tmp8;
    double tmp13 = constant< 0 >();
    const auto tmp14 = tmp13 * tmp12;
    const auto tmp15 = tmp14 + tmp9;
    const auto tmp16 = tmp4 * tmp11;
    const auto tmp17 = tmp14 + tmp16;
    const auto tmp18 = tmp17 + tmp15;
    const auto tmp19 = 0.3333333333333333 * tmp18;
    const auto tmp20 = -1 * tmp19;
    const auto tmp21 = tmp15 + tmp20;
    const auto tmp22 = tmp21 * tmp21;
    const auto tmp23 = tmp22 + tmp6;
    const auto tmp24 = tmp17 + tmp20;
    const auto tmp25 = tmp24 * tmp24;
    const auto tmp26 = tmp25 + tmp6;
    const auto tmp27 = tmp26 + tmp23;
    const auto tmp28 = 1.5 * tmp27;
    const auto tmp29 = std::sqrt( tmp28 );
    result[ 0 ] = tmp29;
  }

  template< class Point >
  void jacobian ( const Point &x, typename FunctionSpaceType::JacobianRangeType &result ) const
  {
    using std::sqrt;
    typename CoefficientFunctionSpaceType< 0 >::JacobianRangeType tmp0 = jacobianCoefficient< 0 >( x );
    const auto tmp1 = (tmp0[ 0 ])[ 1 ] + (tmp0[ 1 ])[ 0 ];
    const auto tmp2 = tmp1 / 2;
    double tmp3 = constant< 1 >();
    const auto tmp4 = 2 * tmp3;
    const auto tmp5 = tmp4 * tmp2;
    const auto tmp6 = tmp5 * tmp5;
    const auto tmp7 = (tmp0[ 1 ])[ 1 ] + (tmp0[ 1 ])[ 1 ];
    const auto tmp8 = tmp7 / 2;
    const auto tmp9 = tmp4 * tmp8;
    const auto tmp10 = (tmp0[ 0 ])[ 0 ] + (tmp0[ 0 ])[ 0 ];
    const auto tmp11 = tmp10 / 2;
    const auto tmp12 = tmp11 + tmp8;
    double tmp13 = constant< 0 >();
    const auto tmp14 = tmp13 * tmp12;
    const auto tmp15 = tmp14 + tmp9;
    const auto tmp16 = tmp4 * tmp11;
    const auto tmp17 = tmp14 + tmp16;
    const auto tmp18 = tmp17 + tmp15;
    const auto tmp19 = 0.3333333333333333 * tmp18;
    const auto tmp20 = -1 * tmp19;
    const auto tmp21 = tmp15 + tmp20;
    const auto tmp22 = tmp21 * tmp21;
    const auto tmp23 = tmp22 + tmp6;
    const auto tmp24 = tmp17 + tmp20;
    const auto tmp25 = tmp24 * tmp24;
    const auto tmp26 = tmp25 + tmp6;
    const auto tmp27 = tmp26 + tmp23;
    const auto tmp28 = 1.5 * tmp27;
    const auto tmp29 = std::sqrt( tmp28 );
    const auto tmp30 = 2 * tmp29;
    typename CoefficientFunctionSpaceType< 0 >::HessianRangeType tmp31 = hessianCoefficient< 0 >( x );
    const auto tmp32 = ((tmp31[ 0 ])[ 1 ])[ 0 ] + ((tmp31[ 1 ])[ 0 ])[ 0 ];
    const auto tmp33 = tmp32 / 2;
    const auto tmp34 = tmp4 * tmp33;
    const auto tmp35 = tmp5 * tmp34;
    const auto tmp36 = tmp34 * tmp5;
    const auto tmp37 = tmp36 + tmp35;
    const auto tmp38 = ((tmp31[ 1 ])[ 1 ])[ 0 ] + ((tmp31[ 1 ])[ 1 ])[ 0 ];
    const auto tmp39 = tmp38 / 2;
    const auto tmp40 = tmp4 * tmp39;
    const auto tmp41 = ((tmp31[ 0 ])[ 0 ])[ 0 ] + ((tmp31[ 0 ])[ 0 ])[ 0 ];
    const auto tmp42 = tmp41 / 2;
    const auto tmp43 = tmp42 + tmp39;
    const auto tmp44 = tmp13 * tmp43;
    const auto tmp45 = tmp44 + tmp40;
    const auto tmp46 = tmp4 * tmp42;
    const auto tmp47 = tmp44 + tmp46;
    const auto tmp48 = tmp47 + tmp45;
    const auto tmp49 = 0.3333333333333333 * tmp48;
    const auto tmp50 = -1 * tmp49;
    const auto tmp51 = tmp45 + tmp50;
    const auto tmp52 = tmp21 * tmp51;
    const auto tmp53 = tmp51 * tmp21;
    const auto tmp54 = tmp53 + tmp52;
    const auto tmp55 = tmp54 + tmp37;
    const auto tmp56 = tmp47 + tmp50;
    const auto tmp57 = tmp24 * tmp56;
    const auto tmp58 = tmp56 * tmp24;
    const auto tmp59 = tmp58 + tmp57;
    const auto tmp60 = tmp59 + tmp37;
    const auto tmp61 = tmp60 + tmp55;
    const auto tmp62 = 1.5 * tmp61;
    const auto tmp63 = tmp62 / tmp30;
    const auto tmp64 = ((tmp31[ 0 ])[ 1 ])[ 1 ] + ((tmp31[ 1 ])[ 0 ])[ 1 ];
    const auto tmp65 = tmp64 / 2;
    const auto tmp66 = tmp4 * tmp65;
    const auto tmp67 = tmp5 * tmp66;
    const auto tmp68 = tmp66 * tmp5;
    const auto tmp69 = tmp68 + tmp67;
    const auto tmp70 = ((tmp31[ 1 ])[ 1 ])[ 1 ] + ((tmp31[ 1 ])[ 1 ])[ 1 ];
    const auto tmp71 = tmp70 / 2;
    const auto tmp72 = tmp4 * tmp71;
    const auto tmp73 = ((tmp31[ 0 ])[ 0 ])[ 1 ] + ((tmp31[ 0 ])[ 0 ])[ 1 ];
    const auto tmp74 = tmp73 / 2;
    const auto tmp75 = tmp74 + tmp71;
    const auto tmp76 = tmp13 * tmp75;
    const auto tmp77 = tmp76 + tmp72;
    const auto tmp78 = tmp4 * tmp74;
    const auto tmp79 = tmp76 + tmp78;
    const auto tmp80 = tmp79 + tmp77;
    const auto tmp81 = 0.3333333333333333 * tmp80;
    const auto tmp82 = -1 * tmp81;
    const auto tmp83 = tmp77 + tmp82;
    const auto tmp84 = tmp21 * tmp83;
    const auto tmp85 = tmp83 * tmp21;
    const auto tmp86 = tmp85 + tmp84;
    const auto tmp87 = tmp86 + tmp69;
    const auto tmp88 = tmp79 + tmp82;
    const auto tmp89 = tmp24 * tmp88;
    const auto tmp90 = tmp88 * tmp24;
    const auto tmp91 = tmp90 + tmp89;
    const auto tmp92 = tmp91 + tmp69;
    const auto tmp93 = tmp92 + tmp87;
    const auto tmp94 = 1.5 * tmp93;
    const auto tmp95 = tmp94 / tmp30;
    (result[ 0 ])[ 0 ] = tmp63;
    (result[ 0 ])[ 1 ] = tmp95;
  }

  template< class Point >
  void hessian ( const Point &x, typename FunctionSpaceType::HessianRangeType &result ) const
  {
    DUNE_THROW(Dune::NotImplemented,"hessian method could not be generated for local function (TooHighDerivative('CodeGenerator does not allow for third order derivatives, yet.'))");
    result=typename FunctionSpaceType::HessianRangeType(0);
  }

  template< std::size_t i >
  const ConstantType< i > &constant () const
  {
    return *std::get< i >( constants_ );
  }

  template< std::size_t i >
  ConstantType< i > &constant ()
  {
    return *std::get< i >( constants_ );
  }

  const ConLame_1 &conLame_1 () const
  {
    return *std::get< 0 >( constants_ );
  }

  ConLame_1 &conLame_1 ()
  {
    return *std::get< 0 >( constants_ );
  }

  const ConLame_2 &conLame_2 () const
  {
    return *std::get< 1 >( constants_ );
  }

  ConLame_2 &conLame_2 ()
  {
    return *std::get< 1 >( constants_ );
  }

  template< std::size_t i, class Point >
  typename CoefficientFunctionSpaceType< i >::RangeType evaluateCoefficient ( const Point &x ) const
  {
    typename CoefficientFunctionSpaceType< i >::RangeType result;
    std::get< i >( coefficients_ ).evaluate( x, result );;
    return result;
  }

  template< std::size_t i, class Point >
  typename CoefficientFunctionSpaceType< i >::JacobianRangeType jacobianCoefficient ( const Point &x ) const
  {
    typename CoefficientFunctionSpaceType< i >::JacobianRangeType result;
    std::get< i >( coefficients_ ).jacobian( x, result );;
    return result;
  }

  template< std::size_t i, class Point >
  typename CoefficientFunctionSpaceType< i >::HessianRangeType hessianCoefficient ( const Point &x ) const
  {
    typename CoefficientFunctionSpaceType< i >::HessianRangeType result;
    std::get< i >( coefficients_ ).hessian( x, result );;
    return result;
  }
  ConstantTupleType constants_;
  std::tuple< Dune::Fem::ConstLocalFunction< Coeffu_h > > coefficients_;
};

} // namespace UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a

PYBIND11_MODULE( localfunction_898de4ae138e0ed305ef1399c66aa10a_a524c1196983e65de1c06d7d6afdeb44, module )
{
  typedef UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > > LocalFunctionType;
  if constexpr( LocalFunctionType::gridPartValid )
  {
      auto cls = Dune::Python::insertClass<LocalFunctionType>(module,"UFLLocalFunction",Dune::Python::GenerateTypeName("UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > >"), Dune::Python::IncludeFiles({"python/dune/generated/localfunction_898de4ae138e0ed305ef1399c66aa10a_a524c1196983e65de1c06d7d6afdeb44.cc"})).first;
      Dune::FemPy::registerUFLLocalFunction( module, cls );
      cls.def( pybind11::init( [] ( pybind11::object gridView, const std::string &name, int order, const Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > &coeffu_h ) {return new LocalFunctionType( Dune::FemPy::gridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>(gridView),name,order, coeffu_h); } ), pybind11::keep_alive< 1, 2 >(), pybind11::keep_alive< 1, 3 >() );
      cls.def_property( "Lame_1", [] ( LocalFunctionType &self ) -> UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > >::ConLame_1 { return self.conLame_1(); }, [] ( LocalFunctionType &self, const UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > >::ConLame_1 &v ) { self.conLame_1() = v; } );
      cls.def_property( "Lame_2", [] ( LocalFunctionType &self ) -> UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > >::ConLame_2 { return self.conLame_2(); }, [] ( LocalFunctionType &self, const UFLLocalFunctions_898de4ae138e0ed305ef1399c66aa10a::UFLLocalFunction< typename Dune::FemPy::GridPart< Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true > >, Dune::FemPy::VirtualizedGridFunction< Dune::FemPy::GridPart<Dune::Fem::FilteredGridPart< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > >, Dune::Fem::SimpleFilter< Dune::FemPy::GridPart< Dune::Fem::AdaptiveLeafGridPart< Dune::ALUGrid< 2, 2, Dune::simplex > > > >, true >>, Dune::FieldVector< double, 2 > > >::ConLame_2 &v ) { self.conLame_2() = v; } );
      cls.def_property_readonly( "virtualized", [] ( LocalFunctionType& ) -> bool { return true;});
  }
}

#endif
