From 4b989f17458c686a5104a80beef7111b8e172d44 Mon Sep 17 00:00:00 2001 From: Klaus <klaus.boehnlein@tu-dresden.de> Date: Wed, 4 Oct 2023 16:53:43 +0200 Subject: [PATCH] Add Test against parametrized_Laminate (analytical results) --- test/parametrized_laminate.py | 77 +++++++++++ test/parametrizedlaminate.parset | 11 ++ test/parametrizedlaminatetest.cc | 221 ++++++++++++++++++++++++++++--- 3 files changed, 287 insertions(+), 22 deletions(-) create mode 100644 test/parametrized_laminate.py create mode 100644 test/parametrizedlaminate.parset diff --git a/test/parametrized_laminate.py b/test/parametrized_laminate.py new file mode 100644 index 00000000..9007b436 --- /dev/null +++ b/test/parametrized_laminate.py @@ -0,0 +1,77 @@ +import math +import ctypes +import os +import sys +#--------------------------------------------------------------- + +#Parameters used: +theta = 0.25; +mu_1 = 1.0; +theta_mu = 2.0; +mu_2 = theta_mu * mu_1; +rho_1 = 1.0; +theta_rho = 2.0; +rho_2 = rho_1*theta_rho; + + +#--- define indicator function +def indicatorFunction(x): + theta=0.25 + factor=1 + if (abs(x[0]) < (theta/2) and x[2] < 0 ): + return 1 #Phase1 + elif (abs(x[0]) > (theta/2) and x[2] > 0 ): + return 2 #Phase2 + elif (abs(x[0]) < (theta/2) and x[2] > 0 ): + return 3 #Phase3 + else : + return 4 #Phase4 + + +########### Options for material phases: ################################# +# 1. "isotropic" 2. "orthotropic" 3. "transversely_isotropic" 4. "general_anisotropic" +######################################################################### +## Notation - Parameter input : +# isotropic (Lame parameters) : [mu , lambda] +# orthotropic : [E1,E2,E3,G12,G23,G31,nu12,nu13,nu23] # see https://en.wikipedia.org/wiki/Poisson%27s_ratio with x=1,y=2,z=3 +# transversely_isotropic : [E1,E2,G12,nu12,nu23] +# general_anisotropic : full compliance matrix C +###################################################################### + +# --- Number of material phases +Phases=4 + +#--- Define different material phases: + +#- PHASE 1 +phase1_type="isotropic" +materialParameters_phase1 = [2.0, 0] + +#- PHASE 2 +phase2_type="isotropic" +materialParameters_phase2 = [1.0, 0] + + +#- PHASE 3 +phase3_type="isotropic" +materialParameters_phase3 = [2.0, 0] + +#- PHASE 4 +phase4_type="isotropic" +materialParameters_phase4 = [1.0, 0] + + +#--- define prestrain function for each phase +# (also works with non-constant values) +def prestrain_phase1(x): + return [[2, 0, 0], [0,2,0], [0,0,2]] + +def prestrain_phase2(x): + return [[1, 0, 0], [0,1,0], [0,0,1]] + +def prestrain_phase3(x): + return [[0, 0, 0], [0,0,0], [0,0,0]] + +def prestrain_phase4(x): + return [[0, 0, 0], [0,0,0], [0,0,0]] + diff --git a/test/parametrizedlaminate.parset b/test/parametrizedlaminate.parset new file mode 100644 index 00000000..08e2ee45 --- /dev/null +++ b/test/parametrizedlaminate.parset @@ -0,0 +1,11 @@ +# --- Choose material definition: +materialFunction = "parametrized_laminate" + +# --- Choose scale ratio gamma: +gamma=1.0 + +############################################# +# Solver Type: #1: CG - SOLVER , #2: GMRES - SOLVER, #3: QR - SOLVER (default), #4: UMFPACK - SOLVER +############################################# +#Solvertype = 2 # recommended to use iterative solver (e.g GMRES) for finer grid-levels +#Solver_verbosity = 0 #(default = 2) degree of information for solver output \ No newline at end of file diff --git a/test/parametrizedlaminatetest.cc b/test/parametrizedlaminatetest.cc index 12ef53d8..544e8aaa 100644 --- a/test/parametrizedlaminatetest.cc +++ b/test/parametrizedlaminatetest.cc @@ -11,12 +11,10 @@ #include <dune/common/float_cmp.hh> #include <dune/common/math.hh> - #include <dune/geometry/quadraturerules.hh> #include <dune/grid/uggrid.hh> #include <dune/grid/yaspgrid.hh> -// #include <dune/grid/utility/structuredgridfactory.hh> //TEST #include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh> #include <dune/istl/matrix.hh> @@ -41,37 +39,216 @@ #include <dune/functions/gridfunctions/gridviewfunction.hh> #include <dune/common/fvector.hh> -#include <dune/common/fmatrix.hh> +#include <dune/common/fmatrix.hh> -// #include <dune/microstructure/prestrain_material_geometry.hh> #include <dune/microstructure/matrix_operations.hh> -// #include <dune/microstructure/vtk_filler.hh> //TEST -#include <dune/microstructure/CorrectorComputer.hh> -#include <dune/microstructure/EffectiveQuantitiesComputer.hh> -#include <dune/microstructure/prestrainedMaterial.hh> +#include <dune/microstructure/CorrectorComputer.hh> +#include <dune/microstructure/EffectiveQuantitiesComputer.hh> +#include <dune/microstructure/prestrainedMaterial.hh> -#include <dune/solvers/solvers/umfpacksolver.hh> //TEST -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/solvers/solvers/umfpacksolver.hh> +#include <dune/istl/eigenvalue/test/matrixinfo.hh> -// #include <dune/fufem/discretizationerror.hh> #include <dune/fufem/dunepython.hh> -// #include <dune/fufem/functions/virtualgridfunction.hh> //TEST - -// #include <boost/multiprecision/cpp_dec_float.hpp> #include <any> #include <variant> #include <string> -#include <iomanip> // needed when working with relative paths e.g. from python-scripts +#include <iomanip> +#include <filesystem> using namespace Dune; using namespace MatrixOperations; -#include <iostream> - -int main(){ - - - std::cout << "small little program." << std::endl; -} \ No newline at end of file +/** + * @brief In the special case of a parametrized laminate (Lemma 4.5) in + * [Böhnlein,Neukamm,Padilla-Garza,Sander - A homogenized bending theory for prestrained plates] + * some of the effective quantities can be computed analytically. + * This test compares the analytical quantities with numerical results. + */ + + +////////////////////////////////////////////////// +// Infrastructure for handling periodicity +////////////////////////////////////////////////// +// Check whether two points are equal on R/Z x R/Z x R +auto equivalent = [](const FieldVector<double,3>& x, const FieldVector<double,3>& y) + { + return ( (FloatCmp::eq(x[0],y[0]) or FloatCmp::eq(x[0]+1,y[0]) or FloatCmp::eq(x[0]-1,y[0])) + and (FloatCmp::eq(x[1],y[1]) or FloatCmp::eq(x[1]+1,y[1]) or FloatCmp::eq(x[1]-1,y[1])) + and (FloatCmp::eq(x[2],y[2])) + ); + }; + + +int main(int argc, char *argv[]) +{ + MPIHelper::instance(argc, argv); + + Dune::Timer globalTimer; + //--- setup Log-File + std::fstream log; + + std::cout << "Current path is " << std::filesystem::current_path() << '\n'; + std::filesystem::path file_path = (__FILE__); + std::cout<< "File path: " << file_path<<std::endl; + std::cout << "dir_path: " << file_path.parent_path() << std::endl; + std::string dir_path = file_path.parent_path(); + + ParameterTree parameterSet; + if (argc < 2) + ParameterTreeParser::readINITree(dir_path + "/parsets/parametrizedlaminate.parset", parameterSet); + else + { + ParameterTreeParser::readINITree(argv[1], parameterSet); + ParameterTreeParser::readOptions(argc, argv, parameterSet); + } + + //--- Start Python interpreter + Python::start(); + Python::Reference main = Python::import("__main__"); + Python::run("import math"); + Python::runStream() + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" + << std::endl; + + + constexpr int dim = 3; + constexpr int dimWorld = 3; + /////////////////////////////////// + // Generate the grid + /////////////////////////////////// + // --- Corrector Problem Domain (-1/2,1/2)^3: + FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0}); + FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0}); + + int gridLevel = 3; + + std::array<int, dim> nElements = {(int)std::pow(2,gridLevel) ,(int)std::pow(2,gridLevel) ,(int)std::pow(2,gridLevel)}; + std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; + + using CellGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >; + CellGridType grid_CE(lower,upper,nElements); + using GridView = CellGridType::LeafGridView; + const GridView gridView_CE = grid_CE.leafGridView(); + + //--- Choose a finite element space for Cell Problem + using namespace Functions::BasisFactory; + Functions::BasisFactory::Experimental::PeriodicIndexSet periodicIndices; + + //--- get PeriodicIndices for periodicBasis (Don't do the following in real life: It has quadratic run-time in the number of vertices.) + for (const auto& v1 : vertices(gridView_CE)) + for (const auto& v2 : vertices(gridView_CE)) + if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0))) + { + periodicIndices.unifyIndexPair({gridView_CE.indexSet().index(v1)}, {gridView_CE.indexSet().index(v2)}); + } + + //--- setup first order periodic Lagrange-Basis + auto Basis_CE = makeBasis( + gridView_CE, + power<dim>( + Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), + flatLexicographic() + )); + + /////////////////////////////////// + // Create prestrained material object + /////////////////////////////////// + auto material_ = prestrainedMaterial(gridView_CE,parameterSet); + + // --- Get scale ratio + double gamma = parameterSet.get<double>("gamma",1.0); + + //------------------------------------------------------------------------------------------------ + //--- Compute Correctors + auto correctorComputer = CorrectorComputer(Basis_CE, material_, gamma, log, parameterSet); + correctorComputer.solve(); + + + //--- Compute effective quantities + auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material_); + effectiveQuantitiesComputer.computeEffectiveQuantities(); + + //--- get effective quantities + auto Qeff = effectiveQuantitiesComputer.getQeff(); + auto Beff = effectiveQuantitiesComputer.getBeff(); +// printmatrix(std::cout, Qeff, "Matrix Qeff", "--"); +// printvector(std::cout, Beff, "Beff", "--"); + + /** + * @brief Compute analytical effective quantitites + * + */ + //Parameters + double theta = 0.25; + double mu_1 = 1.0; + double theta_mu = 2.0; + double mu_2 = theta_mu * mu_1; + double rho_1 = 1.0; + double theta_rho = 2.0; + double rho_2 = rho_1*theta_rho; + + //Effective quantities + double q_1 = mu_1 * (theta_mu / (6*(theta + (1 - theta)*theta_mu))); + double q_2 = (mu_1/6.0) * ((1-theta) + theta*theta_mu); + double Beff_1 = (3.0*rho_1/2.0) * (1-(theta*(1+theta_rho))); + double Beff_2 = (3.0*rho_1/2.0) * ((1-theta*(1+theta_mu*theta_rho))/(1-theta+theta*theta_mu)); + double Beff_3 = 0.0; + // std::cout << "q_1: " << q_1 << std::endl; + // std::cout << "q_2: " << q_2 << std::endl; + // std::cout << "Beff_1: " << Beff_1 << std::endl; + // std::cout << "Beff_2: " << Beff_2 << std::endl; + // std::cout << "Beff_3: " << Beff_3 << std::endl; + + /** + * @brief Compare numerical and analytical results. + * + */ + if( std::abs(q_1 - Qeff[0][0]) > 1e-2) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Qeff[0][0] is " << Qeff[0][0] << " but " << q_1 << " was expected!" << std::endl; + + return 1; + } + if( std::abs(q_2 - Qeff[1][1]) > 1e-2) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Qeff[1][1] is " << Qeff[1][1] << " but " << q_2 << " was expected!" << std::endl; + + return 1; + } + if( std::abs(Beff_1 - Beff[0]) > 1e-2) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Beff[0] is " << Beff[0] << " but " << Beff_1 << " was expected!" << std::endl; + + return 1; + } + if( std::abs(Beff_2 - Beff[1]) > 1e-2) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Beff[1] is " << Beff[1] << " but " << Beff_2 << " was expected!" << std::endl; + + return 1; + } + if( std::abs(Beff_3 - Beff[2]) > 1e-2) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Beff[2] is " << Beff[2] << " but " << Beff_3 << " was expected!" << std::endl; + return 1; + } + if( (Qeff[2][2] < Qeff[0][0]) || (Qeff[2][2] > Qeff[1][1]) ) + { + std::cerr << std::setprecision(9); + std::cerr << "Computed Qeff[2][2] is " << Qeff[2][2] << " does not lie between Qeff[0][0]:" + << Qeff[0][0] << " and Qeff[1][1]:" << Qeff[1][1] << " as was expected!" << std::endl; + return 1; + } + + std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; + std::cout << "Test parametrizedlaminatetest passed." << std::endl; +} -- GitLab