Skip to content
Snippets Groups Projects
prestrainedMaterial.hh 34.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • #ifndef DUNE_MICROSTRUCTURE_PRESTRAINEDMATERIAL_HH
    #define DUNE_MICROSTRUCTURE_PRESTRAINEDMATERIAL_HH
    
    #include <dune/grid/uggrid.hh>
    #include <dune/grid/yaspgrid.hh>
    
    #include <dune/functions/gridfunctions/gridviewfunction.hh>
    
    #include <dune/functions/gridfunctions/gridviewentityset.hh>
    
    #include <dune/common/parametertree.hh>
    
    #include <dune/fufem/dunepython.hh>
    
    #include <dune/microstructure/matrix_operations.hh>
    
    
    // #include <dune/microstructure/materialDefinitions.hh> //deprecated
    
    using namespace MatrixOperations;
    
    using namespace Dune::Functions;
    using namespace Dune::Functions::BasisFactory;
    
    using std::pow;
    using std::abs;
    using std::sqrt;
    using std::sin;
    using std::cos;
    
    
    using std::shared_ptr;
    using std::make_shared;
    
    
    
    
    
    //   // ----------------------------------------------------------------------------------
    //   template<class Domain>
    //   int indicatorFunction_material(const Domain& x)
    //   {
    //     double theta=0.25;
    //     if (x[0] <(-0.5+theta) and x[2]<(-0.5+theta))
    //         return 1;    //#Phase1
    //     else if (x[1]<(-0.5+theta) and x[2]>(0.5-theta))
    //         return 2;    //#Phase2
    //     else 
    //         return 3;    //#Phase3
    //   }
    //  MatrixRT getL(const int& phase)
    //   {
    //       const FieldVector<double,3> mu     = {80.0, 80.0, 60.0};
    //       const FieldVector<double,3> lambda = {80.0, 80.0, 25.0};
    
    
    
    //       if (phase == 1)
    //         return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); //#Phase1 //Isotrop(mu,lambda)
    //       else if (phase == 2)
    //         return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); //#Phase2
    //       else 
    //         return 2.0 * mu[2] * sym(G) + lambda[2] * trace(sym(G)) * Id(); //#Phase3
    //   }
    //   MatrixRT prestrain_material(const int& phase)
    //   {
    //       if (phase == 1)
    //         return {{1.0, 0.0, 0.0},    //#Phase1
    //                 {0.0, 1.0, 0.0},
    //                 {0.0, 0.0, 1.0}
    //                };
    //       else if (phase == 2)
    //         return {{1.0, 0.0, 0.0},    //#Phase2
    //                 {0.0, 1.0, 0.0},
    //                 {0.0, 0.0, 1.0}
    //                };
    //       else 
    //         return {{0.0, 0.0, 0.0},    //#Phase3
    //                 {0.0, 0.0, 0.0},
    //                 {0.0, 0.0, 0.0}
    //                };
    //   }
    
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    //--------------------------------------------------------
    template <class GridView>         
    
    class prestrainedMaterial
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      static const int dimworld = 3;  //GridView::dimensionworld;
      static const int dim = 3;       //Domain::dimension;
    
      using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
    
      using LocalDomain = typename GridView::template Codim<0>::Geometry::LocalCoordinate;
      using Element = typename GridViewEntitySet<GridView, 0>::Element;
    
      using ScalarRT = Dune::FieldVector< double, 1>;
      using VectorRT = Dune::FieldVector< double, dimworld>;
      using MatrixRT = Dune::FieldMatrix< double, dimworld, dimworld>;
    
      using FuncScalar = std::function< double(const Domain&) >;
    
      using Func2int = std::function< int(const Domain&) >;
    
      using Func2Tensor = std::function< MatrixRT(const Domain&) >;
      using Func2TensorParam = std::function< MatrixRT(const MatrixRT& ,const Domain&) >;
    
      using Func2TensorPhase = std::function< MatrixRT(const MatrixRT& ,const int&) >;
    
      using MatrixFunc  = std::function< MatrixRT(const MatrixRT&) >;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      using MatrixPhase = std::function< MatrixRT(const int&) >;
    
      // using VoigtMatrix = FieldMatrix< double, 6, 6>;
    
    
      const GridView& gridView_;
    
      const Dune::ParameterTree& parameterSet_;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      std::string materialFunctionName_;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      // MatrixFunc L1_;
      // MatrixFunc L2_;
      // MatrixFunc L3_;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      // Elasticity tensors (in voigt notation)
    
      Dune::FieldMatrix<double,6,6> L1_;
      Dune::FieldMatrix<double,6,6> L2_;
      Dune::FieldMatrix<double,6,6> L3_;
      Dune::FieldMatrix<double,6,6> L4_; //not used yet
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
      Func2Tensor prestrain1_;
      Func2Tensor prestrain2_; 
      Func2Tensor prestrain3_;  
      Func2Tensor prestrain4_;  //not used yet
    
      Python::Module module_;
    
      // const FuncScalar mu_; 
      // const FuncScalar lambda_; 
      // const int phases_;
      // Func2Tensor elasticityTensor_;
    
      // Func2TensorParam elasticityTensor_;
      Func2TensorPhase elasticityTensor_;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      MatrixPhase prestrain_;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      Func2int indicatorFunction_;
    
      GridViewFunction<int(const Domain&), GridView> indicatorFunctionGVF_;
      LocalFunction<int(const Domain&), typename GridViewEntitySet<GridView, 0>::Element >  localIndicatorFunction_;
    
    
      //Transformation matrix for Voigt notation
    
      Dune::FieldMatrix<double,6,6> D_ = {{1.0, 0.0, 0.0, 0.0 , 0.0, 0.0},
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                                  {0.0, 1.0, 0.0, 0.0 , 0.0, 0.0},
                                  {0.0, 0.0, 1.0, 0.0 , 0.0, 0.0},
                                  {0.0, 0.0, 0.0, sqrt(2.0) , 0.0, 0.0},
                                  {0.0, 0.0, 0.0, 0.0 , sqrt(2.0), 0.0},
                                  {0.0, 0.0, 0.0, 0.0 , 0.0, sqrt(2.0)}
                                };
    
      Dune::FieldMatrix<double,6,6> D_inv = {{1.0, 0.0, 0.0, 0.0 , 0.0, 0.0},
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                                      {0.0, 1.0, 0.0, 0.0 , 0.0, 0.0},
                                      {0.0, 0.0, 1.0, 0.0 , 0.0, 0.0},
                                      {0.0, 0.0, 0.0, 1.0/sqrt(2.0) , 0.0, 0.0},
                                      {0.0, 0.0, 0.0, 0.0 , 1.0/sqrt(2.0), 0.0},
                                      {0.0, 0.0, 0.0, 0.0 , 0.0, 1.0/sqrt(2.0)}
                                    };
    
    public: 
        ///////////////////////////////
        // constructor
        ///////////////////////////////
    
        prestrainedMaterial(const GridView gridView,
    
                            const Dune::ParameterTree& parameterSet)
    
                           : gridView_(gridView), 
                             parameterSet_(parameterSet)
    
    	  std::string materialFunctionName_ = parameterSet.get<std::string>("materialFunction", "material_1");
    
        std::cout << "materialFunctionName_ : " << materialFunctionName_ << std::endl;
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // setupMaterial(materialFunctionName_);  //old-Version
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        module_ = Python::import(materialFunctionName_);  //TODO use this instead?
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
        // const FieldVector<double,3> mu     = {80.0, 80.0, 60.0};
        // const FieldVector<double,3> lambda = {80.0, 80.0, 25.0};
    
    
        //elastic moduli in the order (E1,E2,E3,G12,G23,G31,nu12,nu13,nu23)
    
        //-- Walnut see [Dimwoodie; Timber its nature and behavior p.109]
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // const FieldVector<double,9> walnut_parameters={11.2e3,630,1190,700,230,960,0.63 ,0.49,0.37};
    
    
        //-- Norway spruce see [Dimwoodie; Timber its nature and behavior p.109]
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // const FieldVector<double,9> Nspruce_parameters={10.7e3,430,710,620,23,500, 0.51 ,0.38,0.31};
    
    
        //frame vectors
        VectorRT e1 = {1.0,0.0,0.0};
        VectorRT e2 = {0.0,1.0,0.0};
        VectorRT e3 = {0.0,0.0,1.0};
    
    
    
        // L1_ = orthotropic(e1,e2,e3,walnut_parameters);
        // L2_ = orthotropic(e1,e2,e3,Nspruce_parameters);
        // L3_ = orthotropic(e1,e2,e3,Nspruce_parameters);
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        setup(materialFunctionName_);
        // setup("material");
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        indicatorFunctionGVF_ = Dune::Functions::makeGridViewFunction(indicatorFunction_, gridView_);
        localIndicatorFunction_ = localFunction(indicatorFunctionGVF_);
    
    
    
        // L1_ = transversely_isotropic(e1,e2,e3, {11.2e3,1190,960,0.63 ,0.37});
        // L2_ = transversely_isotropic(e1,e2,e3, {11.2e3,1190,960,0.63, 0.37});
        // L3_ = transversely_isotropic(e1,e2,e3, {10.7e3,710 ,500,0.51 ,0.31});
    
    
        // L1_ = isotropic(mu[0],lambda[0]);
        // L2_ = isotropic(mu[1],lambda[1]);
        // L3_ = isotropic(mu[2],lambda[2]); 
    
    
    
    
        // L1_ = {{lambda[0]+2.0*mu[0], lambda[0], lambda[0], 0.0 , 0.0, 0.0},
        //         {lambda[0], lambda[0]+2*mu[0], lambda[0], 0.0 ,0.0 ,0.0},
        //         {lambda[0], lambda[0],  lambda[0]+2.0*mu[0], 0.0, 0.0, 0.0},
        //         { 0.0 ,0.0, 0.0, 2.0*mu[0], 0.0, 0.0},
        //         { 0.0 ,0.0, 0.0, 0.0, 2.0*mu[0], 0.0},
        //         { 0.0 ,0.0, 0.0, 0.0, 0.0, 2.0*mu[0]}
        //       };
    
        // L2_ = {{lambda[1]+2.0*mu[1], lambda[1], lambda[1], 0.0 , 0.0, 0.0},
        //         {lambda[1], lambda[1]+2*mu[1], lambda[1], 0.0 ,0.0 ,0.0},
        //         {lambda[1], lambda[1],  lambda[1]+2.0*mu[1], 0.0, 0.0, 0.0},
        //         { 0.0 ,0.0, 0.0, 2.0*mu[1], 0.0, 0.0},
        //         { 0.0 ,0.0, 0.0, 0.0, 2.0*mu[1], 0.0},
        //         { 0.0 ,0.0, 0.0, 0.0, 0.0, 2.0*mu[1]}
        //       };
    
        // L3_ = {{lambda[2]+2.0*mu[2], lambda[2], lambda[2], 0.0 , 0.0, 0.0},
        //       {lambda[2], lambda[2]+2.0*mu[2], lambda[2], 0.0 ,0.0 ,0.0},
        //       {lambda[2], lambda[2],  lambda[2]+2.0*mu[2], 0.0, 0.0, 0.0},
        //       { 0.0 ,0.0, 0.0, 2.0*mu[2], 0.0, 0.0},
        //       { 0.0 ,0.0, 0.0, 0.0, 2.0*mu[2], 0.0},
        //       { 0.0 ,0.0, 0.0, 0.0, 0.0, 2.0*mu[2]}
        //     };
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // printmatrix(std::cout, D_, "D_", "--");
        // printmatrix(std::cout, D_inv, "D_inv", "--");
    
        // printmatrix(std::cout, L1_, "L1_", "--");
        // L1_.leftmultiply(D_inv);
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // printmatrix(std::cout, L1_, "L1_.leftmultiply(D_inv)", "--");
        // L1_.rightmultiply(D_);
        // printmatrix(std::cout, L1_, "L1_.rightmultiply(D_)", "--");
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // Python::Module module = Python::import(materialFunctionName_);
        // elasticityTensor_ = Python::make_function<MatrixRT>(module.get("L"));
        // elasticityTensor_ = setupElasticityTensor(materialFunctionName_);
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // auto indicatorFunction = Python::make_function<int>(module.get("indicatorFunction"));
        // indicatorFunction_ = Python::make_function<int>(module.get("indicatorFunction"));
        // indicatorFunction_ =  Dune::Functions::makeGridViewFunction(indicatorFunction , gridView_);
    
        // module.get("Phases").toC<int>(Phases_);
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // L1_ = Python::make_function<MatrixRT>(module.get("L1"));
        // L2_ = Python::make_function<MatrixRT>(module.get("L2"));
        // L3_ = Python::make_function<MatrixRT>(module.get("L3"));
    
        // bool isotropic_ = true; // read from module File 
        // auto Test = Dune::Functions::makeGridViewFunction(MAT<Domain> , gridView_); //not working 
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
    Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Module module, int phase)
    
    {
      std::string materialParameters_string;
      std::cout << "Setup phase "<< phase << " as " << phaseType << " material." << std::endl;
    
      switch (phase)
      {
        case 1:
        {
          materialParameters_string = "materialParameters_phase1";
          break;
        }
        case 2:
        {
          materialParameters_string = "materialParameters_phase2";
          break;
        }
        case 3:
        {
          materialParameters_string= "materialParameters_phase3";
          break;
        }
        default:
    
        DUNE_THROW(Dune::Exception, "Phase number not implemented.");
    
            break;
      }
    
      if(phaseType == "isotropic")                           //TODO SetupPHASE (phase_type)
      {
    
          Dune::FieldVector<double,2> materialParameters(0);
          module.get(materialParameters_string).toC<Dune::FieldVector<double,2>>(materialParameters);
    
          return isotropic(materialParameters[0],materialParameters[1]);
      }
      if(phaseType == "orthotropic")                           //TODO SetupPHASE (phase_type)
      {
          // TODO: Generalize here:
          //frame vectors
          VectorRT e1 = {1.0,0.0,0.0};
          VectorRT e2 = {0.0,1.0,0.0};
          VectorRT e3 = {0.0,0.0,1.0};
    
          Dune::FieldVector<double,9> materialParameters(0);
          module.get(materialParameters_string).toC<Dune::FieldVector<double,9>>(materialParameters);
    
          return orthotropic(e1,e2,e3,materialParameters);
      }
      if(phaseType == "transversely_isotropic")                           //TODO SetupPHASE (phase_type)
      {
          // TODO: Generalize here:
          //frame vectors
          VectorRT e1 = {1.0,0.0,0.0};
          VectorRT e2 = {0.0,1.0,0.0};
          VectorRT e3 = {0.0,0.0,1.0};
    
          Dune::FieldVector<double,5> materialParameters(0);
          module.get(materialParameters_string).toC<Dune::FieldVector<double,5>>(materialParameters);
    
          return transversely_isotropic(e1,e2,e3,materialParameters);
      }
      if(phaseType == "general_anisotropic")                           //TODO SetupPHASE (phase_type)
      {
          // TODO: Generalize here:
          //frame vectors
          VectorRT e1 = {1.0,0.0,0.0};
          VectorRT e2 = {0.0,1.0,0.0};
          VectorRT e3 = {0.0,0.0,1.0};
    
          Dune::FieldMatrix<double,6,6> materialParameters(0); //compliance matric
          module.get(materialParameters_string).toC<Dune::FieldMatrix<double,6,6>>(materialParameters);
    
          printmatrix(std::cout, materialParameters, "Compliance matrix used:", "--");
          return general_anisotropic(e1,e2,e3,materialParameters);
      }
      else
    
        DUNE_THROW(Dune::Exception, " Unknown material class for phase ");
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      //---function that determines elasticity Tensor 
      // void setup(const std::string name, const int Phases)  // cant use materialFunctionName_ here!?
      void setup(const std::string name)  // cant use materialFunctionName_ here!?
      {
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        Python::Module module = Python::import(name);
        indicatorFunction_ = Python::make_function<int>(module.get("indicatorFunction"));
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        std::cout << "---- setup material... " << std::endl;
        
        int Phases;
        module.get("Phases").toC<int>(Phases);
        std::cout << "Number of Phases: " << Phases  << std::endl;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        switch (Phases)
        {
        case 1:
        {
          std::string phase1_type;
          module.get("phase1_type").toC<std::string>(phase1_type);
          L1_ = setupPhase(phase1_type, module,1);
          prestrain1_ = Python::make_function<MatrixRT>(module.get("prestrain_phase1"));
          break;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        case 2:
        {
          std::string phase1_type;
          module.get("phase1_type").toC<std::string>(phase1_type);
          std::string phase2_type;
          module.get("phase2_type").toC<std::string>(phase2_type);
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
          L1_ = setupPhase(phase1_type, module,1);
          L2_ = setupPhase(phase2_type, module,2);
          prestrain1_ = Python::make_function<MatrixRT>(module.get("prestrain_phase1"));
          prestrain2_ = Python::make_function<MatrixRT>(module.get("prestrain_phase2"));
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
          break;
        }
        case 3:
        {
          std::string phase1_type;
          module.get("phase1_type").toC<std::string>(phase1_type);
          std::string phase2_type;
          module.get("phase2_type").toC<std::string>(phase2_type);
          std::string phase3_type;
          module.get("phase3_type").toC<std::string>(phase3_type);
    
          L1_ = setupPhase(phase1_type, module,1);
          L2_ = setupPhase(phase2_type, module,2);
          L3_ = setupPhase(phase3_type, module,3);
    
          prestrain1_ = Python::make_function<MatrixRT>(module.get("prestrain_phase1"));
          prestrain2_ = Python::make_function<MatrixRT>(module.get("prestrain_phase2"));
          prestrain3_ = Python::make_function<MatrixRT>(module.get("prestrain_phase3"));
            
          // if (phase1_type == "isotropic" )                           //TODO SetupPHASE (phase_type)
          // {
          //   FieldVector<double,2> materialParameters_phase1(0);
          //   module.get("materialParameters_phase1").toC<FieldVector<double,2>>(materialParameters_phase1);
          //   L1_ = isotropic(materialParameters_phase1[0],materialParameters_phase1[1]);
          // }
          // if (phase2_type == "isotropic" )                           //TODO SetupPHASE (phase_type)
          // {
          //   FieldVector<double,2> materialParameters_phase2(0);
          //   module.get("materialParameters_phase2").toC<FieldVector<double,2>>(materialParameters_phase2);
          //   L2_ = isotropic(materialParameters_phase2[0],materialParameters_phase2[1]);
          // }
          // if (phase3_type == "isotropic" )                           //TODO SetupPHASE (phase_type)
          // {
          //   FieldVector<double,2> materialParameters_phase3(0);
          //   module.get("materialParameters_phase3").toC<FieldVector<double,2>>(materialParameters_phase3);
          //   L3_ = isotropic(materialParameters_phase3[0],materialParameters_phase3[1]);
          // }
          break;
        }
        default:
          break;
        }
        std::cout << "Material setup done." << std::endl;
      }
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      ///////////////////////////////////////////////////////////////////////
    
      // //---function that determines elasticity Tensor 
      //   void setupMaterial(const std::string name)  // cant use materialFunctionName_ here!?
      //   {
      //       // std::cout << "Using material definition:" << name << std::endl;
      //       if(name == "material_neukamm")
      //       {   
      //         indicatorFunction_ = indicatorFunction_material_neukamm<Domain>;
      //         elasticityTensor_ = material_neukamm;
      //         prestrain_ = prestrain_material_neukamm;
      //       }
      //       else if(name == "two_phase_material_1")
      //       {
      //         indicatorFunction_ = indicatorFunction_two_phase_material_1<Domain>;
      //         elasticityTensor_ = two_phase_material_1;
      //         prestrain_ = prestrain_two_phase_material_1;
      //       }
      //       else if(name == "two_phase_material_2")
      //       {
      //         indicatorFunction_ = indicatorFunction_two_phase_material_2<Domain>;
      //         elasticityTensor_ = two_phase_material_2;
      //         prestrain_ = prestrain_two_phase_material_2;
      //       }
      //       else if(name == "homogeneous")
      //       {
      //         indicatorFunction_ = indicatorFunction_material_homogeneous<Domain>;
      //         elasticityTensor_ = material_homogeneous;
      //         prestrain_ = prestrain_homogeneous;
      //       }
      //       else
      //        DUNE_THROW(Exception, "There exists no material with this name "); 
      //   }
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
      ////////////////////////////////////////////////////////
      //      MATERIAL CLASSES DEFINITIONS:
      ////////////////////////////////////////////////////////
    
    
      //--- Definition of isotropic elasticity tensor (in voigt notation)
    
      Dune::FieldMatrix<double,6,6> isotropic(const double& mu, const double& lambda)
    
      {
          return {{lambda+2.0*mu, lambda       , lambda       , 0.0   , 0.0   , 0.0   },
                  {lambda       , lambda+2.0*mu, lambda       , 0.0   , 0.0   , 0.0   },
                  {lambda       , lambda       , lambda+2.0*mu, 0.0   , 0.0   , 0.0   },
                  {  0.0        ,  0.0         , 0.0          , 2.0*mu, 0.0   , 0.0   },
                  {  0.0        ,  0.0         , 0.0          , 0.0   , 2.0*mu, 0.0   },
                  {  0.0        ,  0.0         , 0.0          , 0.0   , 0.0   , 2.0*mu}
                 };
      }
    
      //-------------------------------------------------------------------------------
    
    
      //--- Definition of orthotropic elasticity tensor (in voigt notation)
      // - Input: (Youngs modulus, shear modulus, Poisson ratio): {E1,E2,E3,G12,G23,G31,nu12,nu13,nu23}
      // - Output: compliance Matrix
    
      Dune::FieldMatrix<double,6,6> orthotropic(const VectorRT& framevector1,
    
                                          const VectorRT& framevector2,
                                          const VectorRT& framevector3,
    
                                          const Dune::FieldVector<double,9>& p //elastic moduli {E1,E2,E3,G12,G23,G31,nu12,nu13,nu23}
    
                                          ) 
      {
        // (see https://en.wikipedia.org/wiki/Orthotropic_material)
          auto E_1 = p[0];
          auto E_2 = p[1];
          auto E_3 = p[2];
          auto G_12 = p[3];
          auto G_23 = p[4];
          auto G_31 = p[5];
          auto nu_12 = p[6];
          auto nu_13 = p[7];
          auto nu_23 = p[8];
          //other three poisson ratios are not independent 
          auto nu_21 = (p[6]/p[0])*p[1];
          auto nu_31 = (p[7]/p[0])*p[2];
          auto nu_32 = (p[8]/p[1])*p[2]; 
    
          //compliance matrix
    
          Dune::FieldMatrix<double,6,6> C = {{1.0/E_1      , -nu_21/E_2   , -nu_31/E_3   , 0.0     , 0.0     , 0.0   },
    
                                           {-nu_12/E_1   , 1.0/E_2      , -nu_32/E_3   , 0.0     , 0.0     , 0.0   },
                                           {-nu_13/E_1   , -nu_23/E_2   , 1.0/E_3      , 0.0     , 0.0     , 0.0   },
                                           {  0.0        ,  0.0         , 0.0          , 1.0/G_23, 0.0     , 0.0   },
                                           {  0.0        ,  0.0         , 0.0          , 0.0     , 1.0/G_31, 0.0   },
                                           {  0.0        ,  0.0         , 0.0          , 0.0     , 0.0     , 1.0/G_12}
                                          };
    
        
          // printmatrix(std::cout, C, "C", "--");
    
          //--- return elasticity tensor 
          C.invert();
          // printmatrix(std::cout, C, "C after .invert()", "--");
          return C;
      }
    
      //-------------------------------------------------------------------------------
    
    
    
      //--- Definition of transversely isotropic elasticity tensor (in voigt notation)
      // - Input: (Youngs modulus, shear modulus, Poisson ratio): {E1,E2,G12,nu12,nu23}
      // - Output: compliance Matrix
    
      Dune::FieldMatrix<double,6,6> transversely_isotropic(const VectorRT& framevector1,
    
                                                     const VectorRT& framevector2,
                                                     const VectorRT& framevector3,
    
                                                     const Dune::FieldVector<double,5>& p //elastic moduli {E1,E2,G12,nu12,nu23}
    
                                                     ) 
      {
        // (see https://en.wikipedia.org/wiki/Poisson%27s_ratio)
          auto E_1 = p[0];
          auto E_2 = p[1];
          auto E_3 = E_2;
          auto nu_12 = p[3];
          auto nu_13 = nu_12;
          auto nu_21 = (nu_12/E_1)*E_2;
          auto nu_31 = nu_21;
          auto nu_23 = p[4];
          auto nu_32 = nu_23;
          auto G_12 = p[2];
          auto G_23 = E_2/(2.0*(1+nu_23));
          auto G_31 = G_23;
          //other three poisson ratios are not independent 
          
          //---compliance matrix
    
          Dune::FieldMatrix<double,6,6> C = {{1.0/E_1      , -nu_21/E_2   , -nu_31/E_3   , 0.0     , 0.0     , 0.0   },
    
                                       {-nu_12/E_1   , 1.0/E_2      , -nu_32/E_3   , 0.0     , 0.0     , 0.0   },
                                       {-nu_13/E_1   , -nu_23/E_2   , 1.0/E_3      , 0.0     , 0.0     , 0.0   },
                                       {  0.0        ,  0.0         , 0.0          , 1.0/G_23, 0.0     , 0.0   },
                                       {  0.0        ,  0.0         , 0.0          , 0.0     , 1.0/G_31, 0.0   },
                                       {  0.0        ,  0.0         , 0.0          , 0.0     , 0.0     , 1.0/G_12}
                                      };
    
          // printmatrix(std::cout, C, "C", "--");
    
          //--- return elasticity tensor 
          C.invert();
          // printmatrix(std::cout, C, "C after .invert()", "--");
          return C;
      }
    
      //-------------------------------------------------------------------------------
    
      // --- Definition of transversely isotropic elasticity tensor (in voigt notation)
      // - Input: (Youngs modulus, shear modulus, Poisson ratio): {E1,E2,G12,nu12,nu23}
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      // - Output: inverse compliance Matrix
    
      Dune::FieldMatrix<double,6,6> general_anisotropic(const VectorRT& framevector1,
    
                                                  const VectorRT& framevector2,
                                                  const VectorRT& framevector3,
    
                                                  const Dune::FieldMatrix<double,6,6>& C //compliance matrix
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
          //--- return elasticity tensor (in Voigt notation)
    
          auto tmp = C;
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
          tmp.invert();  
    
          // printmatrix(std::cout, C, "C after .invert()", "--");
          return tmp;
      }
      //-------------------------------------------------------------------------------
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      // --- Helpers
    
      static Dune::FieldVector<double,6> MatrixToVoigt(const MatrixRT& G)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      {
        // return {G[0][0], G[1][1], G[2][2], G[1][2], G[0][2], G[0][1]};
        return {G[0][0], G[1][1], G[2][2], 2.0*G[1][2], 2.0*G[0][2], 2.0*G[0][1]};
    
      }
    
    
      static MatrixRT VoigtToMatrix(const Dune::FieldVector<double,6>& v)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      {
        // return {{v[0], v[5], v[4]}, {v[5], v[1], v[3]}, {v[4], v[3], v[2]}};
        return {{v[0], v[5]/2.0, v[4]/2.0}, {v[5]/2.0, v[1], v[3]/2.0}, {v[4]/2.0, v[3]/2.0, v[2]}};
      }
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      MatrixRT applyElasticityTensor(const MatrixRT& G, const int& phase)  const  
    
      {
        // FieldVector<double,6> G_tmp = {G[0][0], G[1][1], G[2][2], sqrt(2.0)*G[1][2], sqrt(2.0)*G[0][2], sqrt(2.0)*G[0][1]};
    
        // FieldVector<double,6> G_tmp = {G[0][0], G[1][1], G[2][2], G[1][2], G[0][2], G[0][1]};
    
        Dune::FieldVector<double,6> G_tmp = MatrixToVoigt(G);
        Dune::FieldVector<double,6> out(0);
    
        // printvector(std::cout, G_tmp, "G_tmp", "--");
    
          // printmatrix(std::cout, L1_, "L1_", "--");
    
          L1_.mv(G_tmp,out);
        }
        else if (phase == 2)
        {
    
          // printmatrix(std::cout, L2_, "L2_", "--");
    
          L2_.mv(G_tmp,out);
        }
        else 
        {
    
          // printmatrix(std::cout, L3_, "L3_", "--");
    
        // printvector(std::cout, out, "out", "--");
        return VoigtToMatrix(out);
    
        // return image as Matrix again
        // return {{out[0], (1.0/sqrt(2.0))*out[5], (1.0/sqrt(2.0))*out[4]}, {(1.0/sqrt(2.0))*out[5], out[1], (1.0/sqrt(2.0))*out[3]}, {(1.0/sqrt(2.0))*out[4], (1.0/sqrt(2.0))*out[3], out[2]}};
        // return {{out[0], (1.0/2.0)*out[5], (1.0/2.0)*out[4]}, {(1.0/2.0)*out[5], out[1], (1.0/2.0)*out[3]}, {(1.0/2.0)*out[4], (1.0/2.0)*out[3], out[2]}};
    
        // return {{out[0], out[5], out[4]}, {out[5], out[1], out[3]}, {out[4], out[3], out[2]}};
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      ////////////////////////////////////////////////////////////////////////////////////////
      MatrixRT prestrain(const int& phase,const Domain& x) const  
      {
        if (phase == 1)
          return prestrain1_(x);
        else if (phase == 2)
          return prestrain2_(x);
    
        else if (phase ==3)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
          return prestrain3_(x);
    
          DUNE_THROW(Dune::Exception, "Phase number not implemented.");
    
    
    
    ////////////////////////////////////////////////////////
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      //--- Apply elasticityTensor_ to input Matrix G at material phase
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
     // input: Matrix G, material-phase
    
      MatrixRT ElasticityTensor(const MatrixRT& G, const int& phase) const      //deprecated
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      {
    
        return elasticityTensor_(G,phase);   
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      }
    
      int IndicatorFunction(const Domain& x) const
      {
        return indicatorFunction_(x);
      }
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
        ///////////////////////////////
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        // Getter
    
        ///////////////////////////////
    
        Dune::ParameterTree getParameterSet() const {return parameterSet_;}
    
        // Func2Tensor getElasticityTensor() const {return elasticityTensor_;}
    
        // Func2TensorParam getElasticityTensor() const {return elasticityTensor_;}
        Func2TensorPhase getElasticityTensor() const {return elasticityTensor_;}
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        MatrixPhase getPrestrainFunction() const {return prestrain_;} 
    
        auto getLocalIndicatorFunction() const {return localIndicatorFunction_;}   //get as localFunction
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        auto getIndicatorFunctionGVF() const {return indicatorFunctionGVF_;}   //get as GridViewFunction
        auto getIndicatorFunction() const {return indicatorFunction_;}
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        //getLameParameters()? .. Throw Exception if isotropic_ = false! 
    
      ///////////////////////////////
      // VTK - Writer
      ///////////////////////////////
      // -----------------------------------------------------------------
      // --- write material (grid)functions to VTK
      void writeVTKMaterialFunctions(std::array<int, dim> nElements, const int level)
      {
            std::string outputPath = parameterSet_.get("outputPath", "../../outputs");
    
            using VTKGridType = Dune::YaspGrid<dim, Dune::EquidistantOffsetCoordinates<double, dim> >;
    
            // VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{80,80,80});
    
            VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},nElements);
            
    
            using GridViewVTK = typename VTKGridType::LeafGridView;
    
            const GridViewVTK gridView_VTK = grid_VTK.leafGridView();
            
            auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>());
            auto scalarP1FeBasis = makeBasis(gridView_VTK,lagrange<1>());
    
            std::vector<double> indicatorFunction_CoeffP0;
    
            Dune::Functions::interpolate(scalarP0FeBasis, indicatorFunction_CoeffP0, indicatorFunction_);
            auto indicatorFunction_P0 = Dune::Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, indicatorFunction_CoeffP0);
    
            
            std::vector<double> indicatorFunction_CoeffP1;
    
            Dune::Functions::interpolate(scalarP1FeBasis, indicatorFunction_CoeffP1, indicatorFunction_);
            auto indicatorFunction_P1 = Dune::Functions::makeDiscreteGlobalBasisFunction<double>(scalarP1FeBasis, indicatorFunction_CoeffP1);
    
            Dune::VTKWriter<GridView> MaterialVtkWriter(gridView_VTK);
    
            MaterialVtkWriter.addCellData(
    
                indicatorFunction_P0,
    
                Dune::VTK::FieldInfo("indicatorFunction_P0", Dune::VTK::FieldInfo::Type::scalar, 1));
    
            MaterialVtkWriter.addVertexData(
    
                indicatorFunction_P1,
    
                Dune::VTK::FieldInfo("indicatorFunction_P1", Dune::VTK::FieldInfo::Type::scalar, 1));
    
            
            MaterialVtkWriter.write(outputPath + "/MaterialFunctions-level"+ std::to_string(level) );
            std::cout << "wrote data to file:" + outputPath +"/MaterialFunctions-level" + std::to_string(level) << std::endl;  
    	      return;
      };
    
      // -----------------------------------------------------------------
      // --- write prestrain (grid)functions to VTK
      // void writeVTKPrestainFunctions(std::array<int, dim> nElements, const int level)
      // {
      //       std::string outputPath = parameterSet_.get("outputPath", "../../outputs");
      //       using VTKGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >;
      //       //VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{80,80,80});
      //       VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},nElements);
            
      //       using GridViewVTK = VTKGridType::LeafGridView;
      //       const GridViewVTK gridView_VTK = grid_VTK.leafGridView();
            
      //       auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>());
      //       auto scalarP1FeBasis = makeBasis(gridView_VTK,lagrange<1>());
    
      //       std::vector<double> prestrainFunction_CoeffP0;
      //       Functions::interpolate(scalarP0FeBasis, prestrainFunction_CoeffP0, prestrain_);
      //       auto prestrainFunction_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, prestrainFunction_CoeffP0);
            
      //       std::vector<double> prestrainFunction_CoeffP1;
      //       Functions::interpolate(scalarP1FeBasis, prestrainFunction_CoeffP1, prestrain_);
      //       auto prestrainFunction_P1 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP1FeBasis, prestrainFunction_CoeffP1);
            
      //       VTKWriter<GridView> MaterialVtkWriter(gridView_VTK);
            
      //       MaterialVtkWriter.addVertexData(
      //           prestrainFunction_P0,
      //           VTK::FieldInfo("prestrainFunction_P0", VTK::FieldInfo::Type::scalar, 1));    
      //       MaterialVtkWriter.addCellData(
      //           prestrainFunction_P1,
      //           VTK::FieldInfo("prestrainFunction_P1", VTK::FieldInfo::Type::scalar, 1));    
    
      //       MaterialVtkWriter.write(outputPath + "/PrestrainFunctions-level"+ std::to_string(level) );
      //       std::cout << "wrote data to file:" + outputPath + "/PrestrainFunctions-level" + std::to_string(level) << std::endl;  
    	//       return;
      // };
    
      // void writeVTKPrestainFunctions(std::array<int, dim> nElements, const int level)
      // {
    //     using VTKGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >;
    // //     VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{80,80,80});
    // //     VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{40,40,40});
    //     VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},nElements);
    //     using GridViewVTK = VTKGridType::LeafGridView;
    //     const GridViewVTK gridView_VTK = grid_VTK.leafGridView();
       
    //     FTKfillerContainer<dim> VTKFiller;
    //     VTKFiller.vtkPrestrainNorm(gridView_VTK, B_Term, "PrestrainBNorm");
        
    //     // WORKS Too 
    //     VTKFiller.vtkProblemCell(gridView_VTK, B_Term, muLocal,"VTKProblemCell");;
        
        
    //     // TEST 
    //     auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>());
    //     auto scalarP1FeBasis = makeBasis(gridView_VTK,lagrange<1>());
    
    //     std::vector<double> B_CoeffP0;
    //     Functions::interpolate(scalarP0FeBasis, B_CoeffP0, B_Term);
    //     auto B_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, B_CoeffP0);
            
    
            
    //     VTKWriter<GridView> PrestrainVtkWriter(gridView_VTK);
             
    //     PrestrainVtkWriter.addCellData(
    //             B_DGBF_P0,
    //             VTK::FieldInfo("B_P0", VTK::FieldInfo::Type::scalar, 1));     
            
    //     PrestrainVtkWriter.write(outputPath + "/PrestrainFunctions-level"+ std::to_string(level) );
    //     std::cout << "wrote data to file:" + outputPath +"/PrestrainFunctions-level" + std::to_string(level) << std::endl; 
    
    //    // };
      
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
      // MatrixRT ElasticityTensorGlobal(const MatrixRT& G, const Domain& x) const  //global Version (takes global coordinates)
      // {
      //   return MAT(G,x);
      // }
    
      // //--- apply elasticityTensor_ to input Matrix G at position x
      // MatrixRT applyElasticityTensor(const MatrixRT& G, const Domain& x) const  //global Version (takes global coordinates)
      // {
      //   // Python::Module module = Python::import("material");
      //   // auto indicatorFunctionTest = Python::make_function<double>(module.get("indicatorFunction"));
      //   // return elasticityTensor_(G,indicatorFunctionTest(x));
      //   // auto IFunction = localFunction(indicatorFunction_);
      //   // auto IFunction = this->getIndicatorFunction();
      //   // auto tmp = Dune::Functions::makeGridViewFunction(indicatorFunction_material_1, gridView_);
      //   // auto tmpLocal = LocalF
      //   // return elasticityTensor_(G,IFunction(x));
      //   // return elasticityTensor_(G,localIndicatorFunction_(x));
      //   return elasticityTensor_(G,indicatorFunction_(x));
      //   // return elasticityTensor_(G,indicatorFunctionGVF_(x));
      //   // int phase = indicatorFunction_(x);
      //   // auto tmp = elasticityTensor_(G,phase);
      //   // auto tmp = material_1(G,indicatorFunction_(x));
      //   // printmatrix(std::cout, material_1(G,indicatorFunction_(x)), "material_1(G,indicatorFunction_(x))", "--");
      //   // printmatrix(std::cout, elasticityTensor_(G,phase), "elasticityTensor_(G,phase)", "--");
      // }
    
    
    //  template<class Domain>
    // static MatrixRT MAT(const MatrixRT& G, const Domain& x)      //unfortunately not possible as a GridViewFunction? 
    //   {
    //       const FieldVector<double,3> mu = {80.0, 80.0, 60.0};
    //       const FieldVector<double,3> lambda = {80.0, 80.0, 25.0};
    //       double theta=0.25;
    //       if (x[0] <(-0.5+theta) and x[2]<(-0.5+theta))
    //          return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id();
    //       else if (x[1]<(-0.5+theta) and x[2]>(0.5-theta))
    //          return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id();
    //       else 
    //          return 2.0 * mu[2] * sym(G) + lambda[2] * trace(sym(G)) * Id();
    //   }
    
    
    
    
    }; // end class