From f62c44f5c9253f4f3f59fe598725e0f6c2243913 Mon Sep 17 00:00:00 2001 From: Klaus <klaus.boehnlein@tu-dresden.de> Date: Sun, 1 Oct 2023 18:41:02 +0200 Subject: [PATCH] Add option to rotate material coordinate frame --- dune/microstructure/matrix_operations.hh | 58 +++ dune/microstructure/prestrainedMaterial.hh | 494 +++++++++++++-------- materials/material_orthotropic.py | 14 +- 3 files changed, 378 insertions(+), 188 deletions(-) diff --git a/dune/microstructure/matrix_operations.hh b/dune/microstructure/matrix_operations.hh index fc1670e5..3eca389f 100644 --- a/dune/microstructure/matrix_operations.hh +++ b/dune/microstructure/matrix_operations.hh @@ -105,6 +105,64 @@ namespace MatrixOperations { return sum; } + + /** + * @brief Determines rotation matrix based on an axis and an angle + * + * @param axis + * @param angle + * @return MatrixRT + */ + static MatrixRT rotationMatrix(int axis, double angle){ + + switch (axis) + { + case 0: + { + return {{1.0, 0, 0 }, + { 0, cos(angle), -1.0*sin(angle)}, + { 0, sin(angle), cos(angle)}}; + } + case 1: + { + return {{ cos(angle), 0, sin(angle)}, + { 0, 1.0, 0 }, + {-1.0*sin(angle), 0, cos(angle)}}; + } + case 2: + { + return {{cos(angle), -1.0*sin(angle), 0}, + {sin(angle), cos(angle), 0}, + { 0, 0, 1.0}}; + } + default: + DUNE_THROW(Dune::Exception, " axis not feasible. rotationMatrix is only implemented for 3x3-matrices."); + } + } + + /** + * @brief 6x6 matrix that transforms the strain tensor. This matrix is used to + * transform the compliance matrix (given in Voigt notation) into another frame. + * see 'https://en.wikipedia.org/wiki/Orthotropic_material#Condition_for_material_symmetry_2' + * for details. + * + * @param axis + * @param angle + * @return MatrixRT + */ + static Dune::FieldMatrix<double,6,6> rotationMatrixCompliance(int axis, double angle){ + + MatrixRT R = rotationMatrix(axis,angle); + + return {{ R[0][0]*R[0][0], R[0][1]*R[0][1], R[0][2]*R[0][2], R[0][1]*R[0][2], R[0][0]*R[0][2], R[0][0]*R[0][1]}, + { R[1][0]*R[1][0], R[1][1]*R[1][1], R[1][2]*R[1][2], R[1][1]*R[1][2], R[1][0]*R[1][2], R[1][0]*R[1][1]}, + { R[2][0]*R[2][0], R[2][1]*R[2][1], R[2][2]*R[2][2], R[2][1]*R[2][2], R[2][0]*R[2][2], R[2][0]*R[2][1]}, + {2.0*R[1][0]*R[2][0], 2.0*R[1][1]*R[2][1], 2.0*R[1][2]*R[2][2], R[1][1]*R[2][2]+R[1][2]*R[2][1], R[1][0]*R[2][2]+R[1][2]*R[2][0], R[1][0]*R[2][1]+R[1][1]*R[2][0]}, + {2.0*R[0][0]*R[2][0], 2.0*R[0][1]*R[2][1], 2.0*R[0][2]*R[2][2], R[0][1]*R[2][2]+R[0][2]*R[2][1], R[0][0]*R[2][2]+R[0][2]*R[2][0], R[0][0]*R[2][1]+R[0][1]*R[2][0]}, + {2.0*R[0][0]*R[0][0], 2.0*R[0][1]*R[1][1], 2.0*R[0][2]*R[1][2], R[0][1]*R[1][2]+R[0][2]*R[1][1], R[0][0]*R[1][2]+R[0][2]*R[1][0], R[0][0]*R[1][1]+R[0][1]*R[1][0]} + }; + } + // static double linearizedStVenantKirchhoffDensity(double mu, double lambda, MatrixRT E1, MatrixRT E2){ // ?? Check with Robert // E1= sym(E1); // E2 = sym(E2); diff --git a/dune/microstructure/prestrainedMaterial.hh b/dune/microstructure/prestrainedMaterial.hh index 60ddc691..8651815a 100644 --- a/dune/microstructure/prestrainedMaterial.hh +++ b/dune/microstructure/prestrainedMaterial.hh @@ -185,10 +185,6 @@ public: //-- Norway spruce see [Dimwoodie; Timber its nature and behavior p.109] // 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}; @@ -262,172 +258,213 @@ public: // auto Test = Dune::Functions::makeGridViewFunction(MAT<Domain> , gridView_); //not working } +/** + * @brief TODO: Code allows a spatially varying prestrain. However most of the time we only + * use a constant prestrain. + * - Add switch (constant/non-constant) prestrain? + * + * @param module python module used + * @param phase material phase + * @return Func2Tensor + */ +Func2Tensor setupPrestrainPhase(Python::Module module, int phase){ + + auto prestrain = Python::make_function<MatrixRT>(module.get("prestrain_phase" + std::to_string(phase))); + + int axis = 0; + double angle = 0; + try + { + module.get("phase" + std::to_string(phase) + "_axis").toC<int>(axis); + module.get("phase" + std::to_string(phase) + "_angle").toC<double>(angle); + } + catch(Dune::Exception) + { + //default frame is used. + } + /** + * @brief (optional) Tramsform prestrain to the correct frame. + */ + if(abs(angle) > 1e-12){ + auto R = rotationMatrix(axis,angle); + Func2Tensor f = [prestrain,R] (const Domain& x) { return (prestrain(x).leftmultiply(R)).rightmultiply(R.transposed()); }; + + return f; + } + else + return prestrain; +} - -Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Module module, int phase) +// Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Module module, int phase) +Dune::FieldMatrix<double,6,6> setupPhase(Python::Module module, int phase) { - std::string materialParameters_string; - std::cout << "Setup phase "<< phase << " as " << phaseType << " material." << std::endl; + std::string phaseType; + module.get("phase" + std::to_string(phase) + "_type").toC<std::string>(phaseType); - switch (phase) - { - case 1: - { - materialParameters_string = "materialParameters_phase1"; - break; - } - case 2: - { - materialParameters_string = "materialParameters_phase2"; - break; - } - case 3: - { - materialParameters_string= "materialParameters_phase3"; - break; - } - case 4: - { - materialParameters_string= "materialParameters_phase4"; - break; - } - default: - DUNE_THROW(Dune::Exception, "Phase number not implemented."); - break; - } + std::cout << "Setup phase "<< phase << " as " << phaseType << " material." << std::endl; - if(phaseType == "isotropic") //TODO SetupPHASE (phase_type) + if(phaseType == "isotropic") { Dune::FieldVector<double,2> materialParameters(0); - module.get(materialParameters_string).toC<Dune::FieldVector<double,2>>(materialParameters); + module.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,2>>(materialParameters); std::cout << "Lame-Parameters (mu,lambda): (" << materialParameters[0] << "," << materialParameters[1] << ") " << std::endl; return isotropic(materialParameters[0],materialParameters[1]); } - if(phaseType == "orthotropic") //TODO SetupPHASE (phase_type) + + /** + * @brief For other material classes. The stiffness-/compliance matrix depends on the + * coordinate frame. + * + * The default frame vectors: + */ + // VectorRT frameVector1 = {1.0,0.0,0.0}; + // VectorRT frameVector2 = {0.0,1.0,0.0}; + // VectorRT frameVector3 = {0.0,0.0,1.0}; + /** + * @brief For other material classes. The stiffness-/compliance matrix depends on the + * coordinate frame. + * + * (optional) rotate material coordinate frame by an 'angle' around 'axis' + */ + int axis = 0; + double angle = 0; + + try + { + // module.get("phase" + std::to_string(phase) + "_FrameVector1").toC<VectorRT>(frameVector1); + // module.get("phase" + std::to_string(phase) + "_FrameVector2").toC<VectorRT>(frameVector2); + // module.get("phase" + std::to_string(phase) + "_FrameVector3").toC<VectorRT>(frameVector3); + // printvector(std::cout, frameVector1, "frameVector1: ", "--"); + // printvector(std::cout, frameVector2, "frameVector2: ", "--"); + // printvector(std::cout, frameVector3, "frameVector3: ", "--"); + module.get("phase" + std::to_string(phase) + "_axis").toC<int>(axis); + module.get("phase" + std::to_string(phase) + "_angle").toC<double>(angle); + } + catch(Dune::Exception) + { + // std::cout << "(Could not read frame vectors for material phase) " << phase << ": - Canonical Frame (default) is used." << std::endl; + std::cout << "(Could not read rotaton axis & angle for material phase) " << phase << ": - Canonical Frame (default) is used." << std::endl; + } + + + if(phaseType == "orthotropic") { - // 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); + module.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9>>(materialParameters); + // return orthotropic(frameVector1,frameVector2,frameVector3,materialParameters); + return orthotropic(axis,angle,materialParameters); } - if(phaseType == "transversely_isotropic") //TODO SetupPHASE (phase_type) + if(phaseType == "transversely_isotropic") { - // 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); + module.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,5>>(materialParameters); + // return transversely_isotropic(frameVector1,frameVector2,frameVector3,materialParameters); + return transversely_isotropic(axis,angle,materialParameters); } - if(phaseType == "general_anisotropic") //TODO SetupPHASE (phase_type) + if(phaseType == "general_anisotropic") { - // 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); + module.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6>>(materialParameters); + // return general_anisotropic(frameVector1,frameVector2,frameVector3,materialParameters); + return general_anisotropic(axis,angle,materialParameters); } else - DUNE_THROW(Dune::Exception, " Unknown material class for phase "); + DUNE_THROW(Dune::Exception, " Unknown material class for phase " + std::to_string(phase)); } - //---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!? + /** + * @brief Setup method that determines the correct stiffness-matrix (constitutive law) + * for each material phase separately. + * + * @param name name of the material file being used. + */ + void setup(const std::string name) // cant use materialFunctionName_ here? { - Python::Module module = Python::import(name); indicatorFunction_ = Python::make_function<int>(module.get("indicatorFunction")); - std::cout << "---- setup material... " << std::endl; - - int Phases; - module.get("Phases").toC<int>(Phases); - std::cout << "Number of Phases: " << Phases << std::endl; + int phases; + module.get("Phases").toC<int>(phases); + std::cout << "---- Starting material setup... (Number of Phases: "<< phases << ") " << std::endl; - - switch (Phases) - { - case 1: + switch (phases) { - 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; - } - 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); - - 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")); + case 1: + { + // std::string phase1_type; + // module.get("phase1_type").toC<std::string>(phase1_type); - 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")); - - break; - } - case 4: - { - 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); - std::string phase4_type; - module.get("phase4_type").toC<std::string>(phase4_type); - - L1_ = setupPhase(phase1_type, module,1); - L2_ = setupPhase(phase2_type, module,2); - L3_ = setupPhase(phase3_type, module,3); - L4_ = setupPhase(phase4_type, module,4); - - 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")); - prestrain4_ = Python::make_function<MatrixRT>(module.get("prestrain_phase4")); - - break; - } - default: - break; + L1_ = setupPhase(module,1); + // prestrain1_ = Python::make_function<MatrixRT>(module.get("prestrain_phase1")); + prestrain1_ = setupPrestrainPhase(module,1); + break; + } + 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); + + L1_ = setupPhase(module,1); + L2_ = setupPhase(module,2); + // prestrain1_ = Python::make_function<MatrixRT>(module.get("prestrain_phase1")); + // prestrain2_ = Python::make_function<MatrixRT>(module.get("prestrain_phase2")); + prestrain1_ = setupPrestrainPhase(module,1); + prestrain2_ = setupPrestrainPhase(module,2); + 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(module,1); + L2_ = setupPhase(module,2); + L3_ = setupPhase(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")); + prestrain1_ = setupPrestrainPhase(module,1); + prestrain2_ = setupPrestrainPhase(module,2); + prestrain3_ = setupPrestrainPhase(module,3); + break; + } + case 4: + { + // 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); + // std::string phase4_type; + // module.get("phase4_type").toC<std::string>(phase4_type); + + L1_ = setupPhase(module,1); + L2_ = setupPhase(module,2); + L3_ = setupPhase(module,3); + L4_ = setupPhase(module,4); + // 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")); + // prestrain4_ = Python::make_function<MatrixRT>(module.get("prestrain_phase4")); + prestrain1_ = setupPrestrainPhase(module,1); + prestrain2_ = setupPrestrainPhase(module,2); + prestrain3_ = setupPrestrainPhase(module,3); + prestrain4_ = setupPrestrainPhase(module,4); + break; + } + default: + DUNE_THROW(Dune::Exception, " No more than 4 material phases are implemented yet! "); } std::cout << "Material setup done." << std::endl; } @@ -440,26 +477,41 @@ Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Mo //--- Definition of isotropic elasticity tensor (stiffness matrix 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 , mu , 0.0 , 0.0 }, - { 0.0 , 0.0 , 0.0 , 0.0 , mu , 0.0 }, - { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , mu } - }; + 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 , mu , 0.0 , 0.0 }, + { 0.0 , 0.0 , 0.0 , 0.0 , mu , 0.0 }, + { 0.0 , 0.0 , 0.0 , 0.0 , 0.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} - ) + // 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} + // ) + + /** + * @brief Definition of orthotropic elasticity/stiffness tensor (in Voigt notation). + * The convention in literature is to provide the elastic constants in form of the 'compliance matrix' + * In order to compute stresses from strain, we have to invert the 'compliance matrix' to obtain the 'stiffness matrix' + * (see https://en.wikipedia.org/wiki/Orthotropic_material for more details) + * + * @param axis rotate material frame around axis + * @param angle rotation angle + * @param p elastic constants: (E1,E2,E3,G12,G23,G31,nu12,nu13,nu23) + * @return Stiffness matrix + */ + Dune::FieldMatrix<double,6,6> orthotropic(const int& axis, + const double& angle, + const Dune::FieldVector<double,9>& p + ) { - // (see https://en.wikipedia.org/wiki/Orthotropic_material) auto E_1 = p[0]; auto E_2 = p[1]; auto E_3 = p[2]; @@ -474,34 +526,58 @@ Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Mo 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} - }; + std::string axis_string; + switch (axis) + { + case 0: axis_string = "x - axis"; + case 1: axis_string = "y - axis"; + case 2: axis_string = "z - axis"; + default: break; + } - printmatrix(std::cout, C, "(Orthotropic) Compliance matrix used:", "--"); - // printmatrix(std::cout, C, "C", "--"); + // Compliance matrix + Dune::FieldMatrix<double,6,6> Compliance = {{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} + }; + + + /** + * @brief (optional) Tramsform compliance matrix to the correct frame. + */ + if(abs(angle) > 1e-12){ + // std::cout << "material frame rotated around axis: " << axis << " by an angle of: " << angle << std::endl; + std::cout << "material frame rotated around axis: " << axis_string << " by an angle of: " << angle << std::endl; + Dune::FieldMatrix<double,6,6> C_rot = rotationMatrixCompliance(axis,angle); + (Compliance.leftmultiply(C_rot)).rightmultiply(C_rot.transposed()); + } - //--- return elasticity tensor - C.invert(); - // printmatrix(std::cout, C, "C after .invert()", "--"); - return C; + + printmatrix(std::cout, Compliance, "Compliance matrix used:", "--"); + + // invert to obtain elasticity/stiffness-Tensor + Compliance.invert(); + // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); + return Compliance; } //------------------------------------------------------------------------------- + // 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} + // ) //--- 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} - ) + Dune::FieldMatrix<double,6,6> transversely_isotropic(const int& axis, + const double& angle, + const Dune::FieldVector<double,5>& p + ) { // (see https://en.wikipedia.org/wiki/Poisson%27s_ratio) auto E_1 = p[0]; @@ -517,22 +593,42 @@ Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Mo auto G_23 = E_2/(2.0*(1+nu_23)); auto G_31 = G_23; //other three poisson ratios are not independent + + std::string axis_string; + switch (axis) + { + case 0: axis_string = "x - axis"; + case 1: axis_string = "y - axis"; + case 2: axis_string = "z - axis"; + default: break; + } //---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} - }; + Dune::FieldMatrix<double,6,6> Compliance = {{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} + }; + + /** + * @brief (optional) Tramsform compliance matrix to the correct frame. + */ + if(abs(angle) > 1e-12){ + // std::cout << "material frame rotated around axis: " << axis << " by an angle of: " << angle << std::endl; + std::cout << "material frame rotated around axis: " << axis_string << " by an angle of: " << angle << std::endl; + Dune::FieldMatrix<double,6,6> C_rot = rotationMatrixCompliance(axis,angle); + (Compliance.leftmultiply(C_rot)).rightmultiply(C_rot.transposed()); + } + printmatrix(std::cout, Compliance, "Compliance matrix used:", "--"); // printmatrix(std::cout, C, "C", "--"); //--- return elasticity tensor - C.invert(); + Compliance.invert(); // printmatrix(std::cout, C, "C after .invert()", "--"); - return C; + return Compliance; } //------------------------------------------------------------------------------- @@ -540,17 +636,41 @@ Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Mo // --- Definition of transversely isotropic elasticity tensor (in voigt notation) // - Input: (Youngs modulus, shear modulus, Poisson ratio): {E1,E2,G12,nu12,nu23} // - 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 - ) + // 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 + // ) + Dune::FieldMatrix<double,6,6> general_anisotropic(const int& axis, + const double& angle, + Dune::FieldMatrix<double,6,6>& Compliance + ) { + + std::string axis_string; + switch (axis) + { + case 0: axis_string = "x - axis"; + case 1: axis_string = "y - axis"; + case 2: axis_string = "z - axis"; + default: break; + } + + /** + * @brief (optional) Tramsform compliance matrix to the correct frame. + */ + if(abs(angle) > 1e-12){ + // std::cout << "material frame rotated around axis: " << axis << " by an angle of: " << angle << std::endl; + std::cout << "material frame rotated around axis: " << axis_string << " by an angle of: " << angle << std::endl; + Dune::FieldMatrix<double,6,6> C_rot = rotationMatrixCompliance(axis,angle); + (Compliance.leftmultiply(C_rot)).rightmultiply(C_rot.transposed()); + } + printmatrix(std::cout, Compliance, "Compliance matrix used:", "--"); + //--- return elasticity tensor (in Voigt notation) - auto tmp = C; - tmp.invert(); + Compliance.invert(); // printmatrix(std::cout, C, "C after .invert()", "--"); - return tmp; + return Compliance; } //------------------------------------------------------------------------------- diff --git a/materials/material_orthotropic.py b/materials/material_orthotropic.py index ffaf3901..3f9ab71e 100644 --- a/materials/material_orthotropic.py +++ b/materials/material_orthotropic.py @@ -41,7 +41,19 @@ materialParameters_phase1 = [11.2e3,630,1190,700,230,960,0.63 ,0.49,0.37] # w #- PHASE 2 phase2_type="orthotropic" -materialParameters_phase2 = [10.7e3,430,710,620,23,500, 0.51 ,0.38,0.31] # Norway spruce parameters (values for compliance matrix) see [Dimwoodie; Timber its nature and behavior p.109] +# materialParameters_phase2 = [10.7e3,430,710,620,23,500, 0.51 ,0.38,0.31] # Norway spruce parameters (values for compliance matrix) see [Dimwoodie; Timber its nature and behavior p.109] +materialParameters_phase2 = [11.2e3,630,1190,700,230,960,0.63 ,0.49,0.37] + +# Pass a set of FrameVectors to transform material properties to this Frame +# phase2_FrameVector1 = [1, 0 ,0] +# phase2_FrameVector2 = [0, 5, 0] +# phase2_FrameVector3 = [0, 0, 1] + +phase2_axis = 2 +phase2_angle = np.pi/2.0 +# phase2_angle = 2*np.pi/12 + + #- PHASE 3 phase3_type="isotropic" -- GitLab