diff --git a/dune/microstructure/CorrectorComputer.hh b/dune/microstructure/CorrectorComputer.hh index 34917870853d2540a9221770afee63927feb3a21..d9ce0d4890df6bcf7477d506c239fd00115b22be 100644 --- a/dune/microstructure/CorrectorComputer.hh +++ b/dune/microstructure/CorrectorComputer.hh @@ -5,19 +5,19 @@ #include <dune/common/parametertree.hh> #include <dune/functions/functionspacebases/interpolate.hh> -#include <dune/functions/gridfunctions/gridviewfunction.hh> -#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh> +#include <dune/functions/gridfunctions/gridviewfunction.hh> +#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh> #include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh> #include <dune/istl/matrixindexset.hh> -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/microstructure/matrix_operations.hh> #include <dune/microstructure/voigthelper.hh> -#include <dune/solvers/solvers/umfpacksolver.hh> -#include <dune/solvers/solvers/cholmodsolver.hh> +#include <dune/solvers/solvers/umfpacksolver.hh> +#include <dune/solvers/solvers/cholmodsolver.hh> using namespace MatrixOperations; using std::shared_ptr; @@ -28,20 +28,20 @@ template <class Basis, class Material> //, class LocalScalar, class Local2Tensor class CorrectorComputer { public: - static const int dimworld = 3; //GridView::dimensionworld; - static const int dim = Basis::GridView::dimension; //const int dim = Domain::dimension; - - using GridView = typename Basis::GridView; - using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate; - using VectorRT = Dune::FieldVector< double, dimworld>; - using MatrixRT = Dune::FieldMatrix< double, dimworld, dimworld>; - using FuncScalar = std::function< double(const Domain&) >; - using FuncVector = std::function< VectorRT(const Domain&) >; - using Func2Tensor = std::function< MatrixRT(const Domain&) >; - using Func2int = std::function< int(const Domain&) >; - using VectorCT = Dune::BlockVector<Dune::FieldVector<double,1> >; - using MatrixCT = Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1> >; - using ElementMatrixCT = Dune::Matrix<double>; + static const int dimworld = 3; //GridView::dimensionworld; + static const int dim = Basis::GridView::dimension; //const int dim = Domain::dimension; + + using GridView = typename Basis::GridView; + using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate; + using VectorRT = Dune::FieldVector< double, dimworld>; + using MatrixRT = Dune::FieldMatrix< double, dimworld, dimworld>; + using FuncScalar = std::function< double (const Domain&) >; + using FuncVector = std::function< VectorRT(const Domain&) >; + using Func2Tensor = std::function< MatrixRT(const Domain&) >; + using Func2int = std::function< int (const Domain&) >; + using VectorCT = Dune::BlockVector<Dune::FieldVector<double,1> >; + using MatrixCT = Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1> >; + using ElementMatrixCT = Dune::Matrix<double>; @@ -51,20 +51,20 @@ public: protected: - const Basis& basis_; + const Basis& basis_; // const Material& material_; // Material& material_; // Material material_; - // fstream& log_; // Output-log - const Dune::ParameterTree& parameterSet_; + // fstream& log_; // Output-log + const Dune::ParameterTree& parameterSet_; - MatrixCT stiffnessMatrix_; - VectorCT load_alpha1_,load_alpha2_,load_alpha3_; //right-hand side(load) vectors + MatrixCT stiffnessMatrix_; + VectorCT load_alpha1_,load_alpha2_,load_alpha3_; //right-hand side(load) vectors - VectorCT x_1_, x_2_, x_3_; // (all) Corrector coefficient vectors - VectorCT phi_1_, phi_2_, phi_3_; // Corrector phi_i coefficient vectors + VectorCT x_1_, x_2_, x_3_; // (all) Corrector coefficient vectors + VectorCT phi_1_, phi_2_, phi_3_; // Corrector phi_i coefficient vectors Dune::FieldVector<double,3> m_1_, m_2_, m_3_; // Corrector m_i coefficient vectors // (assembled) corrector matrices M_i @@ -77,119 +77,119 @@ protected: const std::array<VoigtVector<double,3>,3 > matrixBasis_; Func2Tensor x3G_1_ = [] (const Domain& x) { - return MatrixRT{{1.0*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; + return MatrixRT{{1.0*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; Func2Tensor x3G_2_ = [] (const Domain& x) { - return MatrixRT{{0.0, 0.0, 0.0}, {0.0, 1.0*x[2], 0.0}, {0.0, 0.0, 0.0}}; - }; + return MatrixRT{{0.0, 0.0, 0.0}, {0.0, 1.0*x[2], 0.0}, {0.0, 0.0, 0.0}}; + }; - Func2Tensor x3G_3_ = [] (const Domain& x) { - return MatrixRT{{0.0, (1.0/sqrt(2.0))*x[2], 0.0}, {(1.0/sqrt(2.0))*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; + Func2Tensor x3G_3_ = [] (const Domain& x) { + return MatrixRT{{0.0, (1.0/sqrt(2.0))*x[2], 0.0}, {(1.0/sqrt(2.0))*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; const std::array<Func2Tensor, 3> x3MatrixBasisContainer_ = {x3G_1_, x3G_2_, x3G_3_}; - // --- Offset between basis indices + // --- Offset between basis indices const int phiOffset_; -public: - /////////////////////////////// - // constructor - /////////////////////////////// - // CorrectorComputer(const Basis& basis, - // Material& material, - // std::fstream& log, - // const Dune::ParameterTree& parameterSet) - // : basis_(basis), - // material_(material), - // gamma_(material_.getGamma()), - // log_(log), - // parameterSet_(parameterSet), - // matrixBasis_(std::array<VoigtVector<double,3>,3>{matrixToVoigt(Dune::FieldMatrix<double,3,3>({{1, 0, 0}, {0, 0, 0}, {0, 0, 0}})), - // matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 0, 0}, {0, 1, 0}, {0, 0, 0}})), - // matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 1/std::sqrt(2.0), 0}, {1/std::sqrt(2.0), 0, 0}, {0, 0, 0}}))}), - // phiOffset_(basis.size()) - // {} - - CorrectorComputer(const Basis& basis, - std::shared_ptr<Material> material, - // std::fstream& log, - const Dune::ParameterTree& parameterSet) - : basis_(basis), - material_(material), - // gamma_(material_->getGamma()), - // log_(log), - parameterSet_(parameterSet), - matrixBasis_(std::array<VoigtVector<double,3>,3>{matrixToVoigt(Dune::FieldMatrix<double,3,3>({{1, 0, 0}, {0, 0, 0}, {0, 0, 0}})), - matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 0, 0}, {0, 1, 0}, {0, 0, 0}})), - matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 1/std::sqrt(2.0), 0}, {1/std::sqrt(2.0), 0, 0}, {0, 0, 0}}))}), - phiOffset_(basis.size()) - {} +public: + /////////////////////////////// + // constructor + /////////////////////////////// + // CorrectorComputer(const Basis& basis, + // Material& material, + // std::fstream& log, + // const Dune::ParameterTree& parameterSet) + // : basis_(basis), + // material_(material), + // gamma_(material_.getGamma()), + // log_(log), + // parameterSet_(parameterSet), + // matrixBasis_(std::array<VoigtVector<double,3>,3>{matrixToVoigt(Dune::FieldMatrix<double,3,3>({{1, 0, 0}, {0, 0, 0}, {0, 0, 0}})), + // matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 0, 0}, {0, 1, 0}, {0, 0, 0}})), + // matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 1/std::sqrt(2.0), 0}, {1/std::sqrt(2.0), 0, 0}, {0, 0, 0}}))}), + // phiOffset_(basis.size()) + // {} + + CorrectorComputer(const Basis& basis, + std::shared_ptr<Material> material, + // std::fstream& log, + const Dune::ParameterTree& parameterSet) + : basis_(basis), + material_(material), + // gamma_(material_->getGamma()), + // log_(log), + parameterSet_(parameterSet), + matrixBasis_(std::array<VoigtVector<double,3>,3>{matrixToVoigt(Dune::FieldMatrix<double,3,3>({{1, 0, 0}, {0, 0, 0}, {0, 0, 0}})), + matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 0, 0}, {0, 1, 0}, {0, 0, 0}})), + matrixToVoigt(Dune::FieldMatrix<double,3,3>({{0, 1/std::sqrt(2.0), 0}, {1/std::sqrt(2.0), 0, 0}, {0, 0, 0}}))}), + phiOffset_(basis.size()) + {} // ----------------------------------------------------------------- // --- Assemble Corrector problems void assemble() { - Dune::Timer StiffnessTimer; - assembleCellStiffness(stiffnessMatrix_); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "Stiffness assembly Timer: " << StiffnessTimer.elapsed() << std::endl; - + Dune::Timer StiffnessTimer; + assembleCellStiffness(stiffnessMatrix_); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "Stiffness assembly Timer: " << StiffnessTimer.elapsed() << std::endl; - Dune::Timer LoadVectorTimer; - assembleCellLoad(load_alpha1_ ,x3G_1_); - assembleCellLoad(load_alpha2_ ,x3G_2_); - assembleCellLoad(load_alpha3_ ,x3G_3_); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "Load vector assembly Timer: " << LoadVectorTimer.elapsed() << std::endl; + + Dune::Timer LoadVectorTimer; + assembleCellLoad(load_alpha1_ ,x3G_1_); + assembleCellLoad(load_alpha2_ ,x3G_2_); + assembleCellLoad(load_alpha3_ ,x3G_3_); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "Load vector assembly Timer: " << LoadVectorTimer.elapsed() << std::endl; }; - // void updateMaterial(Material mat) - // { - // this->material_ = mat; - // } + // void updateMaterial(Material mat) + // { + // this->material_ = mat; + // } - void updateMaterial(std::shared_ptr<Material> mat) - { - // std::cout << "updateMaterial of CorrectorComputer" << std::endl; - material_ = mat; - } + void updateMaterial(std::shared_ptr<Material> mat) + { + // std::cout << "updateMaterial of CorrectorComputer" << std::endl; + material_ = mat; + } - /////////////////////////////// - // Getter - /////////////////////////////// - const shared_ptr<Basis> getBasis() {return make_shared<Basis>(basis_);} + /////////////////////////////// + // Getter + /////////////////////////////// + const shared_ptr<Basis> getBasis() {return make_shared<Basis>(basis_);} - Dune::ParameterTree getParameterSet() const {return parameterSet_;} + Dune::ParameterTree getParameterSet() const {return parameterSet_;} - // fstream* getLog(){return &log_;} + // fstream* getLog(){return &log_;} - // double getGamma(){return gamma_;} - double getGamma(){return material_->gamma_;} + // double getGamma(){return gamma_;} + double getGamma(){return material_->gamma_;} - shared_ptr<MatrixCT> getStiffnessMatrix(){return make_shared<MatrixCT>(stiffnessMatrix_);} - shared_ptr<VectorCT> getLoad_alpha1(){return make_shared<VectorCT>(load_alpha1_);} - shared_ptr<VectorCT> getLoad_alpha2(){return make_shared<VectorCT>(load_alpha2_);} - shared_ptr<VectorCT> getLoad_alpha3(){return make_shared<VectorCT>(load_alpha3_);} - // shared_ptr<Material> getMaterial(){return make_shared<Material>(material_);} - shared_ptr<Material> getMaterial(){return material_;} + shared_ptr<MatrixCT> getStiffnessMatrix(){return make_shared<MatrixCT>(stiffnessMatrix_);} + shared_ptr<VectorCT> getLoad_alpha1(){return make_shared<VectorCT>(load_alpha1_);} + shared_ptr<VectorCT> getLoad_alpha2(){return make_shared<VectorCT>(load_alpha2_);} + shared_ptr<VectorCT> getLoad_alpha3(){return make_shared<VectorCT>(load_alpha3_);} + // shared_ptr<Material> getMaterial(){return make_shared<Material>(material_);} + shared_ptr<Material> getMaterial(){return material_;} - // --- Get Correctors - auto getMcontainer(){return mContainer;} - shared_ptr<std::array<VectorCT, 3>> getPhicontainer(){return make_shared<std::array<VectorCT, 3>>(phiContainer);} + // --- Get Correctors + auto getMcontainer(){return mContainer;} + shared_ptr<std::array<VectorCT, 3> > getPhicontainer(){return make_shared<std::array<VectorCT, 3> >(phiContainer);} - auto getMatrixBasiscontainer(){return make_shared<std::array<VoigtVector<double,3>,3 >>(matrixBasis_);} - auto getx3MatrixBasiscontainer(){return x3MatrixBasisContainer_;} + auto getMatrixBasiscontainer(){return make_shared<std::array<VoigtVector<double,3>,3 > >(matrixBasis_);} + auto getx3MatrixBasiscontainer(){return x3MatrixBasisContainer_;} - shared_ptr<VectorCT> getCorr_phi1(){return make_shared<VectorCT>(phi_1_);} - shared_ptr<VectorCT> getCorr_phi2(){return make_shared<VectorCT>(phi_2_);} - shared_ptr<VectorCT> getCorr_phi3(){return make_shared<VectorCT>(phi_3_);} + shared_ptr<VectorCT> getCorr_phi1(){return make_shared<VectorCT>(phi_1_);} + shared_ptr<VectorCT> getCorr_phi2(){return make_shared<VectorCT>(phi_2_);} + shared_ptr<VectorCT> getCorr_phi3(){return make_shared<VectorCT>(phi_3_);} @@ -241,7 +241,7 @@ public: ////////////////////////////////////////////////////////////////// // setOneBaseFunctionToZero ////////////////////////////////////////////////////////////////// - if(parameterSet_.get<bool>("set_oneBasisFunction_Zero ", true)){ + if(parameterSet_.get<bool>("set_oneBasisFunction_Zero ", true)) { Dune::FieldVector<int,3> row; unsigned int arbitraryLeafIndex = parameterSet_.get<unsigned int>("arbitraryLeafIndex", 0); unsigned int arbitraryElementNumber = parameterSet_.get<unsigned int>("arbitraryElementNumber", 0); @@ -272,8 +272,8 @@ public: void computeElementStiffnessMatrix(const typename Basis::LocalView& localView, const Dune::QuadratureRule<double,dim>& quadRule, const std::vector<int>& phaseAtQuadPoint, - ElementMatrixCT& elementMatrix - ) + ElementMatrixCT& elementMatrix + ) { auto element = localView.element(); @@ -285,7 +285,7 @@ public: // LocalBasis-Offset const int localPhiOffset = localView.size(); - const auto& localFiniteElement = localView.tree().child(0).finiteElement(); + const auto& localFiniteElement = localView.tree().child(0).finiteElement(); const auto nSf = localFiniteElement.localBasis().size(); int QPcounter= 0; @@ -320,31 +320,31 @@ public: const auto phase = phaseAtQuadPoint[QPcounter-1]; for (size_t l=0; l< dimworld; l++) - for (size_t j=0; j < nSf; j++ ) - { + for (size_t j=0; j < nSf; j++ ) + { size_t row = localView.tree().child(l).localIndex(j); - + // "phi*phi"-part for (size_t k=0; k < dimworld; k++) - for (size_t i=0; i < nSf; i++) - { + for (size_t i=0; i < nSf; i++) + { double energyDensity= voigtScalarProduct(material_->applyElasticityTensor(deformationGradient[i][k],phase),deformationGradient[j][l]); - size_t col = localView.tree().child(k).localIndex(i); - + size_t col = localView.tree().child(k).localIndex(i); + elementMatrix[row][col] += energyDensity * quadPoint.weight() * integrationElement; - } - + } + // "m*phi" & "phi*m" - part for( size_t m=0; m<3; m++) { - double energyDensityGphi = voigtScalarProduct(material_->applyElasticityTensor(matrixBasis_[m],phase),deformationGradient[j][l]); + double energyDensityGphi = voigtScalarProduct(material_->applyElasticityTensor(matrixBasis_[m],phase),deformationGradient[j][l]); - auto value = energyDensityGphi * quadPoint.weight() * integrationElement; - elementMatrix[row][localPhiOffset+m] += value; - elementMatrix[localPhiOffset+m][row] += value; + auto value = energyDensityGphi * quadPoint.weight() * integrationElement; + elementMatrix[row][localPhiOffset+m] += value; + elementMatrix[localPhiOffset+m][row] += value; } - } + } // "m*m"-part for(size_t m=0; m<3; m++) //TODO ist symmetric.. reicht die hälfte zu berechnen!!! for(size_t n=0; n<3; n++) @@ -352,11 +352,11 @@ public: double energyDensityGG = voigtScalarProduct(material_->applyElasticityTensor(matrixBasis_[m],phase),matrixBasis_[n]); elementMatrix[localPhiOffset+m][localPhiOffset+n] += energyDensityGG * quadPoint.weight() * integrationElement; // += !!!!! (Fixed-Bug) - + } } - // std::cout << "Number of QuadPoints:" << QPcounter << std::endl; - // printmatrix(std::cout, elementMatrix, "elementMatrix", "--"); + // std::cout << "Number of QuadPoints:" << QPcounter << std::endl; + // printmatrix(std::cout, elementMatrix, "elementMatrix", "--"); } @@ -364,18 +364,18 @@ public: * @brief Compute element load vector. Layout: * | f*phi| * | f*m | - * - * @tparam Vector - * @tparam LocalForce - * @param localView - * @param elementRhs - * @param forceTerm + * + * @tparam Vector + * @tparam LocalForce + * @param localView + * @param elementRhs + * @param forceTerm */ template<class Vector, class LocalForce> void computeElementLoadVector( const typename Basis::LocalView& localView, - Vector& elementRhs, - const LocalForce& forceTerm - ) + Vector& elementRhs, + const LocalForce& forceTerm + ) { const auto element = localView.element(); const auto geometry = element.geometry(); @@ -393,7 +393,7 @@ public: // LocalBasis-Offset const int localPhiOffset = localView.size(); - int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); + int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); const auto& quad = Dune::QuadratureRules<double,dim>::rule(element.type(), orderQR); for (const auto& quadPoint : quad) @@ -407,7 +407,7 @@ public: for (size_t i=0; i< jacobians.size(); i++) jacobians[i] = jacobians[i] * geometryJacobianInverse; - + // "f*phi"-part for (size_t i=0; i < nSf; i++) @@ -418,7 +418,7 @@ public: tmpDefGradientV[k][0] = jacobians[i][0][0]; // Y tmpDefGradientV[k][1] = jacobians[i][0][1]; // X2 tmpDefGradientV[k][2] = jacobians[i][0][2]; // X3 - + VoigtVector<double,3> defGradientV = symVoigt(crossSectionDirectionScaling((1.0/(material_->gamma_)),tmpDefGradientV)); double energyDensity= voigtScalarProduct(material_->applyElasticityTensor((-1.0)*matrixToVoigt(forceTerm(quadPos)),localIndicatorFunction(quadPos)),defGradientV); @@ -513,37 +513,37 @@ public: { computeElementStiffnessMatrix(localView, quadRule, phaseAtQuadPoint, elementMatrix); } - - + + // TEST: Check Element-Stiffness-Symmetry: if(parameterSet_.get<bool>("print_debug", false)) { - for (size_t i=0; i<localPhiOffset; i++) + for (size_t i=0; i<localPhiOffset; i++) for (size_t j=0; j<localPhiOffset; j++ ) { - if(abs(elementMatrix[i][j] - elementMatrix[j][i]) > 1e-12 ) - std::cout << "ELEMENT-STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; + if(abs(elementMatrix[i][j] - elementMatrix[j][i]) > 1e-12 ) + std::cout << "ELEMENT-STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; } } ////////////////////////////////////////////////////////////////////////////// // GLOBAL STIFFNES ASSEMBLY ////////////////////////////////////////////////////////////////////////////// for (size_t i=0; i<localPhiOffset; i++) - for (size_t j=0; j<localPhiOffset; j++ ) - { + for (size_t j=0; j<localPhiOffset; j++ ) + { auto row = localView.index(i); auto col = localView.index(j); matrix[row][col] += elementMatrix[i][j]; - } + } for (size_t i=0; i<localPhiOffset; i++) - for(size_t m=0; m<3; m++) - { + for(size_t m=0; m<3; m++) + { auto row = localView.index(i); matrix[row][phiOffset+m] += elementMatrix[i][localPhiOffset+m]; matrix[phiOffset+m][row] += elementMatrix[localPhiOffset+m][i]; - } + } for (size_t m=0; m<3; m++ ) - for (size_t n=0; n<3; n++ ) + for (size_t n=0; n<3; n++ ) matrix[phiOffset+m][phiOffset+n] += elementMatrix[localPhiOffset+m][localPhiOffset+n]; // printmatrix(std::cout, matrix, "StiffnessMatrix", "--"); @@ -562,9 +562,9 @@ public: auto localView = basis_.localView(); const int phiOffset = basis_.dimension(); - // Transform G_alpha's to GridViewFunctions/LocalFunctions + // Transform G_alpha's to GridViewFunctions/LocalFunctions auto loadGVF = Dune::Functions::makeGridViewFunction(forceTerm, basis_.gridView()); - auto loadFunctional = localFunction(loadGVF); + auto loadFunctional = localFunction(loadGVF); for (const auto& element : elements(basis_.gridView())) { @@ -594,8 +594,8 @@ public: // ----------------------------------------------------------------- // --- Functions for global integral mean equals zero constraint auto arbitraryComponentwiseIndices(const int elementNumber, - const int leafIdx - ) + const int leafIdx + ) { // (Local Approach -- works for non Lagrangian-Basis too) // Input : elementNumber & localIdx @@ -627,8 +627,8 @@ public: if (parameterSet_.get<bool>("printMicroOutput ", false)) std::cout << "Setting one Basis-function to zero" << std::endl; - // constexpr int dim = Basis::LocalView::Element::dimension; - + // constexpr int dim = Basis::LocalView::Element::dimension; + unsigned int arbitraryLeafIndex = parameterSet_.template get<unsigned int>("arbitraryLeafIndex", 0); unsigned int arbitraryElementNumber = parameterSet_.template get<unsigned int>("arbitraryElementNumber", 0); //Determine 3 global indices (one for each component of an arbitrary local FE-function) @@ -662,8 +662,8 @@ public: for(const auto& element : elements(basis_.gridView())) { localView.bind(element); - const auto& localFiniteElement = localView.tree().child(k).finiteElement(); - const auto nSf = localFiniteElement.localBasis().size(); + const auto& localFiniteElement = localView.tree().child(k).finiteElement(); + const auto nSf = localFiniteElement.localBasis().size(); for(size_t j=0; j<nSf; j++) { @@ -685,7 +685,7 @@ public: auto integralMean(VectorCT& coeffVector) { - auto GVFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<Dune::FieldVector<double,dim>>(basis_,coeffVector); + auto GVFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<Dune::FieldVector<double,dim> >(basis_,coeffVector); auto localfun = localFunction(GVFunction); auto localView = basis_.localView(); @@ -699,8 +699,8 @@ public: localView.bind(element); localfun.bind(element); const auto& localFiniteElement = localView.tree().child(0).finiteElement(); - - // int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST + + // int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); const auto& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), orderQR); @@ -709,7 +709,7 @@ public: const auto& quadPos = quadPoint.position(); const double integrationElement = element.geometry().integrationElement(quadPos); area += quadPoint.weight() * integrationElement; - + r += localfun(quadPos) * quadPoint.weight() * integrationElement; } } @@ -735,399 +735,399 @@ public: /** * @brief Solve corrector problem for different right-hand sides. - * Choose between solvers: + * Choose between solvers: * 1 : CG-Solver * 2 : GMRES * 3 : QR (default) * 4 : UMFPACK - * - * @return auto + * + * @return auto */ auto solve() { - - bool set_oneBasisFunction_Zero = parameterSet_.get<bool>("set_oneBasisFunction_Zero", false); - bool substract_integralMean = false; - if(parameterSet_.get<bool>("set_IntegralZero", false)) - { - set_oneBasisFunction_Zero = true; - substract_integralMean = true; - } - // set one basis-function to zero - if(set_oneBasisFunction_Zero) - setOneBaseFunctionToZero(); - - //TEST: Compute Condition Number (Can be very expensive !) - const bool verbose = true; - const unsigned int arppp_a_verbosity_level = 2; - const unsigned int pia_verbosity_level = 1; - if(parameterSet_.get<bool>("print_conditionNumber", false)) - { - MatrixInfo<MatrixCT> matrixInfo(stiffnessMatrix_,verbose,arppp_a_verbosity_level,pia_verbosity_level); - std::cout << "Get condition number of Stiffness_CE: " << matrixInfo.getCond2(true) << std::endl; - } - unsigned int Solvertype = parameterSet_.get<unsigned int>("Solvertype", 4); - unsigned int Solver_verbosity = parameterSet_.get<unsigned int>("Solver_verbosity", 2); + bool set_oneBasisFunction_Zero = parameterSet_.get<bool>("set_oneBasisFunction_Zero", false); + bool substract_integralMean = false; + if(parameterSet_.get<bool>("set_IntegralZero", false)) + { + set_oneBasisFunction_Zero = true; + substract_integralMean = true; + } + // set one basis-function to zero + if(set_oneBasisFunction_Zero) + setOneBaseFunctionToZero(); + + //TEST: Compute Condition Number (Can be very expensive !) + const bool verbose = true; + const unsigned int arppp_a_verbosity_level = 2; + const unsigned int pia_verbosity_level = 1; + if(parameterSet_.get<bool>("print_conditionNumber", false)) + { + MatrixInfo<MatrixCT> matrixInfo(stiffnessMatrix_,verbose,arppp_a_verbosity_level,pia_verbosity_level); + std::cout << "Get condition number of Stiffness_CE: " << matrixInfo.getCond2(true) << std::endl; + } + + unsigned int Solvertype = parameterSet_.get<unsigned int>("Solvertype", 4); + unsigned int Solver_verbosity = parameterSet_.get<unsigned int>("Solver_verbosity", 2); - // --- set initial values for solver - x_1_ = load_alpha1_; - x_2_ = load_alpha2_; - x_3_ = load_alpha3_; + // --- set initial values for solver + x_1_ = load_alpha1_; + x_2_ = load_alpha2_; + x_3_ = load_alpha3_; + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "start corrector solver..." << std::endl; + Dune::Timer SolverTimer; + if (Solvertype==1) // CG - SOLVER + { if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "start corrector solver..." << std::endl; - Dune::Timer SolverTimer; - if (Solvertype==1) // CG - SOLVER - { - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "------------ CG - Solver ------------" << std::endl; - Dune::MatrixAdapter<MatrixCT, VectorCT, VectorCT> op(stiffnessMatrix_); - - // Sequential incomplete LU decomposition as the preconditioner - Dune::SeqILU<MatrixCT, VectorCT, VectorCT> ilu0(stiffnessMatrix_,1.0); - int iter = parameterSet_.get<double>("iterations_CG", 999); - // Preconditioned conjugate-gradient solver - Dune::CGSolver<VectorCT> solver(op, - ilu0, //NULL, - 1e-8, // desired residual reduction factorlack - iter, // maximum number of iterations - Solver_verbosity, - true // Try to estimate condition_number - ); // verbosity of the solver - Dune::InverseOperatorResult statistics; - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "solve linear system for x_1.\n"; - solver.apply(x_1_, load_alpha1_, statistics); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "solve linear system for x_2.\n"; - solver.apply(x_2_, load_alpha2_, statistics); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "solve linear system for x_3.\n"; - solver.apply(x_3_, load_alpha3_, statistics); - // log_ << "Solver-type used: " <<" CG-Solver" << std::endl; - - - if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) - { - std::cout << "statistics.converged " << statistics.converged << std::endl; - std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl; - std::cout << "statistics.iterations: " << statistics.iterations << std::endl; - } - } - //////////////////////////////////////////////////////////////////////////////////// - else if (Solvertype==2) // GMRES - SOLVER - { - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "------------ GMRES - Solver ------------" << std::endl; - // Turn the matrix into a linear operator - Dune::MatrixAdapter<MatrixCT,VectorCT,VectorCT> stiffnessOperator(stiffnessMatrix_); - - // Fancy (but only) way to not have a preconditioner at all - Dune::Richardson<VectorCT,VectorCT> preconditioner(1.0); - - // Construct the iterative solver - Dune::RestartedGMResSolver<VectorCT> solver( - stiffnessOperator, // Operator to invert - preconditioner, // Preconditioner - 1e-10, // Desired residual reduction factor - 500, // Number of iterations between restarts, - // here: no restarting - 500, // Maximum number of iterations - Solver_verbosity); // Verbosity of the solver - - // Object storing some statistics about the solving process - Dune::InverseOperatorResult statistics; - - // solve for different Correctors (alpha = 1,2,3) - solver.apply(x_1_, load_alpha1_, statistics); //load_alpha1 now contains the corresponding residual!! - solver.apply(x_2_, load_alpha2_, statistics); - solver.apply(x_3_, load_alpha3_, statistics); - // log_ << "Solver-type used: " <<" GMRES-Solver" << std::endl; - if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) - { - std::cout << "statistics.converged " << statistics.converged << std::endl; - std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl; - std::cout << "statistics.iterations: " << statistics.iterations << std::endl; - } - } - //////////////////////////////////////////////////////////////////////////////////// - else if ( Solvertype==3)// QR - SOLVER - { - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "------------ QR - Solver ------------" << std::endl; - // log_ << "solveLinearSystems: We use QR solver.\n"; - //TODO install suitesparse - Dune::SPQR<MatrixCT> sPQR(stiffnessMatrix_); - // sPQR.setVerbosity(1); - sPQR.setVerbosity(Solver_verbosity); - Dune::InverseOperatorResult statisticsQR; - - if(basis_.dimension() > 1e5) - std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; - - sPQR.apply(x_1_, load_alpha1_, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - sPQR.apply(x_2_, load_alpha2_, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - sPQR.apply(x_3_, load_alpha3_, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // log_ << "Solver-type used: " <<" QR-Solver" << std::endl; - if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) - { - std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - } + std::cout << "------------ CG - Solver ------------" << std::endl; + Dune::MatrixAdapter<MatrixCT, VectorCT, VectorCT> op(stiffnessMatrix_); + + // Sequential incomplete LU decomposition as the preconditioner + Dune::SeqILU<MatrixCT, VectorCT, VectorCT> ilu0(stiffnessMatrix_,1.0); + int iter = parameterSet_.get<double>("iterations_CG", 999); + // Preconditioned conjugate-gradient solver + Dune::CGSolver<VectorCT> solver(op, + ilu0, //NULL, + 1e-8, // desired residual reduction factorlack + iter, // maximum number of iterations + Solver_verbosity, + true // Try to estimate condition_number + ); // verbosity of the solver + Dune::InverseOperatorResult statistics; + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "solve linear system for x_1.\n"; + solver.apply(x_1_, load_alpha1_, statistics); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "solve linear system for x_2.\n"; + solver.apply(x_2_, load_alpha2_, statistics); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "solve linear system for x_3.\n"; + solver.apply(x_3_, load_alpha3_, statistics); + // log_ << "Solver-type used: " <<" CG-Solver" << std::endl; - } - //////////////////////////////////////////////////////////////////////////////////// - else if (Solvertype==4)// UMFPACK - SOLVER - { - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "------------ UMFPACK - Solver ------------" << std::endl; - // log_ << "solveLinearSystems: We use UMFPACK solver.\n"; - - - // #if HAVE_UMFPACK - // std::cout << "HAVE_UMFPACK TRUE" << std::endl; - // #else - // std::cout << "HAVE_UMFPACK FALSE" << std::endl; - // #endif - - // #if HAVE_SUITESPARSE_UMFPACK - // std::cout << "HAVE_SUITESPARSE_UMFPACK TRUE" << std::endl; - // #else - // std::cout << "HAVE_SUITESPARSE_UMFPACK FALSE" << std::endl; - // #endif - - - - if(basis_.dimension() > 1e5) - std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; - - Dune::Solvers::UMFPackSolver<MatrixCT,VectorCT> solver; - solver.setProblem(stiffnessMatrix_,x_1_,load_alpha1_); - // solver.preprocess(); - solver.solve(); - solver.setProblem(stiffnessMatrix_,x_2_,load_alpha2_); - // solver.preprocess(); - solver.solve(); - solver.setProblem(stiffnessMatrix_,x_3_,load_alpha3_); - // solver.preprocess(); - solver.solve(); - // sPQR.apply(x_1, load_alpha1, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // sPQR.apply(x_2, load_alpha2, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // sPQR.apply(x_3, load_alpha3, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // log_ << "Solver-type used: " <<" UMFPACK-Solver" << std::endl; - } - //////////////////////////////////////////////////////////////////////////////////// - else if (Solvertype==5)// CHOLDMOD - SOLVER + + if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) { - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "------------ CHOLMOD - Solver ------------" << std::endl; - // log_ << "solveLinearSystems: We use CHOLMOD solver.\n"; - - if(basis_.dimension() > 1e5) - std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; - - Dune::Solvers::CholmodSolver<MatrixCT,VectorCT> solver; - solver.setProblem(stiffnessMatrix_,x_1_,load_alpha1_); - // solver.preprocess(); - solver.solve(); - solver.setProblem(stiffnessMatrix_,x_2_,load_alpha2_); - // solver.preprocess(); - solver.solve(); - solver.setProblem(stiffnessMatrix_,x_3_,load_alpha3_); - // solver.preprocess(); - solver.solve(); - // sPQR.apply(x_1, load_alpha1, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // sPQR.apply(x_2, load_alpha2, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // sPQR.apply(x_3, load_alpha3, statisticsQR); - // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; - // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; - // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; - // log_ << "Solver-type used: " <<" CHOLMOD-Solver" << std::endl; + std::cout << "statistics.converged " << statistics.converged << std::endl; + std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl; + std::cout << "statistics.iterations: " << statistics.iterations << std::endl; } + } + //////////////////////////////////////////////////////////////////////////////////// + else if (Solvertype==2) // GMRES - SOLVER + { if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "Corrector computation finished. Time required:" << SolverTimer.elapsed() << std::endl; - - //////////////////////////////////////////////////////////////////////////////////// - // Extract phi_alpha & M_alpha coefficients - //////////////////////////////////////////////////////////////////////////////////// - phi_1_.resize(basis_.size()); - phi_1_ = 0; - phi_2_.resize(basis_.size()); - phi_2_ = 0; - phi_3_.resize(basis_.size()); - phi_3_ = 0; - - for(size_t i=0; i<basis_.size(); i++) + std::cout << "------------ GMRES - Solver ------------" << std::endl; + // Turn the matrix into a linear operator + Dune::MatrixAdapter<MatrixCT,VectorCT,VectorCT> stiffnessOperator(stiffnessMatrix_); + + // Fancy (but only) way to not have a preconditioner at all + Dune::Richardson<VectorCT,VectorCT> preconditioner(1.0); + + // Construct the iterative solver + Dune::RestartedGMResSolver<VectorCT> solver( + stiffnessOperator, // Operator to invert + preconditioner, // Preconditioner + 1e-10, // Desired residual reduction factor + 500, // Number of iterations between restarts, + // here: no restarting + 500, // Maximum number of iterations + Solver_verbosity); // Verbosity of the solver + + // Object storing some statistics about the solving process + Dune::InverseOperatorResult statistics; + + // solve for different Correctors (alpha = 1,2,3) + solver.apply(x_1_, load_alpha1_, statistics); //load_alpha1 now contains the corresponding residual!! + solver.apply(x_2_, load_alpha2_, statistics); + solver.apply(x_3_, load_alpha3_, statistics); + // log_ << "Solver-type used: " <<" GMRES-Solver" << std::endl; + if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) { - phi_1_[i] = x_1_[i]; - phi_2_[i] = x_2_[i]; - phi_3_[i] = x_3_[i]; + std::cout << "statistics.converged " << statistics.converged << std::endl; + std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl; + std::cout << "statistics.iterations: " << statistics.iterations << std::endl; } - for(size_t i=0; i<3; i++) + } + //////////////////////////////////////////////////////////////////////////////////// + else if ( Solvertype==3) // QR - SOLVER + { + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "------------ QR - Solver ------------" << std::endl; + // log_ << "solveLinearSystems: We use QR solver.\n"; + //TODO install suitesparse + Dune::SPQR<MatrixCT> sPQR(stiffnessMatrix_); + // sPQR.setVerbosity(1); + sPQR.setVerbosity(Solver_verbosity); + Dune::InverseOperatorResult statisticsQR; + + if(basis_.dimension() > 1e5) + std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; + + sPQR.apply(x_1_, load_alpha1_, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + sPQR.apply(x_2_, load_alpha2_, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + sPQR.apply(x_3_, load_alpha3_, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // log_ << "Solver-type used: " <<" QR-Solver" << std::endl; + if(parameterSet_.get<bool>("printMicroOutput ", false) && Solver_verbosity > 0) { - m_1_[i] = x_1_[phiOffset_+i]; - m_2_[i] = x_2_[phiOffset_+i]; - m_3_[i] = x_3_[phiOffset_+i]; + std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; } - // assemble M_alpha's (actually iota(M_alpha) ) - for (auto& matrix : mContainer) - matrix = 0; + } + //////////////////////////////////////////////////////////////////////////////////// + else if (Solvertype==4) // UMFPACK - SOLVER + { + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "------------ UMFPACK - Solver ------------" << std::endl; + // log_ << "solveLinearSystems: We use UMFPACK solver.\n"; + + + // #if HAVE_UMFPACK + // std::cout << "HAVE_UMFPACK TRUE" << std::endl; + // #else + // std::cout << "HAVE_UMFPACK FALSE" << std::endl; + // #endif + + // #if HAVE_SUITESPARSE_UMFPACK + // std::cout << "HAVE_SUITESPARSE_UMFPACK TRUE" << std::endl; + // #else + // std::cout << "HAVE_SUITESPARSE_UMFPACK FALSE" << std::endl; + // #endif + + + + if(basis_.dimension() > 1e5) + std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; + + Dune::Solvers::UMFPackSolver<MatrixCT,VectorCT> solver; + solver.setProblem(stiffnessMatrix_,x_1_,load_alpha1_); + // solver.preprocess(); + solver.solve(); + solver.setProblem(stiffnessMatrix_,x_2_,load_alpha2_); + // solver.preprocess(); + solver.solve(); + solver.setProblem(stiffnessMatrix_,x_3_,load_alpha3_); + // solver.preprocess(); + solver.solve(); + // sPQR.apply(x_1, load_alpha1, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // sPQR.apply(x_2, load_alpha2, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // sPQR.apply(x_3, load_alpha3, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // log_ << "Solver-type used: " <<" UMFPACK-Solver" << std::endl; + } + //////////////////////////////////////////////////////////////////////////////////// + else if (Solvertype==5) // CHOLDMOD - SOLVER + { + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "------------ CHOLMOD - Solver ------------" << std::endl; + // log_ << "solveLinearSystems: We use CHOLMOD solver.\n"; + + if(basis_.dimension() > 1e5) + std::cout << "WARNING: Using a direct solver with " << basis_.dimension() << " degrees of freedom may be not feasible or slow." << std::endl; + + Dune::Solvers::CholmodSolver<MatrixCT,VectorCT> solver; + solver.setProblem(stiffnessMatrix_,x_1_,load_alpha1_); + // solver.preprocess(); + solver.solve(); + solver.setProblem(stiffnessMatrix_,x_2_,load_alpha2_); + // solver.preprocess(); + solver.solve(); + solver.setProblem(stiffnessMatrix_,x_3_,load_alpha3_); + // solver.preprocess(); + solver.solve(); + // sPQR.apply(x_1, load_alpha1, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // sPQR.apply(x_2, load_alpha2, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // sPQR.apply(x_3, load_alpha3, statisticsQR); + // std::cout << "statistics.converged " << statisticsQR.converged << std::endl; + // std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl; + // std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl; + // log_ << "Solver-type used: " <<" CHOLMOD-Solver" << std::endl; + } + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "Corrector computation finished. Time required:" << SolverTimer.elapsed() << std::endl; + + //////////////////////////////////////////////////////////////////////////////////// + // Extract phi_alpha & M_alpha coefficients + //////////////////////////////////////////////////////////////////////////////////// + phi_1_.resize(basis_.size()); + phi_1_ = 0; + phi_2_.resize(basis_.size()); + phi_2_ = 0; + phi_3_.resize(basis_.size()); + phi_3_ = 0; + + for(size_t i=0; i<basis_.size(); i++) + { + phi_1_[i] = x_1_[i]; + phi_2_[i] = x_2_[i]; + phi_3_[i] = x_3_[i]; + } + for(size_t i=0; i<3; i++) + { + m_1_[i] = x_1_[phiOffset_+i]; + m_2_[i] = x_2_[phiOffset_+i]; + m_3_[i] = x_3_[phiOffset_+i]; + } + // assemble M_alpha's (actually iota(M_alpha) ) - for(size_t i=0; i<3; i++) - { - mContainer[0] += m_1_[i]*voigtToMatrix(matrixBasis_[i]); - mContainer[1] += m_2_[i]*voigtToMatrix(matrixBasis_[i]); - mContainer[2] += m_3_[i]*voigtToMatrix(matrixBasis_[i]); - } + for (auto& matrix : mContainer) + matrix = 0; - if(parameterSet_.get<bool>("print_corrector_matrices", false)) - { - std::cout << "--- plot corrector-Matrices M_alpha --- " << std::endl; - printmatrix(std::cout, mContainer[0], "Corrector-Matrix M_1", "--"); - printmatrix(std::cout, mContainer[1], "Corrector-Matrix M_2", "--"); - printmatrix(std::cout, mContainer[2], "Corrector-Matrix M_3", "--"); - } + for(size_t i=0; i<3; i++) + { + mContainer[0] += m_1_[i]*voigtToMatrix(matrixBasis_[i]); + mContainer[1] += m_2_[i]*voigtToMatrix(matrixBasis_[i]); + mContainer[2] += m_3_[i]*voigtToMatrix(matrixBasis_[i]); + } - if(parameterSet_.get<bool>("writeCorrectorsVTK", false)) - this->writeCorrectorsVTK(parameterSet_.get<int>("gridLevel", 0)); + if(parameterSet_.get<bool>("print_corrector_matrices", false)) + { + std::cout << "--- plot corrector-Matrices M_alpha --- " << std::endl; + printmatrix(std::cout, mContainer[0], "Corrector-Matrix M_1", "--"); + printmatrix(std::cout, mContainer[1], "Corrector-Matrix M_2", "--"); + printmatrix(std::cout, mContainer[2], "Corrector-Matrix M_3", "--"); + } - // log_ << "---------- OUTPUT ----------" << std::endl; - // log_ << " --------------------" << std::endl; - // log_ << "Corrector-Matrix M_1: \n" << mContainer[0] << std::endl; - // log_ << " --------------------" << std::endl; - // log_ << "Corrector-Matrix M_2: \n" << mContainer[1] << std::endl; - // log_ << " --------------------" << std::endl; - // log_ << "Corrector-Matrix M_3: \n" << mContainer[2] << std::endl; - // log_ << " --------------------" << std::endl; + if(parameterSet_.get<bool>("writeCorrectorsVTK", false)) + this->writeCorrectorsVTK(parameterSet_.get<int>("gridLevel", 0)); + // log_ << "---------- OUTPUT ----------" << std::endl; + // log_ << " --------------------" << std::endl; + // log_ << "Corrector-Matrix M_1: \n" << mContainer[0] << std::endl; + // log_ << " --------------------" << std::endl; + // log_ << "Corrector-Matrix M_2: \n" << mContainer[1] << std::endl; + // log_ << " --------------------" << std::endl; + // log_ << "Corrector-Matrix M_3: \n" << mContainer[2] << std::endl; + // log_ << " --------------------" << std::endl; - if(parameterSet_.get<bool>("write_IntegralMean", false)) + + if(parameterSet_.get<bool>("write_IntegralMean", false)) + { + std::cout << "check integralMean phi_1: " << std::endl; + auto A = integralMean(phi_1_); + for(size_t i=0; i<3; i++) { - std::cout << "check integralMean phi_1: " << std::endl; - auto A = integralMean(phi_1_); - for(size_t i=0; i<3; i++) - { - std::cout << "Integral-Mean phi_1 : " << A[i] << std::endl; - } + std::cout << "Integral-Mean phi_1 : " << A[i] << std::endl; } - if(substract_integralMean) + } + if(substract_integralMean) + { + Dune::Timer integralMeanTimer; + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << " --- subtracting integralMean --- " << std::endl; + subtractIntegralMean(phi_1_); + subtractIntegralMean(phi_2_); + subtractIntegralMean(phi_3_); + subtractIntegralMean(x_1_); + subtractIntegralMean(x_2_); + subtractIntegralMean(x_3_); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "substract integral mean took " << integralMeanTimer.elapsed() << " seconds " << std::endl; + ////////////////////////////////////////// + // Check Integral-mean again: + ////////////////////////////////////////// + if(parameterSet_.get<bool>("write_IntegralMean", false)) { - Dune::Timer integralMeanTimer; - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << " --- subtracting integralMean --- " << std::endl; - subtractIntegralMean(phi_1_); - subtractIntegralMean(phi_2_); - subtractIntegralMean(phi_3_); - subtractIntegralMean(x_1_); - subtractIntegralMean(x_2_); - subtractIntegralMean(x_3_); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "substract integral mean took " << integralMeanTimer.elapsed() << " seconds " << std::endl; - ////////////////////////////////////////// - // Check Integral-mean again: - ////////////////////////////////////////// - if(parameterSet_.get<bool>("write_IntegralMean", false)) - { - auto A = integralMean(phi_1_); - for(size_t i=0; i<3; i++) - { - std::cout << "Integral-Mean phi_1 (Check again) : " << A[i] << std::endl; - } - } + auto A = integralMean(phi_1_); + for(size_t i=0; i<3; i++) + { + std::cout << "Integral-Mean phi_1 (Check again) : " << A[i] << std::endl; + } } - ///////////////////////////////////////////////////////// - // Write Solution (Corrector Coefficients) in Logs - ///////////////////////////////////////////////////////// - // if(parameterSet_.get<bool>("write_corrector_phi1", false)) - // { - // log_ << "\nSolution of Corrector problems:\n"; - // log_ << "\n Corrector_phi1:\n"; - // log_ << x_1_ << std::endl; - // } - // if(parameterSet_.get<bool>("write_corrector_phi2", false)) - // { - // log_ << "-----------------------------------------------------"; - // log_ << "\n Corrector_phi2:\n"; - // log_ << x_2_ << std::endl; - // } - // if(parameterSet_.get<bool>("write_corrector_phi3", false)) - // { - // log_ << "-----------------------------------------------------"; - // log_ << "\n Corrector_phi3:\n"; - // log_ << x_3_ << std::endl; - // } + } + ///////////////////////////////////////////////////////// + // Write Solution (Corrector Coefficients) in Logs + ///////////////////////////////////////////////////////// + // if(parameterSet_.get<bool>("write_corrector_phi1", false)) + // { + // log_ << "\nSolution of Corrector problems:\n"; + // log_ << "\n Corrector_phi1:\n"; + // log_ << x_1_ << std::endl; + // } + // if(parameterSet_.get<bool>("write_corrector_phi2", false)) + // { + // log_ << "-----------------------------------------------------"; + // log_ << "\n Corrector_phi2:\n"; + // log_ << x_2_ << std::endl; + // } + // if(parameterSet_.get<bool>("write_corrector_phi3", false)) + // { + // log_ << "-----------------------------------------------------"; + // log_ << "\n Corrector_phi3:\n"; + // log_ << x_3_ << std::endl; + // } } /** * @brief Write correctors as grid functions to VTK. - * + * * @param level GridLevel */ void writeCorrectorsVTK(const int level) { - std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); - std::string vtkOutputName = parameterSet_.get("resultPath", "../../outputs") + "/" + baseName; - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "Write Correctors to VTK with Filename:" << vtkOutputName << std::endl; - - - int subsamplingRefinement = parameterSet_.get<int>("subsamplingRefinement", 2); - Dune::SubsamplingVTKWriter<typename Basis::GridView> vtkWriter(basis_.gridView(), Dune::refinementLevels(subsamplingRefinement)); - // Dune::VTKWriter<typename Basis::GridView> vtkWriter(basis_.gridView()); - - vtkWriter.addVertexData( - Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_1_), - Dune::VTK::FieldInfo("Corrector phi_1 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); - vtkWriter.addVertexData( - Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_2_), - Dune::VTK::FieldInfo("Corrector phi_2 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); - vtkWriter.addVertexData( - Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_3_), - Dune::VTK::FieldInfo("Corrector phi_3 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); - vtkWriter.write(vtkOutputName + "Correctors-level"+ std::to_string(level)); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "wrote Corrector-VTK data to file: " + vtkOutputName + "-level" + std::to_string(level) << std::endl; + std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); + std::string vtkOutputName = parameterSet_.get("resultPath", "../../outputs") + "/" + baseName; + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "Write Correctors to VTK with Filename:" << vtkOutputName << std::endl; + + + int subsamplingRefinement = parameterSet_.get<int>("subsamplingRefinement", 2); + Dune::SubsamplingVTKWriter<typename Basis::GridView> vtkWriter(basis_.gridView(), Dune::refinementLevels(subsamplingRefinement)); + // Dune::VTKWriter<typename Basis::GridView> vtkWriter(basis_.gridView()); + + vtkWriter.addVertexData( + Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_1_), + Dune::VTK::FieldInfo("Corrector phi_1 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); + vtkWriter.addVertexData( + Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_2_), + Dune::VTK::FieldInfo("Corrector phi_2 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); + vtkWriter.addVertexData( + Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_3_), + Dune::VTK::FieldInfo("Corrector phi_3 level"+ std::to_string(level) , Dune::VTK::FieldInfo::Type::vector, dim)); + vtkWriter.write(vtkOutputName + "Correctors-level"+ std::to_string(level)); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "wrote Corrector-VTK data to file: " + vtkOutputName + "-level" + std::to_string(level) << std::endl; } // ----------------------------------------------------------------- // --- Compute norms of the corrector functions: void computeNorms() { - computeL2Norm(); - computeL2SymGrad(); - std::cout<< "Frobenius-Norm of M1_: " << mContainer[0].frobenius_norm() << std::endl; - std::cout<< "Frobenius-Norm of M2_: " << mContainer[1].frobenius_norm() << std::endl; - std::cout<< "Frobenius-Norm of M3_: " << mContainer[2].frobenius_norm() << std::endl; + computeL2Norm(); + computeL2SymGrad(); + std::cout<< "Frobenius-Norm of M1_: " << mContainer[0].frobenius_norm() << std::endl; + std::cout<< "Frobenius-Norm of M2_: " << mContainer[1].frobenius_norm() << std::endl; + std::cout<< "Frobenius-Norm of M3_: " << mContainer[2].frobenius_norm() << std::endl; } void computeL2Norm() @@ -1195,23 +1195,23 @@ public: localfun_3.bind(element); auto geometry = element.geometry(); - const auto& localFiniteElement = localView.tree().child(0).finiteElement(); + const auto& localFiniteElement = localView.tree().child(0).finiteElement(); - int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 ); + int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 ); const auto& quad = Dune::QuadratureRules<double,dim>::rule(element.type(), orderQR); for (const auto& quadPoint : quad) { - const auto& quadPos = quadPoint.position(); - const auto integrationElement = geometry.integrationElement(quadPos); + const auto& quadPos = quadPoint.position(); + const auto integrationElement = geometry.integrationElement(quadPos); - auto scaledSymGrad1 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_1(quadPos))); - auto scaledSymGrad2 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_2(quadPos))); - auto scaledSymGrad3 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_3(quadPos))); + auto scaledSymGrad1 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_1(quadPos))); + auto scaledSymGrad2 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_2(quadPos))); + auto scaledSymGrad3 = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), localfun_3(quadPos))); - error_1 += scalarProduct(scaledSymGrad1,scaledSymGrad1) * quadPoint.weight() * integrationElement; - error_2 += scalarProduct(scaledSymGrad2,scaledSymGrad2) * quadPoint.weight() * integrationElement; - error_3 += scalarProduct(scaledSymGrad3,scaledSymGrad3) * quadPoint.weight() * integrationElement; + error_1 += scalarProduct(scaledSymGrad1,scaledSymGrad1) * quadPoint.weight() * integrationElement; + error_2 += scalarProduct(scaledSymGrad2,scaledSymGrad2) * quadPoint.weight() * integrationElement; + error_3 += scalarProduct(scaledSymGrad3,scaledSymGrad3) * quadPoint.weight() * integrationElement; } } std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_1): " << sqrt(error_1) << std::endl; @@ -1221,10 +1221,10 @@ public: } /** - * @brief Test: Check orthogonality relation (75) in + * @brief Test: Check orthogonality relation (75) in * [Böhnlein,Neukamm,Padilla-Garza,Sander - A homogenized bending theory for prestrained plates]. - * - * @return auto + * + * @return auto */ auto check_Orthogonality() { @@ -1242,20 +1242,20 @@ public: const std::array<decltype(localfun_1)*,3> phiDerContainer = {&localfun_1 , &localfun_2 , &localfun_3 }; auto localIndicatorFunction = material_->getLocalIndicatorFunction(); - + for(int a=0; a<3; a++) - for(int b=0; b<3; b++) - { - double energy = 0.0; + for(int b=0; b<3; b++) + { + double energy = 0.0; - auto DerPhi1 = *phiDerContainer[a]; - auto DerPhi2 = *phiDerContainer[b]; - - auto matrixFieldGGVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer_[a], basis_.gridView()); - auto matrixFieldG = localFunction(matrixFieldGGVF); + auto DerPhi1 = *phiDerContainer[a]; + auto DerPhi2 = *phiDerContainer[b]; - for (const auto& e : elements(basis_.gridView())) - { + auto matrixFieldGGVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer_[a], basis_.gridView()); + auto matrixFieldG = localFunction(matrixFieldGGVF); + + for (const auto& e : elements(basis_.gridView())) + { localView.bind(e); matrixFieldG.bind(e); DerPhi1.bind(e); @@ -1271,33 +1271,33 @@ public: const auto& quad = Dune::QuadratureRules<double, dim>::rule(e.type(), orderQR); - for (const auto& quadPoint : quad) + for (const auto& quadPoint : quad) { - const auto& quadPos = quadPoint.position(); - const double integrationElement = geometry.integrationElement(quadPos); - - auto Chi = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), DerPhi2(quadPos))) + mContainer[b]; + const auto& quadPos = quadPoint.position(); + const double integrationElement = geometry.integrationElement(quadPos); - const auto strain1 = symVoigt(crossSectionDirectionScaling(1.0/(material_->gamma_), DerPhi1(quadPos))); - - auto G = matrixFieldG(quadPos); + auto Chi = sym(crossSectionDirectionScaling(1.0/(material_->gamma_), DerPhi2(quadPos))) + mContainer[b]; - auto tmp = matrixToVoigt(G + mContainer[a]) + strain1; + const auto strain1 = symVoigt(crossSectionDirectionScaling(1.0/(material_->gamma_), DerPhi1(quadPos))); - double energyDensity= voigtScalarProduct(material_->applyElasticityTensor(tmp,localIndicatorFunction(quadPos)),symVoigt(Chi)); + auto G = matrixFieldG(quadPos); - elementEnergy += energyDensity * quadPoint.weight() * integrationElement; + auto tmp = matrixToVoigt(G + mContainer[a]) + strain1; + + double energyDensity= voigtScalarProduct(material_->applyElasticityTensor(tmp,localIndicatorFunction(quadPos)),symVoigt(Chi)); + + elementEnergy += energyDensity * quadPoint.weight() * integrationElement; } energy += elementEnergy; - } - if(parameterSet_.get<bool>("print_debug", false)) - std::cout << "check_Orthogonality:" << "("<< a <<"," << b << "): " << energy << std::endl; + } + if(parameterSet_.get<bool>("print_debug", false)) + std::cout << "check_Orthogonality:" << "("<< a <<"," << b << "): " << energy << std::endl; - if(energy > 1e-1) - std::cout << "WARNING: check_Orthogonality failed! apparently orthogonality (75) not satisfied on discrete level" << std::endl; + if(energy > 1e-1) + std::cout << "WARNING: check_Orthogonality failed! apparently orthogonality (75) not satisfied on discrete level" << std::endl; - } + } std::cout << "Time required for orthogonality check: " << orthogonalityTimer.elapsed() << std::endl; return 0; } @@ -1316,27 +1316,27 @@ public: const auto localPhiOffset = localView.size(); for(size_t i=0; i<localPhiOffset; i++) - for(size_t j=0; j<localPhiOffset; j++ ) - { + for(size_t j=0; j<localPhiOffset; j++ ) + { auto row = localView.index(i); auto col = localView.index(j); if(abs( stiffnessMatrix_[row][col] - stiffnessMatrix_[col][row]) > 1e-12 ) - std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; - } + std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; + } for(size_t i=0; i<localPhiOffset; i++) - for(size_t m=0; m<3; m++) - { + for(size_t m=0; m<3; m++) + { auto row = localView.index(i); if(abs( stiffnessMatrix_[row][phiOffset_+m] - stiffnessMatrix_[phiOffset_+m][row]) > 1e-12 ) - std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; + std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; - } + } for(size_t m=0; m<3; m++ ) - for(size_t n=0; n<3; n++ ) - { + for(size_t n=0; n<3; n++ ) + { if(abs(stiffnessMatrix_[phiOffset_+m][phiOffset_+n] - stiffnessMatrix_[phiOffset_+n][phiOffset_+m]) > 1e-12 ) - std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; - } + std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl; + } } std::cout << "--- Symmetry test passed ---" << std::endl; } diff --git a/dune/microstructure/EffectiveQuantitiesComputer.hh b/dune/microstructure/EffectiveQuantitiesComputer.hh index d6476cceaa5b81290346addaa53e14b0f89f8d02..99b60e2e76c4e707f8c996663b9ed36c2742b910 100644 --- a/dune/microstructure/EffectiveQuantitiesComputer.hh +++ b/dune/microstructure/EffectiveQuantitiesComputer.hh @@ -2,7 +2,7 @@ #define DUNE_MICROSTRUCTURE_EFFECTIVEQUANTITIESCOMPUTER_HH #include <dune/common/parametertree.hh> -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/istl/io.hh> #include <dune/istl/matrix.hh> #include <dune/microstructure/matrix_operations.hh> @@ -20,248 +20,248 @@ template <class Basis, class Material> class EffectiveQuantitiesComputer { public: - static const int dimworld = 3; - static const int dim = Basis::GridView::dimension; - using Domain = typename CorrectorComputer<Basis,Material>::Domain; - using VectorRT = typename CorrectorComputer<Basis,Material>::VectorRT; - using MatrixRT = typename CorrectorComputer<Basis,Material>::MatrixRT; - using Func2Tensor = typename CorrectorComputer<Basis,Material>::Func2Tensor; - using FuncVector = typename CorrectorComputer<Basis,Material>::FuncVector; - using VectorCT = typename CorrectorComputer<Basis,Material>::VectorCT; - using Func2int = std::function< int(const Domain&) >; - using MatrixPhase = std::function< MatrixRT(const int&) >; + static const int dimworld = 3; + static const int dim = Basis::GridView::dimension; + using Domain = typename CorrectorComputer<Basis,Material>::Domain; + using VectorRT = typename CorrectorComputer<Basis,Material>::VectorRT; + using MatrixRT = typename CorrectorComputer<Basis,Material>::MatrixRT; + using Func2Tensor = typename CorrectorComputer<Basis,Material>::Func2Tensor; + using FuncVector = typename CorrectorComputer<Basis,Material>::FuncVector; + using VectorCT = typename CorrectorComputer<Basis,Material>::VectorCT; + using Func2int = std::function< int (const Domain&) >; + using MatrixPhase = std::function< MatrixRT(const int&) >; protected: - // CorrectorComputer<Basis,Material>& correctorComputer_; - std::shared_ptr<CorrectorComputer<Basis,Material>> correctorComputer_; - // const Material& material_; //Get this from correctorComputer_ this is now an std::shared_ptr. + // CorrectorComputer<Basis,Material>& correctorComputer_; + std::shared_ptr<CorrectorComputer<Basis,Material> > correctorComputer_; + // const Material& material_; //Get this from correctorComputer_ this is now an std::shared_ptr. public: - MatrixRT Qeff_; // Effective moduli COEFFICIENTS - VectorRT Bhat_; - VectorRT Beff_; // Effective prestrain COEFFICIENTS - - - /////////////////////////////// - // constructor - /////////////////////////////// - // EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer, - // const Material& material) - // : correctorComputer_(correctorComputer), - // material_(material) - // {} - // EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer) - // : correctorComputer_(correctorComputer) - // {} - EffectiveQuantitiesComputer(std::shared_ptr<CorrectorComputer<Basis,Material>> correctorComputer) - : correctorComputer_(correctorComputer) - {} + MatrixRT Qeff_; // Effective moduli COEFFICIENTS + VectorRT Bhat_; + VectorRT Beff_; // Effective prestrain COEFFICIENTS - /////////////////////////////// - // Getter - /////////////////////////////// - // CorrectorComputer<Basis,Material> getCorrectorComputer(){return correctorComputer_;} - CorrectorComputer<Basis,Material> getCorrectorComputer(){return *correctorComputer_;} + /////////////////////////////// + // constructor + /////////////////////////////// + // EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer, + // const Material& material) + // : correctorComputer_(correctorComputer), + // material_(material) + // {} + // EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer) + // : correctorComputer_(correctorComputer) + // {} + EffectiveQuantitiesComputer(std::shared_ptr<CorrectorComputer<Basis,Material> > correctorComputer) + : correctorComputer_(correctorComputer) + {} - const shared_ptr<Basis> getBasis() {return *correctorComputer_.getBasis();} + /////////////////////////////// + // Getter + /////////////////////////////// + // CorrectorComputer<Basis,Material> getCorrectorComputer(){return correctorComputer_;} + CorrectorComputer<Basis,Material> getCorrectorComputer(){return *correctorComputer_;} - auto getQeff(){return Qeff_;} - auto getBeff(){return Beff_;} + const shared_ptr<Basis> getBasis() {return *correctorComputer_.getBasis();} - void updateCorrectorComputer(std::shared_ptr<CorrectorComputer<Basis,Material>> correctorComputer) - { - correctorComputer_ = correctorComputer; - } + auto getQeff(){return Qeff_;} + auto getBeff(){return Beff_;} + + + void updateCorrectorComputer(std::shared_ptr<CorrectorComputer<Basis,Material> > correctorComputer) + { + correctorComputer_ = correctorComputer; + } // ----------------------------------------------------------------- // --- Compute Effective Quantities - void computeEffectiveQuantities() - { - Dune::Timer effectiveQuantitiesTimer; - Dune::ParameterTree parameterSet = correctorComputer_->getParameterSet(); - - if (parameterSet.get<bool>("printMicroOutput ", false)) - std::cout << "starting effective quantities computation..." << std::endl; - - - auto MContainer = correctorComputer_->getMcontainer(); - auto MatrixBasisContainer = correctorComputer_->getMatrixBasiscontainer(); - auto x3MatrixBasisContainer = correctorComputer_->getx3MatrixBasiscontainer(); - - auto gamma = correctorComputer_->getGamma(); - auto basis = *correctorComputer_->getBasis(); - - - shared_ptr<VectorCT> phiBasis[3] = {correctorComputer_->getCorr_phi1(), - correctorComputer_->getCorr_phi2(), - correctorComputer_->getCorr_phi3() - }; - - auto localIndicatorFunction = (correctorComputer_->material_)->getLocalIndicatorFunction(); - - Qeff_ = 0 ; - Bhat_ = 0; - - for(size_t a=0; a < 3; a++) - for(size_t b=0; b < 3; b++) - { - double energy = 0.0; - double prestrain = 0.0; - auto localView = basis.localView(); + void computeEffectiveQuantities() + { + Dune::Timer effectiveQuantitiesTimer; + Dune::ParameterTree parameterSet = correctorComputer_->getParameterSet(); - auto GVFunc_a = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiBasis[a])); - auto localfun_a = localFunction(GVFunc_a); + if (parameterSet.get<bool>("printMicroOutput ", false)) + std::cout << "starting effective quantities computation..." << std::endl; - auto matrixFieldG1GVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer[a], basis.gridView()); - auto matrixFieldG1 = localFunction(matrixFieldG1GVF); - auto matrixFieldG2GVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer[b], basis.gridView()); - auto matrixFieldG2 = localFunction(matrixFieldG2GVF); - for (const auto& element : elements(basis.gridView())) - { - localView.bind(element); - matrixFieldG1.bind(element); - matrixFieldG2.bind(element); - localfun_a.bind(element); - - localIndicatorFunction.bind(element); - - double elementEnergy = 0.0; - double elementPrestrain = 0.0; - - auto geometry = element.geometry(); - const auto& localFiniteElement = localView.tree().child(0).finiteElement(); - - int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); - - const auto& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), orderQR); - - for (const auto& quadPoint : quad) - { - const auto& quadPos = quadPoint.position(); - const double integrationElement = geometry.integrationElement(quadPos); - - auto Chi1 = sym(crossSectionDirectionScaling(1.0/gamma, localfun_a(quadPos))) + MContainer[a]; - - auto G1 = matrixFieldG1(quadPos); - auto G2 = matrixFieldG2(quadPos); - - auto X1 = matrixToVoigt(G1 + Chi1); - - double energyDensity= voigtScalarProduct((correctorComputer_->material_)->applyElasticityTensor(X1,localIndicatorFunction(quadPos)), matrixToVoigt(sym(G2))); - - elementEnergy += energyDensity * quadPoint.weight() * integrationElement; // quad[quadPoint].weight() ??? - if (b==0) - { - auto prestrainPhaseValue = (correctorComputer_->material_)->prestrain(localIndicatorFunction(quadPos),element.geometry().global(quadPos)); - auto value = voigtScalarProduct((correctorComputer_->material_)->applyElasticityTensor(X1,localIndicatorFunction(quadPos)),matrixToVoigt(sym(prestrainPhaseValue))); - - elementPrestrain += value * quadPoint.weight() * integrationElement; - } - } - energy += elementEnergy; - prestrain += elementPrestrain; - - } - Qeff_[a][b] = energy; - if (b==0) - Bhat_[a] = prestrain; - } - if(parameterSet.get<bool>("print_debug", false)) - { - printmatrix(std::cout, Qeff_, "Qeff_", "--"); - printvector(std::cout, Bhat_, "Bhat_", "--"); - } + auto MContainer = correctorComputer_->getMcontainer(); + auto MatrixBasisContainer = correctorComputer_->getMatrixBasiscontainer(); + auto x3MatrixBasisContainer = correctorComputer_->getx3MatrixBasiscontainer(); - /////////////////////////////// - // Compute effective Prestrain B_eff (by solving linear system) - ////////////////////////////// - - // std::cout << "------- Information about Q matrix -----" << std::endl; // TODO - // MatrixInfo<MatrixRT> matrixInfo(Qeff_,true,2,1); - // std::cout << "----------------------------------------" << std::endl; - Qeff_.solve(Beff_,Bhat_); - if(parameterSet.get<bool>("print_debug", false)) - printvector(std::cout, Beff_, "Beff_", "--"); - - //LOG-Output - // auto& log = *(correctorComputer_.getLog()); - // log << "--- Effective moduli --- " << std::endl; - // log << "Qeff_: \n" << Qeff_ << std::endl; - // log << "------------------------ " << std::endl; - // log << "--- Prestrain Output --- " << std::endl; - // log << "Bhat_: " << Bhat_ << std::endl; - // log << "Beff_: " << Beff_ << " (Effective Prestrain)" << std::endl; - // log << "------------------------ " << std::endl; - - // std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl; - if (parameterSet.get<bool>("printMicroOutput ", false)) - std::cout << "Time required to solve for effective quantities: " << effectiveQuantitiesTimer.elapsed() << std::endl; - return ; - } + auto gamma = correctorComputer_->getGamma(); + auto basis = *correctorComputer_->getBasis(); - // ----------------------------------------------------------------- - // --- write Data to .Txt-File for Matlab / Optimization-Code - void writeEffectiveQuantitiesToTxt(std::string outputPath) - { - std::cout << "write effective quantities as .txt files to output folder..." << std::endl; - writeMatrixToMatlab(Qeff_, outputPath + "/QMatrix.txt"); - // write effective Prestrain in Matrix for Output - Dune::FieldMatrix<double,1,3> BeffMat; - BeffMat[0] = Beff_; - writeMatrixToMatlab(BeffMat, outputPath + "/BMatrix.txt"); - return; - } + shared_ptr<VectorCT> phiBasis[3] = {correctorComputer_->getCorr_phi1(), + correctorComputer_->getCorr_phi2(), + correctorComputer_->getCorr_phi3() + }; - template<class MatrixFunction> - double energySP(const MatrixFunction& matrixFieldFuncA, - const MatrixFunction& matrixFieldFuncB) - { + auto localIndicatorFunction = (correctorComputer_->material_)->getLocalIndicatorFunction(); + + Qeff_ = 0 ; + Bhat_ = 0; + + for(size_t a=0; a < 3; a++) + for(size_t b=0; b < 3; b++) + { double energy = 0.0; - auto mu_ = *correctorComputer_->getMu(); - auto lambda_ = *correctorComputer_->getLambda(); - auto gamma = correctorComputer_->getGamma(); - auto basis = *correctorComputer_->getBasis(); + double prestrain = 0.0; auto localView = basis.localView(); - auto localIndicatorFunction = (correctorComputer_->material_)->getLocalIndicatorFunction(); + auto GVFunc_a = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiBasis[a])); + auto localfun_a = localFunction(GVFunc_a); - auto matrixFieldAGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView()); - auto matrixFieldA = localFunction(matrixFieldAGVF); - auto matrixFieldBGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView()); - auto matrixFieldB = localFunction(matrixFieldBGVF); + auto matrixFieldG1GVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer[a], basis.gridView()); + auto matrixFieldG1 = localFunction(matrixFieldG1GVF); + auto matrixFieldG2GVF = Dune::Functions::makeGridViewFunction(x3MatrixBasisContainer[b], basis.gridView()); + auto matrixFieldG2 = localFunction(matrixFieldG2GVF); - for (const auto& e : elements(basis.gridView())) + for (const auto& element : elements(basis.gridView())) { - localView.bind(e); - matrixFieldA.bind(e); - matrixFieldB.bind(e); - localIndicatorFunction.bind(e); + localView.bind(element); + matrixFieldG1.bind(element); + matrixFieldG2.bind(element); + localfun_a.bind(element); - double elementEnergy = 0.0; + localIndicatorFunction.bind(element); - auto geometry = e.geometry(); - const auto& localFiniteElement = localView.tree().child(0).finiteElement(); + double elementEnergy = 0.0; + double elementPrestrain = 0.0; - int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); - const auto& quad = Dune::QuadratureRules<double, dim>::rule(e.type(), orderQR); - for (const auto& quadPoint : quad) - { - const auto& quadPos = quadPoint.position(); - const double integrationElement = geometry.integrationElement(quadPos); + auto geometry = element.geometry(); + const auto& localFiniteElement = localView.tree().child(0).finiteElement(); + + int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); - double energyDensity= scalarProduct((correctorComputer_->material_)->applyElasticityTensor(matrixFieldA(quadPos),localIndicatorFunction(quadPos)),sym(matrixFieldB(quadPos))); + const auto& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), orderQR); - elementEnergy += energyDensity * quadPoint.weight() * integrationElement; + for (const auto& quadPoint : quad) + { + const auto& quadPos = quadPoint.position(); + const double integrationElement = geometry.integrationElement(quadPos); + + auto Chi1 = sym(crossSectionDirectionScaling(1.0/gamma, localfun_a(quadPos))) + MContainer[a]; + + auto G1 = matrixFieldG1(quadPos); + auto G2 = matrixFieldG2(quadPos); + + auto X1 = matrixToVoigt(G1 + Chi1); + + double energyDensity= voigtScalarProduct((correctorComputer_->material_)->applyElasticityTensor(X1,localIndicatorFunction(quadPos)), matrixToVoigt(sym(G2))); + + elementEnergy += energyDensity * quadPoint.weight() * integrationElement; // quad[quadPoint].weight() ??? + if (b==0) + { + auto prestrainPhaseValue = (correctorComputer_->material_)->prestrain(localIndicatorFunction(quadPos),element.geometry().global(quadPos)); + auto value = voigtScalarProduct((correctorComputer_->material_)->applyElasticityTensor(X1,localIndicatorFunction(quadPos)),matrixToVoigt(sym(prestrainPhaseValue))); + + elementPrestrain += value * quadPoint.weight() * integrationElement; } - energy += elementEnergy; + } + energy += elementEnergy; + prestrain += elementPrestrain; + } - return energy; + Qeff_[a][b] = energy; + if (b==0) + Bhat_[a] = prestrain; + } + if(parameterSet.get<bool>("print_debug", false)) + { + printmatrix(std::cout, Qeff_, "Qeff_", "--"); + printvector(std::cout, Bhat_, "Bhat_", "--"); + } + + /////////////////////////////// + // Compute effective Prestrain B_eff (by solving linear system) + ////////////////////////////// + + // std::cout << "------- Information about Q matrix -----" << std::endl; // TODO + // MatrixInfo<MatrixRT> matrixInfo(Qeff_,true,2,1); + // std::cout << "----------------------------------------" << std::endl; + Qeff_.solve(Beff_,Bhat_); + if(parameterSet.get<bool>("print_debug", false)) + printvector(std::cout, Beff_, "Beff_", "--"); + + //LOG-Output + // auto& log = *(correctorComputer_.getLog()); + // log << "--- Effective moduli --- " << std::endl; + // log << "Qeff_: \n" << Qeff_ << std::endl; + // log << "------------------------ " << std::endl; + // log << "--- Prestrain Output --- " << std::endl; + // log << "Bhat_: " << Bhat_ << std::endl; + // log << "Beff_: " << Beff_ << " (Effective Prestrain)" << std::endl; + // log << "------------------------ " << std::endl; + + // std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl; + if (parameterSet.get<bool>("printMicroOutput ", false)) + std::cout << "Time required to solve for effective quantities: " << effectiveQuantitiesTimer.elapsed() << std::endl; + return ; + } + + + // ----------------------------------------------------------------- + // --- write Data to .Txt-File for Matlab / Optimization-Code + void writeEffectiveQuantitiesToTxt(std::string outputPath) + { + std::cout << "write effective quantities as .txt files to output folder..." << std::endl; + writeMatrixToMatlab(Qeff_, outputPath + "/QMatrix.txt"); + // write effective Prestrain in Matrix for Output + Dune::FieldMatrix<double,1,3> BeffMat; + BeffMat[0] = Beff_; + writeMatrixToMatlab(BeffMat, outputPath + "/BMatrix.txt"); + return; + } + + template<class MatrixFunction> + double energySP(const MatrixFunction& matrixFieldFuncA, + const MatrixFunction& matrixFieldFuncB) + { + double energy = 0.0; + auto mu_ = *correctorComputer_->getMu(); + auto lambda_ = *correctorComputer_->getLambda(); + auto gamma = correctorComputer_->getGamma(); + auto basis = *correctorComputer_->getBasis(); + auto localView = basis.localView(); + + auto localIndicatorFunction = (correctorComputer_->material_)->getLocalIndicatorFunction(); + + auto matrixFieldAGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView()); + auto matrixFieldA = localFunction(matrixFieldAGVF); + auto matrixFieldBGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView()); + auto matrixFieldB = localFunction(matrixFieldBGVF); + + for (const auto& e : elements(basis.gridView())) + { + localView.bind(e); + matrixFieldA.bind(e); + matrixFieldB.bind(e); + localIndicatorFunction.bind(e); + + double elementEnergy = 0.0; + + auto geometry = e.geometry(); + const auto& localFiniteElement = localView.tree().child(0).finiteElement(); + + int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); + const auto& quad = Dune::QuadratureRules<double, dim>::rule(e.type(), orderQR); + for (const auto& quadPoint : quad) + { + const auto& quadPos = quadPoint.position(); + const double integrationElement = geometry.integrationElement(quadPos); + + double energyDensity= scalarProduct((correctorComputer_->material_)->applyElasticityTensor(matrixFieldA(quadPos),localIndicatorFunction(quadPos)),sym(matrixFieldB(quadPos))); + + elementEnergy += energyDensity * quadPoint.weight() * integrationElement; + } + energy += elementEnergy; } + return energy; + } }; // end class diff --git a/dune/microstructure/deprecated_headers/materialDefinitions.hh b/dune/microstructure/deprecated_headers/materialDefinitions.hh index 1a03b8832c93a87d13a680217f7c482772f0ed6e..19468d4551cc67f519ecd111c69a20317a74a144 100644 --- a/dune/microstructure/deprecated_headers/materialDefinitions.hh +++ b/dune/microstructure/deprecated_headers/materialDefinitions.hh @@ -20,11 +20,11 @@ using VectorRT = FieldVector< double, 3>; -// (30.8.22) DEPRECATED CLASS! +// (30.8.22) DEPRECATED CLASS! - ////---------------------------------------------------------------------------------- +////---------------------------------------------------------------------------------- // template<class Domain> // int indicatorFunction_material_new(const Domain& x) // { @@ -33,7 +33,7 @@ using VectorRT = FieldVector< double, 3>; // return 1; //#Phase1 // else if (x[1]<(-0.5+theta) and x[2]>(0.5-theta)) // return 2; //#Phase2 -// else +// else // return 3; //#Phase3 // } // MatrixRT material_new(const MatrixRT& G, const int& phase) @@ -45,7 +45,7 @@ using VectorRT = FieldVector< double, 3>; // // 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 +// else // return 2.0 * mu[2] * sym(G) + lambda[2] * trace(sym(G)) * Id(); //#Phase3 // } // MatrixRT prestrain_material_new(const int& phase) @@ -60,208 +60,208 @@ using VectorRT = FieldVector< double, 3>; // {0.0, 1.0, 0.0}, // {0.0, 0.0, 1.0} // }; -// else +// else // return {{0.0, 0.0, 0.0}, //#Phase3 // {0.0, 0.0, 0.0}, // {0.0, 0.0, 0.0} // }; // } - ////---------------------------------------------------------------------------------- - - - - - - // ---------------------------------------------------------------------------------- - template<class Domain> - int indicatorFunction_material_neukamm(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 material_neukamm(const MatrixRT& G, 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_neukamm(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} - }; - } - // ---------------------------------------------------------------------------------- - - - // ---------------------------------------------------------------------------------- - template<class Domain> - int indicatorFunction_two_phase_material_1(const Domain& x) - { - double theta=0.25; - if(abs(x[0]) > (theta/2.0)) - return 1; //#Phase1 - else - return 0; //#Phase2 - } - MatrixRT two_phase_material_1(const MatrixRT& G, const int& phase) - { - const FieldVector<double,2> mu = {80.0, 160.0}; - const FieldVector<double,2> lambda = {80.0, 160.0}; - if (phase == 1) - return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); - else - return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); - } - MatrixRT prestrain_two_phase_material_1(const int& phase) - { - const FieldVector<double,2> rho = {3.0, 5.0}; - if (phase == 1) - return {{rho[0], 0.0, 0.0}, //#Phase1 - {0.0, rho[0], 0.0}, - {0.0, 0.0, rho[0]} - }; - else - return {{rho[1], 0.0, 0.0}, //#Phase2 - {0.0, rho[1], 0.0}, - {0.0, 0.0, rho[1]} - }; - } - // ---------------------------------------------------------------------------------- - - - // ---------------------------------------------------------------------------------- - template<class Domain> - int indicatorFunction_two_phase_material_2(const Domain& x) - { - double theta=0.25; - if(abs(x[0]) > (theta/2.0)) - return 1; //#Phase1 - else - return 0; //#Phase2 - } - MatrixRT two_phase_material_2(const MatrixRT& G, const int& phase) - { - const FieldVector<double,2> mu = {5.0, 15.0}; - const FieldVector<double,2> lambda = {6.0, 8.0}; - if (phase == 1) - return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); - else - return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); - } - MatrixRT prestrain_two_phase_material_2(const int& phase) - { - const FieldVector<double,2> rho = {3.0, 5.0}; - if (phase == 1) - return {{rho[0], 0.0, 0.0}, //#Phase1 - {0.0, rho[0], 0.0}, - {0.0, 0.0, rho[0]} - }; - else - return {{rho[1], 0.0, 0.0}, //#Phase2 - {0.0, rho[1], 0.0}, - {0.0, 0.0, rho[1]} - }; - } - // ---------------------------------------------------------------------------------- - - - - // ---------------------------------------------------------------------------------- - template<class Domain> - int indicatorFunction_material_2(const Domain& x) - { - double theta=0.25; - if(abs(x[0]) > (theta/2.0)) - return 1; //#Phase1 - else - return 0; //#Phase2 - } - MatrixRT material_2(const MatrixRT& G, const int& phase) - { - const FieldVector<double,2> mu = {80.0, 160.0}; - const FieldVector<double,2> lambda = {80.0, 160.0}; - if (phase == 1) - return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); //#Phase1 - else - return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); //#Phase2 - } - MatrixRT prestrain_material_2(const int& phase) - { - const FieldVector<double,2> rho = {3.0, 5.0}; - if (phase == 1) - return {{rho[0], 0.0, 0.0}, //#Phase1 - {0.0, rho[0], 0.0}, - {0.0, 0.0, rho[0]} - }; - else - return {{rho[1], 0.0, 0.0}, //#Phase2 - {0.0, rho[1], 0.0}, - {0.0, 0.0, rho[1]} - }; - } - // ---------------------------------------------------------------------------------- - - - // ---------------------------------------------------------------------------------- - template<class Domain> - int indicatorFunction_material_homogeneous(const Domain& x) - { - return 0; - } - MatrixRT material_homogeneous(const MatrixRT& G, const int& phase) - { - const FieldVector<double,1> mu = {80.0}; - const FieldVector<double,1> lambda = {80.0}; - return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); - } - MatrixRT prestrain_homogeneous(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 {{1.0, 0.0, 0.0}, //#Phase3 - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0} - }; - } - // ---------------------------------------------------------------------------------- - - - - - - +////---------------------------------------------------------------------------------- + + + + + +// ---------------------------------------------------------------------------------- +template<class Domain> +int indicatorFunction_material_neukamm(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 material_neukamm(const MatrixRT& G, 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_neukamm(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} + }; +} +// ---------------------------------------------------------------------------------- + + +// ---------------------------------------------------------------------------------- +template<class Domain> +int indicatorFunction_two_phase_material_1(const Domain& x) +{ + double theta=0.25; + if(abs(x[0]) > (theta/2.0)) + return 1; //#Phase1 + else + return 0; //#Phase2 +} +MatrixRT two_phase_material_1(const MatrixRT& G, const int& phase) +{ + const FieldVector<double,2> mu = {80.0, 160.0}; + const FieldVector<double,2> lambda = {80.0, 160.0}; + if (phase == 1) + return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); + else + return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); +} +MatrixRT prestrain_two_phase_material_1(const int& phase) +{ + const FieldVector<double,2> rho = {3.0, 5.0}; + if (phase == 1) + return {{rho[0], 0.0, 0.0}, //#Phase1 + {0.0, rho[0], 0.0}, + {0.0, 0.0, rho[0]} + }; + else + return {{rho[1], 0.0, 0.0}, //#Phase2 + {0.0, rho[1], 0.0}, + {0.0, 0.0, rho[1]} + }; +} +// ---------------------------------------------------------------------------------- + + +// ---------------------------------------------------------------------------------- +template<class Domain> +int indicatorFunction_two_phase_material_2(const Domain& x) +{ + double theta=0.25; + if(abs(x[0]) > (theta/2.0)) + return 1; //#Phase1 + else + return 0; //#Phase2 +} +MatrixRT two_phase_material_2(const MatrixRT& G, const int& phase) +{ + const FieldVector<double,2> mu = {5.0, 15.0}; + const FieldVector<double,2> lambda = {6.0, 8.0}; + if (phase == 1) + return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); + else + return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); +} +MatrixRT prestrain_two_phase_material_2(const int& phase) +{ + const FieldVector<double,2> rho = {3.0, 5.0}; + if (phase == 1) + return {{rho[0], 0.0, 0.0}, //#Phase1 + {0.0, rho[0], 0.0}, + {0.0, 0.0, rho[0]} + }; + else + return {{rho[1], 0.0, 0.0}, //#Phase2 + {0.0, rho[1], 0.0}, + {0.0, 0.0, rho[1]} + }; +} +// ---------------------------------------------------------------------------------- + + + +// ---------------------------------------------------------------------------------- +template<class Domain> +int indicatorFunction_material_2(const Domain& x) +{ + double theta=0.25; + if(abs(x[0]) > (theta/2.0)) + return 1; //#Phase1 + else + return 0; //#Phase2 +} +MatrixRT material_2(const MatrixRT& G, const int& phase) +{ + const FieldVector<double,2> mu = {80.0, 160.0}; + const FieldVector<double,2> lambda = {80.0, 160.0}; + if (phase == 1) + return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); //#Phase1 + else + return 2.0 * mu[1] * sym(G) + lambda[1] * trace(sym(G)) * Id(); //#Phase2 +} +MatrixRT prestrain_material_2(const int& phase) +{ + const FieldVector<double,2> rho = {3.0, 5.0}; + if (phase == 1) + return {{rho[0], 0.0, 0.0}, //#Phase1 + {0.0, rho[0], 0.0}, + {0.0, 0.0, rho[0]} + }; + else + return {{rho[1], 0.0, 0.0}, //#Phase2 + {0.0, rho[1], 0.0}, + {0.0, 0.0, rho[1]} + }; +} +// ---------------------------------------------------------------------------------- + + +// ---------------------------------------------------------------------------------- +template<class Domain> +int indicatorFunction_material_homogeneous(const Domain& x) +{ + return 0; +} +MatrixRT material_homogeneous(const MatrixRT& G, const int& phase) +{ + const FieldVector<double,1> mu = {80.0}; + const FieldVector<double,1> lambda = {80.0}; + return 2.0 * mu[0] * sym(G) + lambda[0] * trace(sym(G)) * Id(); +} +MatrixRT prestrain_homogeneous(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 {{1.0, 0.0, 0.0}, //#Phase3 + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0} + }; +} +// ---------------------------------------------------------------------------------- + + + + + + @@ -280,4 +280,4 @@ using VectorRT = FieldVector< double, 3>; -#endif \ No newline at end of file +#endif diff --git a/dune/microstructure/deprecated_headers/prestrain_material_geometry.hh b/dune/microstructure/deprecated_headers/prestrain_material_geometry.hh index 55def935a783ea2ae1fb3db94317ac503ae686b8..cae2f3651b3539c26b5c1088d28e6768b2aa88de 100644 --- a/dune/microstructure/deprecated_headers/prestrain_material_geometry.hh +++ b/dune/microstructure/deprecated_headers/prestrain_material_geometry.hh @@ -18,460 +18,460 @@ using std::cos; -template <int dim> -class IsotropicMaterialImp +template <int dim> +class IsotropicMaterialImp { public: static const int dimWorld = dim; - using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim>>; + using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim> >; using Domain = typename CellGridType::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate; using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>; using Func2Tensor = std::function< MatrixRT(const Domain&) >; - using FuncScalar = std::function< double(const Domain&) >; + using FuncScalar = std::function< double (const Domain&) >; FuncScalar getMu(ParameterTree parameters){ std::string imp = parameters.get<std::string>("material_prestrain_imp", "analytical_Example"); //std::array<std::string,5> imps({"homogen_poisson" "bilayer_poisson" "chess_poisson" "3Dchess_poisson" "vertical_bilayer_poisson"}); - - double phi = M_PI*parameters.get<double>("material_angle", 0.0)/180; //TODO + + double phi = M_PI*parameters.get<double>("material_angle", 0.0)/180; //TODO double theta = parameters.get<double>("theta",1.0/4.0); //TODO alle parameter hier laden? - + double width = parameters.get<double>("width", 1.0); double height = parameters.get<double>("height", 1.0); - if (imp == "homogeneous"){ + if (imp == "homogeneous") { double mu1 = parameters.get<double>("mu1", 10); auto muTerm = [mu1] (const Domain& z) {return mu1;}; - + return muTerm; } - else if (imp == "material_neukamm"){ -// std::array<double,2> mu = parameters.get<std::array<double,2>>("mu", {1.0,3.0}); - // std::array<double,3> mu = parameters.get<std::array<double,3>>("mu", {1.0,3.0,2.0}); - std::array<double,3> mu = parameters.get<std::array<double,3>>("mu", {80.0, 80.0, 60.0}); + else if (imp == "material_neukamm") { + // std::array<double,2> mu = parameters.get<std::array<double,2>>("mu", {1.0,3.0}); + // std::array<double,3> mu = parameters.get<std::array<double,3>>("mu", {1.0,3.0,2.0}); + std::array<double,3> mu = parameters.get<std::array<double,3> >("mu", {80.0, 80.0, 60.0}); // Python::Module module = Python::import(parameters.get<std::string>("material_neukamm")); Python::Module module = Python::import("material_neukamm"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto muTerm = [mu,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return mu[0]; - else if (indicatorFunction(z) == 2) - return mu[1]; - else - return mu[2]; - }; + auto muTerm = [mu,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return mu[0]; + else if (indicatorFunction(z) == 2) + return mu[1]; + else + return mu[2]; + }; return muTerm; } - else if (imp == "two_phase_material_1"){ - std::array<double,2> mu = parameters.get<std::array<double,2>>("mu", {1.0,3.0}); + else if (imp == "two_phase_material_1") { + std::array<double,2> mu = parameters.get<std::array<double,2> >("mu", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_1"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto muTerm = [mu,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return mu[0]; - else - return mu[1]; - }; + auto muTerm = [mu,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return mu[0]; + else + return mu[1]; + }; return muTerm; } - else if (imp == "two_phase_material_2"){ - std::array<double,2> mu = parameters.get<std::array<double,2>>("mu", {1.0,3.0}); + else if (imp == "two_phase_material_2") { + std::array<double,2> mu = parameters.get<std::array<double,2> >("mu", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_2"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto muTerm = [mu,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return mu[0]; - else - return mu[1]; - }; + auto muTerm = [mu,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return mu[0]; + else + return mu[1]; + }; return muTerm; } - else if (imp == "two_phase_material_3"){ - std::array<double,2> mu = parameters.get<std::array<double,2>>("mu", {1.0,3.0}); + else if (imp == "two_phase_material_3") { + std::array<double,2> mu = parameters.get<std::array<double,2> >("mu", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_3"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto muTerm = [mu,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return mu[0]; - else - return mu[1]; - }; + auto muTerm = [mu,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return mu[0]; + else + return mu[1]; + }; return muTerm; } else if (imp == "isotropic_bilayer") - { - double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); - double mu2 = beta*mu1; - - auto muTerm = [mu1, mu2, theta] (const Domain& z) { - if (z[2]>0) - return mu1; - else - return mu2; - }; - - return muTerm; - } - else if (imp == "analytical_Example"){ + { + double mu1 = parameters.get<double>("mu1",10.0); + double beta = parameters.get<double>("beta",2.0); + double mu2 = beta*mu1; + + auto muTerm = [mu1, mu2, theta] (const Domain& z) { + if (z[2]>0) + return mu1; + else + return mu2; + }; + + return muTerm; + } + else if (imp == "analytical_Example") { double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; - + auto muTerm = [mu1, mu2, theta] (const Domain& z) { - // std::cout << "Analytical-MU is used" << std::endl; - if (abs(z[0]) >= (theta/2.0)) + // std::cout << "Analytical-MU is used" << std::endl; + if (abs(z[0]) >= (theta/2.0)) return mu1; - else + else return mu2; }; - + return muTerm; } - else if (imp == "parametrized_Laminate"){ + else if (imp == "parametrized_Laminate") { double mu1 = parameters.get<double>("mu1",1.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; - + auto muTerm = [mu1, mu2, theta] (const Domain& z) { - // std::cout << "Analytical-MU is used" << std::endl; - // if (abs(z[0]) >= (theta/2.0)) - if (abs(z[0]) > (theta/2.0)) + // std::cout << "Analytical-MU is used" << std::endl; + // if (abs(z[0]) >= (theta/2.0)) + if (abs(z[0]) > (theta/2.0)) return mu1; - else + else return mu2; }; - + return muTerm; } - else if (imp == "circle_fiber"){ + else if (imp == "circle_fiber") { double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; - auto muTerm = [mu1,mu2,width] (const Domain& z) { - if (z[0] < 0 && sqrt(pow(z[1],2) + pow(z[2],2) ) < width/4.0 || 0 < z[0] && sqrt(pow(z[1],2) + pow(z[2],2) ) > width/4.0) - return mu1; - else - return mu2; - }; - + auto muTerm = [mu1,mu2,width] (const Domain& z) { + if (z[0] < 0 && sqrt(pow(z[1],2) + pow(z[2],2) ) < width/4.0 || 0 < z[0] && sqrt(pow(z[1],2) + pow(z[2],2) ) > width/4.0) + return mu1; + else + return mu2; + }; + return muTerm; } - else if (imp == "square_fiber"){ + else if (imp == "square_fiber") { double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; - auto muTerm = [mu1,mu2,width] (const Domain& z) { - if (z[0] < 0 && std::max(abs(z[1]), abs(z[2])) < width/4.0 || 0 < z[0] && std::max(abs(z[1]), abs(z[2])) > width/4.0) - return mu1; - else - return mu2; - }; - + auto muTerm = [mu1,mu2,width] (const Domain& z) { + if (z[0] < 0 && std::max(abs(z[1]), abs(z[2])) < width/4.0 || 0 < z[0] && std::max(abs(z[1]), abs(z[2])) > width/4.0) + return mu1; + else + return mu2; + }; + return muTerm; } else if (imp == "matrix_material_circles") // Matrix material with prestrained Fiber inclusions (circular cross-section) - { - double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); - double mu2 = beta*mu1; - - int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - auto muTerm = [mu1,mu2,theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - // TEST - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - // std::cout << "matrixMaterial-MU is used" << std::endl; - - double output; - - // determine if point is in upper/lower Layer - if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - // - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = mu2; - // return mu2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = mu1; - // return mu1; - } - else {} - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = mu2; - // return mu2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = mu1; - // return mu1; - } - else{} - } - - } - return output; - }; - return muTerm; - } + { + double mu1 = parameters.get<double>("mu1",10.0); + double beta = parameters.get<double>("beta",2.0); + double mu2 = beta*mu1; + + int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + auto muTerm = [mu1,mu2,theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + // TEST + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + // std::cout << "matrixMaterial-MU is used" << std::endl; + + double output; + + // determine if point is in upper/lower Layer + if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + // + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = mu2; + // return mu2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = mu1; + // return mu1; + } + else {} + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = mu2; + // return mu2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = mu1; + // return mu1; + } + else{} + } + + } + return output; + }; + return muTerm; + } else if (imp == "matrix_material_squares") // Matrix material with prestrained Fiber inclusions (square-shaped cross-section) - { - double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); - double mu2 = beta*mu1; - - int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - auto muTerm = [mu1,mu2,theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - // TEST - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - // std::cout << "matrixMaterial-MU is used" << std::endl; - double output; - - // determine if point is in upper/lower Layer - if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - // - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = mu2; - // return mu2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = mu1; - // return mu1; - } - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = mu2; - // return mu2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = mu1; - // return mu1; - } - } - } - return output; - }; - return muTerm; - } - else if (imp == "bilayer"){ + { double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); + double mu2 = beta*mu1; + + int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + auto muTerm = [mu1,mu2,theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + // TEST + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + // std::cout << "matrixMaterial-MU is used" << std::endl; + double output; + + // determine if point is in upper/lower Layer + if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + // + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = mu2; + // return mu2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = mu1; + // return mu1; + } + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = mu2; + // return mu2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = mu1; + // return mu1; + } + } + } + return output; + }; + return muTerm; + } + else if (imp == "bilayer") { + double mu1 = parameters.get<double>("mu1",10.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; - + auto muTerm = [mu1, mu2, phi] (const Domain& z) { - if (isInRotatedPlane(phi, z[dim-2], z[dim-1])) - return mu1; - else - return mu2; - }; - + if (isInRotatedPlane(phi, z[dim-2], z[dim-1])) + return mu1; + else + return mu2; + }; + return muTerm; } - - else if (imp == "helix_poisson"){ // interessant! + + else if (imp == "helix_poisson") { // interessant! double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; double r = parameters.get<double>("radius"); double r2 = parameters.get<double>("radius_helix"); auto muTerm = [mu1, mu2, r, r2] (const Domain& z) { - std::array<double,2> h = {r*cos(2*M_PI*z[0]), r*sin(2*M_PI*z[0])}; - if ( sqrt(pow(z[1]-h[0],2)+pow(z[2]-h[1],2)) < r2 ) // distance to the helix? - return mu1; - else - return mu2; - }; - + std::array<double,2> h = {r*cos(2*M_PI*z[0]), r*sin(2*M_PI*z[0])}; + if ( sqrt(pow(z[1]-h[0],2)+pow(z[2]-h[1],2)) < r2 ) // distance to the helix? + return mu1; + else + return mu2; + }; + return muTerm; } - else if (imp == "chess_poisson"){ + else if (imp == "chess_poisson") { double mu1 = parameters.get<double>("mu1",10.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double mu2 = beta*mu1; auto muTerm = [mu1, mu2, phi] (const Domain& z) { - if ( (isInRotatedPlane(phi, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + M_PI/2 , z[dim-2], z[dim-1])) or - (isInRotatedPlane(phi + M_PI, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + 3*M_PI/2, z[dim-2], z[dim-1])) ) - return mu1; - else - return mu2; - }; - + if ( (isInRotatedPlane(phi, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + M_PI/2 , z[dim-2], z[dim-1])) or + (isInRotatedPlane(phi + M_PI, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + 3*M_PI/2, z[dim-2], z[dim-1])) ) + return mu1; + else + return mu2; + }; + return muTerm; } - // else if (imp == "3Dchess_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //Faser - // double nu1 = parameters.get<double>("nu1", 0.3); - // double mu1 = lameMu(E1, nu1); - // - // double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß - // double nu2 = parameters.get<double>("nu2", 0.5); - // double mu2 = lameMu(E2, nu2); - // - // auto muTerm = [mu1, mu2, phi] (const Domain& z) { - // if (z[0]<0.5) - // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or - // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) - // return mu1; - // else - // return mu2; - // else - // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or - // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) - // return mu2; - // else - // return mu1; - // }; - // - // return muTerm; - // } - // else if (imp == "vertical_bilayer_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double mu1 = lameMu(E1, nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double mu2 = lameMu(E2, nu2); - // - // auto muTerm = [mu1, mu2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi+M_PI/2.0, z[dim-2], z[dim-1]) )//x3 - // return mu1; - // else - // return mu2; }; - // - // return muTerm; - // } - // - // else if (imp == "microstructured_bilayer_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double mu1 = lameMu(E1, nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double mu2 = lameMu(E2, nu2); - // - // auto muTerm = [mu1, mu2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi, z[0]-0.5, z[1]) ) //TODO understand this - // return mu1; - // else - // return mu2; }; - // - // return muTerm; - // } - // - // else { //(imp == "bilayer_poisson") - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double mu1 = lameMu(E1, nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double mu2 = lameMu(E2, nu2); - // - // auto muTerm = [mu1, mu2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) //x2 - // return mu1; - // else - // return mu2; }; - // - // return muTerm; - // } + // else if (imp == "3Dchess_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //Faser + // double nu1 = parameters.get<double>("nu1", 0.3); + // double mu1 = lameMu(E1, nu1); + // + // double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß + // double nu2 = parameters.get<double>("nu2", 0.5); + // double mu2 = lameMu(E2, nu2); + // + // auto muTerm = [mu1, mu2, phi] (const Domain& z) { + // if (z[0]<0.5) + // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or + // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) + // return mu1; + // else + // return mu2; + // else + // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or + // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) + // return mu2; + // else + // return mu1; + // }; + // + // return muTerm; + // } + // else if (imp == "vertical_bilayer_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double mu1 = lameMu(E1, nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double mu2 = lameMu(E2, nu2); + // + // auto muTerm = [mu1, mu2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi+M_PI/2.0, z[dim-2], z[dim-1]) )//x3 + // return mu1; + // else + // return mu2; }; + // + // return muTerm; + // } + // + // else if (imp == "microstructured_bilayer_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double mu1 = lameMu(E1, nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double mu2 = lameMu(E2, nu2); + // + // auto muTerm = [mu1, mu2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi, z[0]-0.5, z[1]) ) //TODO understand this + // return mu1; + // else + // return mu2; }; + // + // return muTerm; + // } + // + // else { //(imp == "bilayer_poisson") + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double mu1 = lameMu(E1, nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double mu2 = lameMu(E2, nu2); + // + // auto muTerm = [mu1, mu2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) //x2 + // return mu1; + // else + // return mu2; }; + // + // return muTerm; + // } } FuncScalar getLambda(ParameterTree parameters) @@ -483,441 +483,442 @@ public: //std::string imp = imps[i_imp]; double phi = M_PI*parameters.get<double>("material_angle", 0.0)/180; double theta = parameters.get<double>("theta",1.0/4.0); //TODO alle parameter hier laden? - + double width = parameters.get<double>("width", 1.0); double height = parameters.get<double>("height", 1.0); - if (imp == "homogeneous"){ + if (imp == "homogeneous") { double lambda1 = parameters.get<double>("lambda1",0.0); auto lambdaTerm = [lambda1] (const Domain& z) {return lambda1;}; - + return lambdaTerm; } - if (imp == "material_neukamm"){ -// std::array<double,2> lambda = parameters.get<std::array<double,2>>("lambda", {1.0,3.0}); - // std::array<double,3> lambda = parameters.get<std::array<double,3>>("lambda", {1.0,3.0,2.0}); - std::array<double,3> lambda = parameters.get<std::array<double,3>>("lambda", {80.0, 80.0, 25.0}); - + if (imp == "material_neukamm") { + // std::array<double,2> lambda = parameters.get<std::array<double,2>>("lambda", {1.0,3.0}); + // std::array<double,3> lambda = parameters.get<std::array<double,3>>("lambda", {1.0,3.0,2.0}); + std::array<double,3> lambda = parameters.get<std::array<double,3> >("lambda", {80.0, 80.0, 25.0}); + Python::Module module = Python::import("material_neukamm"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return lambda[0]; - else if (indicatorFunction(z) == 2) - return lambda[1]; - else - return lambda[2]; - }; + auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return lambda[0]; + else if (indicatorFunction(z) == 2) + return lambda[1]; + else + return lambda[2]; + }; return lambdaTerm; } - if (imp == "two_phase_material_1"){ - std::array<double,2> lambda = parameters.get<std::array<double,2>>("lambda", {1.0,3.0}); + if (imp == "two_phase_material_1") { + std::array<double,2> lambda = parameters.get<std::array<double,2> >("lambda", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_1"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return lambda[0]; - else - return lambda[1]; - }; + auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return lambda[0]; + else + return lambda[1]; + }; return lambdaTerm; } - if (imp == "two_phase_material_2"){ - std::array<double,2> lambda = parameters.get<std::array<double,2>>("lambda", {1.0,3.0}); + if (imp == "two_phase_material_2") { + std::array<double,2> lambda = parameters.get<std::array<double,2> >("lambda", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_2"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return lambda[0]; - else - return lambda[1]; - }; + auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return lambda[0]; + else + return lambda[1]; + }; return lambdaTerm; } - if (imp == "two_phase_material_3"){ - std::array<double,2> lambda = parameters.get<std::array<double,2>>("lambda", {1.0,3.0}); + if (imp == "two_phase_material_3") { + std::array<double,2> lambda = parameters.get<std::array<double,2> >("lambda", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_3"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(z) == 1) - return lambda[0]; - else - return lambda[1]; - }; + auto lambdaTerm = [lambda,indicatorFunction] (const Domain& z) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(z) == 1) + return lambda[0]; + else + return lambda[1]; + }; return lambdaTerm; } else if (imp == "isotropic_bilayer") - { - double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); - double lambda2 = beta*lambda1; - - auto lambdaTerm = [lambda1,lambda2, theta] (const Domain& z) { - if (z[2]>0) - return lambda1; - else - return lambda2; - }; - return lambdaTerm; - } - - else if (imp == "analytical_Example"){ + { double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double lambda2 = beta*lambda1; - + auto lambdaTerm = [lambda1,lambda2, theta] (const Domain& z) { - - // std::cout << "Analytical-LAMBDA is used" << std::endl; //TEST - if (abs(z[0]) >= (theta/2.0)) - return lambda1; - else - return lambda2; - }; + if (z[2]>0) + return lambda1; + else + return lambda2; + }; return lambdaTerm; } - else if (imp == "parametrized_Laminate"){ + + else if (imp == "analytical_Example") { double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double lambda2 = beta*lambda1; - + auto lambdaTerm = [lambda1,lambda2, theta] (const Domain& z) { - - // std::cout << "Analytical-LAMBDA is used" << std::endl; //TEST - // std::cout << "Lambda1:" << lambda1 << std::endl; - // if (abs(z[0]) > (theta/2.0)) - if (abs(z[0]) > (theta/2.0)) - return lambda1; - else - return lambda2; - }; + + // std::cout << "Analytical-LAMBDA is used" << std::endl; //TEST + if (abs(z[0]) >= (theta/2.0)) + return lambda1; + else + return lambda2; + }; return lambdaTerm; } - else if (imp == "circle_fiber"){ + else if (imp == "parametrized_Laminate") { double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); + double lambda2 = beta*lambda1; + + auto lambdaTerm = [lambda1,lambda2, theta] (const Domain& z) { + + // std::cout << "Analytical-LAMBDA is used" << std::endl; //TEST + // std::cout << "Lambda1:" << lambda1 << std::endl; + // if (abs(z[0]) > (theta/2.0)) + if (abs(z[0]) > (theta/2.0)) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; + } + else if (imp == "circle_fiber") { + double lambda1 = parameters.get<double>("lambda1",0.0); + double beta = parameters.get<double>("beta",2.0); double lambda2 = beta*lambda1; auto lambdaTerm = [lambda1,lambda2,width] (const Domain& z) // Prestrain inducing twist (bisher nur extension) - { - if (z[0] < 0 && sqrt(pow(z[1],2) + pow(z[2],2) ) < width/4.0 || 0 < z[0] && sqrt(pow(z[1],2) + pow(z[2],2) ) > width/4.0) - return lambda1; - else - return lambda2; - }; - + { + if (z[0] < 0 && sqrt(pow(z[1],2) + pow(z[2],2) ) < width/4.0 || 0 < z[0] && sqrt(pow(z[1],2) + pow(z[2],2) ) > width/4.0) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; } - else if (imp == "square_fiber"){ + else if (imp == "square_fiber") { double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); + double beta = parameters.get<double>("beta",2.0); double lambda2 = beta*lambda1; auto lambdaTerm = [lambda1,lambda2,width] (const Domain& z) // Prestrain inducing twist (bisher nur extension) - { - if (z[0] < 0 && std::max(abs(z[1]), abs(z[2])) < width/4.0 || 0 < z[0] && std::max(abs(z[1]), abs(z[2])) > width/4.0) - return lambda1; - else - return lambda2; - }; - + { + if (z[0] < 0 && std::max(abs(z[1]), abs(z[2])) < width/4.0 || 0 < z[0] && std::max(abs(z[1]), abs(z[2])) > width/4.0) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; } else if (imp == "matrix_material_circles") // Matrix material with prestrained Fiber inclusions (circular cross-section) - { - double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); - double lambda2 = beta*lambda1; - - int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - auto lambdaTerm = [lambda1,lambda2, theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - // TEST - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - // std::cout << "matrixMaterial-MU is used" << std::endl; - double output; - - // determine if point is in upper/lower Layer - if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - // - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = lambda2; - // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = lambda1; - // return lambda1; - } - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = lambda2; - // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = lambda1; - // return lambda1; - } - } - - } - return output; - }; - return lambdaTerm; - } + { + double lambda1 = parameters.get<double>("lambda1",0.0); + double beta = parameters.get<double>("beta",2.0); + double lambda2 = beta*lambda1; + + int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + auto lambdaTerm = [lambda1,lambda2, theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + // TEST + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + // std::cout << "matrixMaterial-MU is used" << std::endl; + double output; + + // determine if point is in upper/lower Layer + if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + // + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = lambda2; + // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = lambda1; + // return lambda1; + } + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = lambda2; + // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = lambda1; + // return lambda1; + } + } + + } + return output; + }; + return lambdaTerm; + } else if (imp == "matrix_material_squares") // Matrix material with prestrained Fiber inclusions (square-shaped cross-section) - { - double lambda1 = parameters.get<double>("lambda1",0.0); - double beta = parameters.get<double>("beta",2.0); - double lambda2 = beta*lambda1; - - int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - auto lambdaTerm = [lambda1,lambda2, theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - // TEST - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - // std::cout << "matrixMaterial-MU is used" << std::endl; - double output; - - // determine if point is in upper/lower Layer - if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - // - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = lambda2; - // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = lambda1; - // return lambda1; - } - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) - { - // std::cout << " i : " << i << std::endl; - // printvector(std::cout, s, "s" , "--"); - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; - // printvector(std::cout, Fcenter, "Fcenter" , "--"); - - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = lambda2; - // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? - else - output = lambda1; - // return lambda1; - } - } - } - return output; - }; - return lambdaTerm; - } - else if (imp == "bilayer_lame"){ + { + double lambda1 = parameters.get<double>("lambda1",0.0); + double beta = parameters.get<double>("beta",2.0); + double lambda2 = beta*lambda1; + + int nF = parameters.get<int>("nF", 2); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + auto lambdaTerm = [lambda1,lambda2, theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + // TEST + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + // std::cout << "matrixMaterial-MU is used" << std::endl; + double output; + + // determine if point is in upper/lower Layer + if ( 0 <= s[2] && s[2] <= 1.0/2.0) // upper Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) // have to evenly space fibers... + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + // + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = lambda2; + // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = lambda1; + // return lambda1; + } + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/double(nF))*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/double(nF))*(i+1)) + { + // std::cout << " i : " << i << std::endl; + // printvector(std::cout, s, "s" , "--"); + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0 }; + // printvector(std::cout, Fcenter, "Fcenter" , "--"); + + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = lambda2; + // return lambda2; //richtig so? Fiber hat tendenziell größeres mu? + else + output = lambda1; + // return lambda1; + } + } + } + return output; + }; + return lambdaTerm; + } + else if (imp == "bilayer_lame") { double lambda1 = parameters.get<double>("mu1",384.615); - double lambda2 = parameters.get<double>("mu2",384.615); - + double lambda2 = parameters.get<double>("mu2",384.615); + auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) - return lambda1; - else - return lambda2; }; - + if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; } - else if (imp == "helix_poisson"){ + else if (imp == "helix_poisson") { double E1 = parameters.get<double>("E1", 17e6); //Faser double nu1 = parameters.get<double>("nu1", 0.3); double lambda1 = lameLambda(E1,nu1); double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß - double nu2 = parameters.get<double>("nu2", 0.5); + double nu2 = parameters.get<double>("nu2", 0.5); double lambda2 = lameLambda(E2, nu2); double r = parameters.get<double>("radius"); double r2 = parameters.get<double>("radius_helix"); auto lambdaTerm = [lambda1, lambda2, r, r2] (const Domain& z) { - std::array<double,2> h = {r*cos(2*M_PI*z[0]), r*sin(2*M_PI*z[0])}; - MatrixRT ret(0.0); - if ( sqrt(pow(z[1]-h[0],2)+pow(z[2]-h[1],2)) < r2 ) - return lambda1; - else - return lambda2; - }; - + std::array<double,2> h = {r*cos(2*M_PI*z[0]), r*sin(2*M_PI*z[0])}; + MatrixRT ret(0.0); + if ( sqrt(pow(z[1]-h[0],2)+pow(z[2]-h[1],2)) < r2 ) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; } - else if (imp == "chess_poisson"){ + else if (imp == "chess_poisson") { double E1 = parameters.get<double>("E1", 17e6); //Faser double nu1 = parameters.get<double>("nu1", 0.3); double lambda1 = lameLambda(E1,nu1); double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß - double nu2 = parameters.get<double>("nu2", 0.5); + double nu2 = parameters.get<double>("nu2", 0.5); double lambda2 = lameLambda(E2, nu2); auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - if ( (isInRotatedPlane(phi, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + M_PI/2 , z[dim-2], z[dim-1])) or - (isInRotatedPlane(phi + M_PI, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + 3*M_PI/2, z[dim-2], z[dim-1])) ) - return lambda1; - else - return lambda2; - }; - + if ( (isInRotatedPlane(phi, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + M_PI/2 , z[dim-2], z[dim-1])) or + (isInRotatedPlane(phi + M_PI, z[dim-2], z[dim-1]) and isInRotatedPlane(phi + 3*M_PI/2, z[dim-2], z[dim-1])) ) + return lambda1; + else + return lambda2; + }; + return lambdaTerm; } - // else if (imp == "3Dchess_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //Faser - // double nu1 = parameters.get<double>("nu1", 0.3); - // double lambda1 = lameLambda(E1,nu1); - // - // double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß - // double nu2 = parameters.get<double>("nu2", 0.5); - // double lambda2 = lameLambda(E2, nu2); - // - // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - // if (z[0]<0.5) - // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or - // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) - // return lambda1; - // else - // return lambda2; - // else - // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or - // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) - // return lambda2; - // else - // return lambda1; - // }; - // - // return lambdaTerm; - // } - // - // else if (imp == "vertical_bilayer_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double lambda1 = lameLambda(E1,nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double lambda2 = lameLambda(E2, nu2); - // - // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi+M_PI/2.0, z[dim-2], z[dim-1]) ) - // return lambda1; - // else - // return lambda2; }; - // - // return lambdaTerm; - // } - // - // else if (imp == "microstructured_bilayer_poisson"){ - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double lambda1 = lameLambda(E1,nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double lambda2 = lameLambda(E2, nu2); - // - // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi, z[0]-0.5, z[1]) ) - // return lambda1; - // else - // return lambda2; }; - // - // return lambdaTerm; - // } - // - // else { //(imp == "bilayer_poisson") - // double E1 = parameters.get<double>("E1", 17e6); //material1 - // double nu1 = parameters.get<double>("nu1", 0.3); - // double lambda1 = lameLambda(E1, nu1); - // double E2 = parameters.get<double>("E2", 17e6); //material2 - // double nu2 = parameters.get<double>("nu2", 0.5); - // double lambda2 = lameLambda(E2, nu2); - // - // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { - // if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) - // return lambda1; - // else - // return lambda2; }; - // - // return lambdaTerm; - // } + // else if (imp == "3Dchess_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //Faser + // double nu1 = parameters.get<double>("nu1", 0.3); + // double lambda1 = lameLambda(E1,nu1); + // + // double E2 = parameters.get<double>("E2", 17e6); //Polymer, weicher, Querkontraktion groß + // double nu2 = parameters.get<double>("nu2", 0.5); + // double lambda2 = lameLambda(E2, nu2); + // + // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { + // if (z[0]<0.5) + // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or + // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) + // return lambda1; + // else + // return lambda2; + // else + // if ( (isInRotatedPlane(phi, z[1], z[2]) and isInRotatedPlane(phi + M_PI/2 , z[1], z[2])) or + // (isInRotatedPlane(phi + M_PI, z[1], z[2]) and isInRotatedPlane(phi + 3*M_PI/2, z[1], z[2])) ) + // return lambda2; + // else + // return lambda1; + // }; + // + // return lambdaTerm; + // } + // + // else if (imp == "vertical_bilayer_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double lambda1 = lameLambda(E1,nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double lambda2 = lameLambda(E2, nu2); + // + // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi+M_PI/2.0, z[dim-2], z[dim-1]) ) + // return lambda1; + // else + // return lambda2; }; + // + // return lambdaTerm; + // } + // + // else if (imp == "microstructured_bilayer_poisson"){ + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double lambda1 = lameLambda(E1,nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double lambda2 = lameLambda(E2, nu2); + // + // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi, z[0]-0.5, z[1]) ) + // return lambda1; + // else + // return lambda2; }; + // + // return lambdaTerm; + // } + // + // else { //(imp == "bilayer_poisson") + // double E1 = parameters.get<double>("E1", 17e6); //material1 + // double nu1 = parameters.get<double>("nu1", 0.3); + // double lambda1 = lameLambda(E1, nu1); + // double E2 = parameters.get<double>("E2", 17e6); //material2 + // double nu2 = parameters.get<double>("nu2", 0.5); + // double lambda2 = lameLambda(E2, nu2); + // + // auto lambdaTerm = [lambda1, lambda2, phi] (const Domain& z) { + // if ( isInRotatedPlane(phi, z[dim-2], z[dim-1]) ) + // return lambda1; + // else + // return lambda2; }; + // + // return lambdaTerm; + // } } @@ -931,17 +932,17 @@ public: -// TODO add log here? +// TODO add log here? template <int dim> -class PrestrainImp +class PrestrainImp { public: // static const int dim = 3; static const int dimWorld = 3; - using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim>>; + using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim> >; // using GridView = CellGridType::LeafGridView; using Domain = typename CellGridType::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate; // using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate; @@ -952,335 +953,335 @@ public: using FuncMatrix = std::function< MatrixRT(const Domain&) >; using FuncVector = std::function< VectorRT(const Domain&) >; protected: - // double p1, p2, theta; - // double width; //Cell geometry + // double p1, p2, theta; + // double width; //Cell geometry public: - + // Func2Tensor getPrestrain(std::string imp) Func2Tensor getPrestrain(ParameterTree parameters) { - + std::string imp = parameters.get<std::string>("material_prestrain_imp", "analytical_Example"); - + double width = parameters.get<double>("width", 1.0); double height = parameters.get<double>("height", 1.0); - - double theta = parameters.get<double>("theta",1.0/4.0); + + double theta = parameters.get<double>("theta",1.0/4.0); double p1 = parameters.get<double>("rho1", 1.0); double alpha = parameters.get<double>("alpha", 2.0); double p2 = alpha*p1; - - - if (imp == "homogeneous"){ + + + if (imp == "homogeneous") { Func2Tensor B = [p1] (const Domain& x) // ISOTROPIC PRESSURE - { - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - }; + { + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + }; std::cout <<" Prestrain Type: homogeneous" << std::endl; return B; } - else if (imp == "two_phase_material_1"){ - std::array<double,2> rho = parameters.get<std::array<double,2>>("rho", {1.0,3.0}); + else if (imp == "two_phase_material_1") { + std::array<double,2> rho = parameters.get<std::array<double,2> >("rho", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_1"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - - Func2Tensor B = [rho,indicatorFunction] (const Domain& x) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(x) == 1) - return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; - else - return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; - }; + + Func2Tensor B = [rho,indicatorFunction] (const Domain& x) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(x) == 1) + return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; + else + return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; + }; std::cout <<" Prestrain Type: two_phase_material_1" << std::endl; return B; } - else if (imp == "material_neukamm"){ -// std::array<double,2> rho = parameters.get<std::array<double,2>>("rho", {1.0,3.0}); + else if (imp == "material_neukamm") { + // std::array<double,2> rho = parameters.get<std::array<double,2>>("rho", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("material_neukamm"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - + auto B1 = Python::make_function<MatrixRT>(module.get("b1")); auto B2 = Python::make_function<MatrixRT>(module.get("b2")); auto B3 = Python::make_function<MatrixRT>(module.get("b3")); - -// Func2Tensor B = [rho,indicatorFunction] (const Domain& x) - Func2Tensor B = [indicatorFunction,B1,B2,B3] (const Domain& x) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(x) == 1) - { -// return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; -// printmatrix(std::cout, B1(x), "Matrix B1(x)", "--"); - return B1(x); - } - else if (indicatorFunction(x) == 2) -// return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; - return B2(x); - else - return B3(x); - }; + + // Func2Tensor B = [rho,indicatorFunction] (const Domain& x) + Func2Tensor B = [indicatorFunction,B1,B2,B3] (const Domain& x) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(x) == 1) + { + // return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; + // printmatrix(std::cout, B1(x), "Matrix B1(x)", "--"); + return B1(x); + } + else if (indicatorFunction(x) == 2) + // return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; + return B2(x); + else + return B3(x); + }; std::cout <<" Prestrain Type: material_neukamm" << std::endl; return B; } - else if (imp == "two_phase_material_2"){ - std::array<double,2> rho = parameters.get<std::array<double,2>>("rho", {1.0,3.0}); + else if (imp == "two_phase_material_2") { + std::array<double,2> rho = parameters.get<std::array<double,2> >("rho", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_2"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - - Func2Tensor B = [rho,indicatorFunction] (const Domain& x) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(x) == 1) - return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; - else - return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; - }; + + Func2Tensor B = [rho,indicatorFunction] (const Domain& x) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(x) == 1) + return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; + else + return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; + }; std::cout <<" Prestrain Type: two_phase_material_2" << std::endl; return B; } - else if (imp == "two_phase_material_3"){ - std::array<double,2> rho = parameters.get<std::array<double,2>>("rho", {1.0,3.0}); + else if (imp == "two_phase_material_3") { + std::array<double,2> rho = parameters.get<std::array<double,2> >("rho", {1.0,3.0}); // Python::Module module = Python::import(parameters.get<std::string>("two_phase_material_1")); Python::Module module = Python::import("two_phase_material_3"); auto indicatorFunction = Python::make_function<double>(module.get("f")); - - Func2Tensor B = [rho,indicatorFunction] (const Domain& x) - { - // std::cout << "Test:" << indicatorFunction(z) << std::endl; - if (indicatorFunction(x) == 1) - return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; - else - return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; - }; + + Func2Tensor B = [rho,indicatorFunction] (const Domain& x) + { + // std::cout << "Test:" << indicatorFunction(z) << std::endl; + if (indicatorFunction(x) == 1) + return MatrixRT{{rho[0], 0.0 , 0.0}, {0.0, rho[0], 0.0}, {0.0, 0.0, rho[0]}}; + else + return MatrixRT{{rho[1], 0.0 , 0.0}, {0.0, rho[1], 0.0}, {0.0, 0.0, rho[1]}}; + }; std::cout <<" Prestrain Type: two_phase_material_3" << std::endl; return B; } else if (imp == "isotropic_bilayer") - { - Func2Tensor B = [p1,p2,theta] (const Domain& x) // ISOTROPIC PRESSURE - { - if (x[2] > 0) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else if (x[2] < 0) - return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - - }; - std::cout <<" Prestrain Type: isotropic_bilayer " << std::endl; - return B; - } - + { + Func2Tensor B = [p1,p2,theta] (const Domain& x) // ISOTROPIC PRESSURE + { + if (x[2] > 0) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else if (x[2] < 0) + return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + + }; + std::cout <<" Prestrain Type: isotropic_bilayer " << std::endl; + return B; + } + else if (imp == "analytical_Example") - { - Func2Tensor B = [p1,theta] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE - { - // if (abs(x[0]) < (theta/2) && x[2] < 0 ) //does not make a difference - if (abs(x[0]) < (theta/2) && x[2] < 0 && x[2] > -(1.0/2.0) ) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; - std::cout <<" Prestrain Type: analytical_Example "<< std::endl; - return B; - } + { + Func2Tensor B = [p1,theta] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE + { + // if (abs(x[0]) < (theta/2) && x[2] < 0 ) //does not make a difference + if (abs(x[0]) < (theta/2) && x[2] < 0 && x[2] > -(1.0/2.0) ) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; + std::cout <<" Prestrain Type: analytical_Example "<< std::endl; + return B; + } else if (imp == "parametrized_Laminate") - { - Func2Tensor B = [p1,p2,theta] (const Domain& x) - { - if (abs(x[0]) < (theta/2) && x[2] < 0 ) - return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - else if (abs(x[0]) > (theta/2) && x[2] > 0 ) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; - std::cout <<"Prestrain Type: parametrized_Laminate"<< std::endl; - return B; - } - else if (imp == "circle_fiber"){ - - Func2Tensor B = [p1,theta,width] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE - { - if (x[0] < 0 && sqrt(pow(x[1],2) + pow(x[2],2) ) < width/4.0 || 0 < x[0] && sqrt(pow(x[1],2) + pow(x[2],2) ) > width/4.0) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; + { + Func2Tensor B = [p1,p2,theta] (const Domain& x) + { + if (abs(x[0]) < (theta/2) && x[2] < 0 ) + return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + else if (abs(x[0]) > (theta/2) && x[2] > 0 ) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; + std::cout <<"Prestrain Type: parametrized_Laminate"<< std::endl; + return B; + } + else if (imp == "circle_fiber") { + + Func2Tensor B = [p1,theta,width] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE + { + if (x[0] < 0 && sqrt(pow(x[1],2) + pow(x[2],2) ) < width/4.0 || 0 < x[0] && sqrt(pow(x[1],2) + pow(x[2],2) ) > width/4.0) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; std::cout <<" Prestrain Type: circle_fiber"<< std::endl; return B; } - else if (imp == "square_fiber"){ - - Func2Tensor B = [p1,theta,width] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE - { - if (x[0] < 0 && std::max(abs(x[1]), abs(x[2])) < width/4.0 || 0 < x[0] && std::max(abs(x[1]), abs(x[2])) > width/4.0) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - }; + else if (imp == "square_fiber") { + + Func2Tensor B = [p1,theta,width] (const Domain& x) // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE + { + if (x[0] < 0 && std::max(abs(x[1]), abs(x[2])) < width/4.0 || 0 < x[0] && std::max(abs(x[1]), abs(x[2])) > width/4.0) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + }; std::cout <<" Prestrain Type: square_fiber"<< std::endl; return B; } else if (imp == "matrix_material_circles") // Matrix material with prestrained Fiber inclusions - { - int nF = parameters.get<int>("nF", 3); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - Func2Tensor B = [p1,p2,theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - - MatrixRT output; - - // determine if point is in upper/lower Layer - if ((0.0 <= s[2] && s[2] <= 1.0/2.0)) // upperLayer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) - { - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - } - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) - { - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0}; - - if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) - output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - } - } - - } - return output; - }; - std::cout <<" Prestrain Type: matrix_material"<< std::endl; - return B; - } - + { + int nF = parameters.get<int>("nF", 3); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + Func2Tensor B = [p1,p2,theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + + MatrixRT output; + + // determine if point is in upper/lower Layer + if ((0.0 <= s[2] && s[2] <= 1.0/2.0)) // upperLayer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) + { + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + } + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) + { + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0}; + + if(sqrt(pow(s[0]-Fcenter[0],2)+pow(s[2]-Fcenter[1],2)) <= rF ) + output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + } + } + + } + return output; + }; + std::cout <<" Prestrain Type: matrix_material"<< std::endl; + return B; + } + else if (imp == "matrix_material_squares") // Matrix material with prestrained Fiber inclusions - { - int nF = parameters.get<int>("nF", 3); //number of Fibers in each Layer - double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) - - assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain - - Func2Tensor B = [p1,p2,theta,nF,rF,height,width] (const Domain& x) - { - //TODO if Domain == 1... if Domain == 2 ... - // double domainShift = 1.0/2.0; - double domainShift = 0.0; - // shift x to domain [0,1]^3 - FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; - - MatrixRT output; - - // determine if point is in upper/lower Layer - if ((0.0 <= s[2] && s[2] <= 1.0/2.0)) // upperLayer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) - { - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; - // - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - } - } - } - else // lower Layer - { - for(size_t i=0; i<nF ;i++) // running through all the Fibers.. - { - if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) - { - // compute Fiber center - FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0}; - - if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) - output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - } - } - - } - return output; - }; - std::cout <<" Prestrain Type: matrix_material"<< std::endl; - return B; - } - else - { - // TODO other geometries etc... - - } + { + int nF = parameters.get<int>("nF", 3); //number of Fibers in each Layer + double rF = parameters.get<double>("rF", 0.5*(width/(2.0*nF)) ); //default: half of the max-fiber-radius mrF = (width/(2.0*nF)) + + assert( (2*rF)*nF <= width && (height/4)+rF <= height); //check that fibers are not bigger than Domain + + Func2Tensor B = [p1,p2,theta,nF,rF,height,width] (const Domain& x) + { + //TODO if Domain == 1... if Domain == 2 ... + // double domainShift = 1.0/2.0; + double domainShift = 0.0; + // shift x to domain [0,1]^3 + FieldVector<double,3> s = {x[0]+domainShift, x[1]+domainShift, x[2]+domainShift}; + + MatrixRT output; + + // determine if point is in upper/lower Layer + if ((0.0 <= s[2] && s[2] <= 1.0/2.0)) // upperLayer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) + { + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , 1.0/4.0}; + // + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + } + } + } + else // lower Layer + { + for(size_t i=0; i<nF ; i++) // running through all the Fibers.. + { + if(-1.0/2.0 + (1.0/nF)*i<= s[0] && s[0] <= -1.0/2.0 + (1.0/nF)*(i+1)) + { + // compute Fiber center + FieldVector<double,2> Fcenter = { (1.0/(2.0*nF))+((1.0/double(nF))*i)-(1.0/2.0) , -1.0/4.0}; + + if(std::max( abs(s[0]-Fcenter[0]), abs(s[2]-Fcenter[1]) ) <= rF ) + output = MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + // return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + output = MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + // return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + } + } + + } + return output; + }; + std::cout <<" Prestrain Type: matrix_material"<< std::endl; + return B; + } + else + { + // TODO other geometries etc... + + } // TODO ANISOTROPIC PRESSURE - + } - - - + + + FuncScalar getNormPrestrain(const FuncMatrix& B) { FuncScalar normB = [&](const Domain& z) { - return norm(B(z)); - }; - return normB; + return norm(B(z)); + }; + return normB; } diff --git a/dune/microstructure/deprecated_headers/prestrainimp.hh b/dune/microstructure/deprecated_headers/prestrainimp.hh index 443de31641e6406e5702a52621ab49606ddb0d07..adc6470d95639c9408e976328e93077534d64263 100644 --- a/dune/microstructure/deprecated_headers/prestrainimp.hh +++ b/dune/microstructure/deprecated_headers/prestrainimp.hh @@ -15,99 +15,99 @@ class PrestrainImp { public: - static const int dim = 3; - static const int nCompo = 3; + static const int dim = 3; + static const int nCompo = 3; -// using GridType_Ce = typename MicrostructuredRodGrid::CellGridType; - using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim>>; - using GridView = CellGridType::LeafGridView; - using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate; + // using GridType_Ce = typename MicrostructuredRodGrid::CellGridType; + using CellGridType = YaspGrid< dim, EquidistantOffsetCoordinates< double, dim> >; + using GridView = CellGridType::LeafGridView; + using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate; - using MatrixRT = FieldMatrix< double, nCompo, nCompo>; - using Func2Tensor = std::function< MatrixRT(const Domain&) >; -// using Domain = typename GridType_Ce::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate; -// using MatrixRT = FieldMatrix< double, nCompo, nCompo>; -// using Func2Tensor = std::function< MatrixRT(const Domain&) >; + using MatrixRT = FieldMatrix< double, nCompo, nCompo>; + using Func2Tensor = std::function< MatrixRT(const Domain&) >; + // using Domain = typename GridType_Ce::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate; + // using MatrixRT = FieldMatrix< double, nCompo, nCompo>; + // using Func2Tensor = std::function< MatrixRT(const Domain&) >; protected: - double p1, p2, theta; - double width; //cell geometry + double p1, p2, theta; + double width; //cell geometry public: - PrestrainImp(double p1, double p2, double theta, double width) : p1(p1), p2(p2), theta(theta), width(width){} + PrestrainImp(double p1, double p2, double theta, double width) : p1(p1), p2(p2), theta(theta), width(width){} - Func2Tensor getPrestrain(unsigned int imp) + Func2Tensor getPrestrain(unsigned int imp) + { + using std::pow; + using std::abs; + using std::sqrt; + using std::sin; + using std::cos; + + if (imp==1) { - using std::pow; - using std::abs; - using std::sqrt; - using std::sin; - using std::cos; - - if (imp==1) - { - - Func2Tensor B1_ = [this] (const Domain& x) { // ISOTROPIC PRESSURE - if (abs(x[0]) > (theta/2) && x[2] > 0) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - if (abs(x[0]) < (theta/2) && x[2] < 0) - return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - - }; - std::cout <<" Prestrain Type: 1 "<< std::endl; - return B1_; - } - else if (imp==2) - { - Func2Tensor B2_ = [this] (const Domain& x) { // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE - - if (abs(x[0]) < (theta/2) && x[2] < 0 && x[2] > -(1.0/2.0) ) - return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; - else - return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; - - - }; - std::cout <<" Prestrain Type: 2 "<< std::endl; - return B2_; - - - } - - - - - // TODO ANISOTROPIC PRESSURE - -// else if (imp==2) -// { -// -// Func2Tensor B2_ = [this] (const Domain& z) -// { -// auto pi = std::acos(-1.0); -// double beta = pi/4.0 + pi/4.0*z[1]; //z[1]=x3 -// MatrixRT Id(0); -// for (int i=0;i<nCompo;i++) -// Id[i][i]=1.0; -// MatrixRT pressure = Id; -// pressure *= 1.0/6.0; -// MatrixRT n_ot_n = { -// {cos(beta)*cos(beta), 0.0, cos(beta)*sin(beta)}, -// {0.0, 0.0, 0.0 }, -// {cos(beta)*sin(beta), 0.0, sin(beta)*sin(beta)} -// }; -// n_ot_n*=0.5; -// pressure += n_ot_n; -// pressure *= this->a; -// return pressure; -// }; -// return B2_; -// } + + Func2Tensor B1_ = [this] (const Domain& x) { // ISOTROPIC PRESSURE + if (abs(x[0]) > (theta/2) && x[2] > 0) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + if (abs(x[0]) < (theta/2) && x[2] < 0) + return MatrixRT{{p2, 0.0 , 0.0}, {0.0, p2, 0.0}, {0.0, 0.0, p2}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + + }; + std::cout <<" Prestrain Type: 1 "<< std::endl; + return B1_; } + else if (imp==2) + { + Func2Tensor B2_ = [this] (const Domain& x) { // Bilayer with one rectangular Fiber & ISOTROPIC PRESSURE + + if (abs(x[0]) < (theta/2) && x[2] < 0 && x[2] > -(1.0/2.0) ) + return MatrixRT{{p1, 0.0 , 0.0}, {0.0, p1, 0.0}, {0.0, 0.0, p1}}; + else + return MatrixRT{{0.0, 0.0 , 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + + + }; + std::cout <<" Prestrain Type: 2 "<< std::endl; + return B2_; + + + } + + + + + // TODO ANISOTROPIC PRESSURE + + // else if (imp==2) + // { + // + // Func2Tensor B2_ = [this] (const Domain& z) + // { + // auto pi = std::acos(-1.0); + // double beta = pi/4.0 + pi/4.0*z[1]; //z[1]=x3 + // MatrixRT Id(0); + // for (int i=0;i<nCompo;i++) + // Id[i][i]=1.0; + // MatrixRT pressure = Id; + // pressure *= 1.0/6.0; + // MatrixRT n_ot_n = { + // {cos(beta)*cos(beta), 0.0, cos(beta)*sin(beta)}, + // {0.0, 0.0, 0.0 }, + // {cos(beta)*sin(beta), 0.0, sin(beta)*sin(beta)} + // }; + // n_ot_n*=0.5; + // pressure += n_ot_n; + // pressure *= this->a; + // return pressure; + // }; + // return B2_; + // } + } }; diff --git a/dune/microstructure/deprecated_headers/vtk_filler.hh b/dune/microstructure/deprecated_headers/vtk_filler.hh index aa61fb2c1c8b475338d0d9def75e57c8709180ca..191272d3a09614ec3c7dfdc56f6eef1a5feafc0a 100644 --- a/dune/microstructure/deprecated_headers/vtk_filler.hh +++ b/dune/microstructure/deprecated_headers/vtk_filler.hh @@ -8,819 +8,819 @@ #include <dune/microstructure/prestrain_material_geometry.hh> - using std::string; - using namespace Dune; - using namespace Functions; - using namespace Functions::BasisFactory; - - //static const int dimworld = 3; - - //using GT = UGGrid<dim>; //typename MicrostructuredRodGrid::GT<dim>; - //using GV = typename GT::LeafGridView; - /* - using MatrixRT = FieldMatrix< double, dimworld, dimworld>; - using VectorRT = FieldVector< double, dimworld>; - using ScalarRT = double; - - - using ScalarCT = std::vector<double>; - using VectorCT = BlockVector<FieldVector<double,1> >; - - using HierarchicVectorView = Dune::Functions::HierarchicVectorWrapper< VectorCT, double>; -*/ - /* - template<class Basis> - static auto scalarDiscGlobalBasisFunc( - const Basis& feBasis, - std::function< double(const typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate&) >& scalarFunc) - { - ScalarCT values; - Functions::interpolate(feBasis, values, scalarFunc); - auto discGlobalBasisFunc = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (feBasis, values); - return discGlobalBasisFunc; - } - - template<class Basis> - static auto vectorDiscGlobalBasisFunc( - const Basis& feBasis, - std::function< FieldVector< double, dimworld>(const typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate&) >& vectorFunc) - { - VectorCT values; - Functions::interpolate(feBasis, values, vectorFunc); - auto discGlobalBasisFunc = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(feBasis), HierarchicVectorView(values)); - return discGlobalBasisFunc; - } -*/ - -template <int dim> -class FTKfillerContainer { - -public: - - static const int dimworld = 3; - -// using GT = UGGrid<dim>; //typename MicrostructuredRodGrid::GT<dim>; - using GT =YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >; - using GV = typename GT::LeafGridView; - using Domain = typename GV::template Codim<0>::Geometry::GlobalCoordinate; - using MatrixRT = FieldMatrix< double, dimworld, dimworld>; - using VectorRT = FieldVector< double, dimworld>; - using ScalarRT = double; - using FuncMatrix = std::function< MatrixRT(const Domain&) >; - using FuncVector = std::function< VectorRT(const Domain&) >; - using FuncScalar = std::function< ScalarRT(const Domain&) >; +using std::string; +using namespace Dune; +using namespace Functions; +using namespace Functions::BasisFactory; - using ScalarCT = std::vector<double>; - using VectorCT = BlockVector<FieldVector<double,1> >; - using HierarchicVectorView = Dune::Functions::HierarchicVectorWrapper< VectorCT, double>; +//static const int dimworld = 3; +//using GT = UGGrid<dim>; //typename MicrostructuredRodGrid::GT<dim>; +//using GV = typename GT::LeafGridView; +/* + using MatrixRT = FieldMatrix< double, dimworld, dimworld>; + using VectorRT = FieldVector< double, dimworld>; + using ScalarRT = double; - void vtkPrestrainNorm(const GV& gridView, const FuncMatrix& B, string filename) // Updated - { - VTKWriter<typename GT::LeafGridView> vtkWriter(gridView); - Functions::LagrangeBasis<typename GT::LeafGridView, 1> feBasis(gridView); - FuncScalar normB = PrestrainImp<dim>().getNormPrestrain(B); -// auto discGlobalBasisFunc = scalarDiscGlobalBasisFunc(feBasis, normB); - auto discGlobalBasisFunc = Dune::Functions::makeGridViewFunction(normB, gridView); -// auto muLocal = localFunction(muGridF); + using ScalarCT = std::vector<double>; + using VectorCT = BlockVector<FieldVector<double,1> >; + using HierarchicVectorView = Dune::Functions::HierarchicVectorWrapper< VectorCT, double>; + */ +/* + template<class Basis> + static auto scalarDiscGlobalBasisFunc( + const Basis& feBasis, + std::function< double(const typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate&) >& scalarFunc) + { + ScalarCT values; + Functions::interpolate(feBasis, values, scalarFunc); + auto discGlobalBasisFunc = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (feBasis, values); + return discGlobalBasisFunc; + } + + template<class Basis> + static auto vectorDiscGlobalBasisFunc( + const Basis& feBasis, + std::function< FieldVector< double, dimworld>(const typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate&) >& vectorFunc) + { + VectorCT values; + Functions::interpolate(feBasis, values, vectorFunc); + auto discGlobalBasisFunc = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(feBasis), HierarchicVectorView(values)); + return discGlobalBasisFunc; + } + */ - ScalarCT values; - Functions::interpolate(feBasis, values, normB); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (feBasis, values); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - vtkWriter.write(filename); +template <int dim> +class FTKfillerContainer { - } +public: - void vtkPrestrainDirector(const typename GT::LeafGridView& gridView, const FuncVector& b, string filename) - { - VTKWriter<typename GT::LeafGridView> vtkWriter(gridView); + static const int dimworld = 3; - using namespace Functions::BasisFactory; + // using GT = UGGrid<dim>; //typename MicrostructuredRodGrid::GT<dim>; + using GT =YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >; + using GV = typename GT::LeafGridView; + using Domain = typename GV::template Codim<0>::Geometry::GlobalCoordinate; + using MatrixRT = FieldMatrix< double, dimworld, dimworld>; + using VectorRT = FieldVector< double, dimworld>; + using ScalarRT = double; + using FuncMatrix = std::function< MatrixRT(const Domain&) >; + using FuncVector = std::function< VectorRT(const Domain&) >; + using FuncScalar = std::function< ScalarRT(const Domain&) >; - auto basis_CE = makeBasis( - gridView, - power<dimworld>( - lagrange<1>(), - flatLexicographic()));//flatInterleaved() + using ScalarCT = std::vector<double>; + using VectorCT = BlockVector<FieldVector<double,1> >; + using HierarchicVectorView = Dune::Functions::HierarchicVectorWrapper< VectorCT, double>; - VectorCT values; - Functions::interpolate(basis_CE, values, b); - auto b_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, values); - vtkWriter.addVertexData(b_DGBF, VTK::FieldInfo("prestrain_director", VTK::FieldInfo::Type::vector, dimworld)); - vtkWriter.write(filename); - } + void vtkPrestrainNorm(const GV& gridView, const FuncMatrix& B, string filename) // Updated + { + VTKWriter<typename GT::LeafGridView> vtkWriter(gridView); + Functions::LagrangeBasis<typename GT::LeafGridView, 1> feBasis(gridView); + FuncScalar normB = PrestrainImp<dim>().getNormPrestrain(B); + // auto discGlobalBasisFunc = scalarDiscGlobalBasisFunc(feBasis, normB); + auto discGlobalBasisFunc = Dune::Functions::makeGridViewFunction(normB, gridView); + // auto muLocal = localFunction(muGridF); - void vtkMaterialCell(const GV& gridView_CE, - const FuncScalar& mu_Func, - std::string filename) - { - std::cout << "vtkMaterialCell ...\n"; + ScalarCT values; + Functions::interpolate(feBasis, values, normB); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (feBasis, values); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + vtkWriter.write(filename); - VTKWriter<GV> vtkWriter(gridView_CE); + } - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + void vtkPrestrainDirector(const typename GT::LeafGridView& gridView, const FuncVector& b, string filename) + { + VTKWriter<typename GT::LeafGridView> vtkWriter(gridView); - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addCellData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + using namespace Functions::BasisFactory; - vtkWriter.write(filename); + auto basis_CE = makeBasis( + gridView, + power<dimworld>( + lagrange<1>(), + flatLexicographic()));//flatInterleaved() - std::cout << "vtkMaterialCell done.\n"; - } + VectorCT values; + Functions::interpolate(basis_CE, values, b); + auto b_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, values); + vtkWriter.addVertexData(b_DGBF, VTK::FieldInfo("prestrain_director", VTK::FieldInfo::Type::vector, dimworld)); + vtkWriter.write(filename); + } - void vtkMaterial3DRod(const GV& gridView_R3D, double eps, - const FuncVector& domain_Func, const FuncScalar& mu_Func, - std::string filename) - { - std::cout << "vtkProblem ...\n"; + void vtkMaterialCell(const GV& gridView_CE, + const FuncScalar& mu_Func, + std::string filename) + { - VTKWriter<GV> vtkWriter(gridView_R3D); + std::cout << "vtkMaterialCell ...\n"; - // Vector data - const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + VTKWriter<GV> vtkWriter(gridView_CE); - VectorCT domain_Coeff; - Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); - auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); - vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addCellData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + vtkWriter.write(filename); - vtkWriter.write(filename); + std::cout << "vtkMaterialCell done.\n"; + } - std::cout << "vtkProblem done.\n"; - } + void vtkMaterial3DRod(const GV& gridView_R3D, double eps, + const FuncVector& domain_Func, const FuncScalar& mu_Func, + std::string filename) + { - void vtkProblemCell(const GV& gridView_CE, - const FuncMatrix& B_Func, const FuncScalar& mu_Func, - std::string filename) - { + std::cout << "vtkProblem ...\n"; - std::cout << "vtkProblemCell ...\n"; - - VTKWriter<GV> vtkWriter(gridView_CE); - - // Vector data - const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - - FuncVector Be1_Func = [B_Func](const auto& x) - { - return B_Func(x)[0]; - }; - VectorCT Be1_Coeff; - Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); - auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); - vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - FuncVector Be2_Func = [B_Func](const auto& x) - { - return B_Func(x)[1]; - }; - VectorCT Be2_Coeff; - Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); - auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); - vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_Func = [B_Func](const auto& x) - { - return B_Func(x)[2]; - }; - VectorCT Be3_Coeff; - Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); - auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); - vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); - FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; - } + VTKWriter<GV> vtkWriter(gridView_R3D); - void vtkProblemCellBVec(const GV& gridView_CE, - const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, - std::string filename) - { + // Vector data + const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - std::cout << "vtkProblemCellBVec ...\n"; + VectorCT domain_Coeff; + Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); + auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); + vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); - VTKWriter<GV> vtkWriter(gridView_CE); + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); - // Vector data - const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + vtkWriter.write(filename); - FuncVector Be1_Func = [B_Func](const auto& x) - { - return B_Func(x)[0]; - }; - VectorCT Be1_Coeff; - Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); - auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); - vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + std::cout << "vtkProblem done.\n"; + } - FuncVector Be2_Func = [B_Func](const auto& x) - { - return B_Func(x)[1]; - }; - VectorCT Be2_Coeff; - Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); - auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); - vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + void vtkProblemCell(const GV& gridView_CE, + const FuncMatrix& B_Func, const FuncScalar& mu_Func, + std::string filename) + { + std::cout << "vtkProblemCell ...\n"; - FuncVector Be3_Func = [B_Func](const auto& x) - { - return B_Func(x)[2]; - }; - VectorCT Be3_Coeff; - Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); - auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); - vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + VTKWriter<GV> vtkWriter(gridView_CE); + // Vector data + const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - VectorCT B_vec_Coeff; - Functions::interpolate(basis_CE, B_vec_Coeff, B_vec_Func); - auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, B_vec_Coeff); - vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); + FuncVector Be1_Func = [B_Func](const auto& x) + { + return B_Func(x)[0]; + }; + VectorCT Be1_Coeff; + Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); + auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); + vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + FuncVector Be2_Func = [B_Func](const auto& x) + { + return B_Func(x)[1]; + }; + VectorCT Be2_Coeff; + Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); + auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); + vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + FuncVector Be3_Func = [B_Func](const auto& x) + { + return B_Func(x)[2]; + }; + VectorCT Be3_Coeff; + Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); + auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); + vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - vtkWriter.write(filename); + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - std::cout << "vtkProblem done.\n"; - } + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + vtkWriter.write(filename); - void vtkProblem3DRod(const GV& gridView_R3D, double eps, - const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncScalar& mu_Func, - std::string filename) - { + std::cout << "vtkProblem done.\n"; + } - std::cout << "vtkProblem ...\n"; - - VTKWriter<GV> vtkWriter(gridView_R3D); - - // Vector data - const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - VectorCT domain_Coeff; - Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); - auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); - vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[0]; - }; - VectorCT Be1_R3D_Coeff; - Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); - auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); - vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[1]; - }; - VectorCT Be2_R3D_Coeff; - Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); - auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); - vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[2]; - }; - VectorCT Be3_R3D_Coeff; - Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); - auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); - vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); - - FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); - FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return normB_Func(x_Ce); - }; - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; - } + void vtkProblemCellBVec(const GV& gridView_CE, + const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, + std::string filename) + { - void vtkProblem3DRodBVec(const GV& gridView_R3D, double eps, - const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, - std::string filename) - { + std::cout << "vtkProblemCellBVec ...\n"; - std::cout << "vtkProblem ...\n"; - - VTKWriter<GV> vtkWriter(gridView_R3D); - - // Vector data - const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - VectorCT domain_Coeff; - Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); - auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); - vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[0]; - }; - VectorCT Be1_R3D_Coeff; - Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); - auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); - vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[1]; - }; - VectorCT Be2_R3D_Coeff; - Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); - auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); - vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[2]; - }; - VectorCT Be3_R3D_Coeff; - Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); - auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); - vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - FuncVector B_vec_R3D_Func = [B_vec_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_vec_Func(x_Ce); - }; - VectorCT B_vec_Coeff; - Functions::interpolate(basis_R3D, B_vec_Coeff, B_vec_R3D_Func); - auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_R3D, B_vec_Coeff); - vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); - - - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); - - FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); - FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return normB_Func(x_Ce); - }; - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - FuncScalar mu_R3D_Func = [mu_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return mu_Func(x_Ce); - }; - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_R3D_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; - } + VTKWriter<GV> vtkWriter(gridView_CE); + + // Vector data + const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + + FuncVector Be1_Func = [B_Func](const auto& x) + { + return B_Func(x)[0]; + }; + VectorCT Be1_Coeff; + Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); + auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); + vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_Func = [B_Func](const auto& x) + { + return B_Func(x)[1]; + }; + VectorCT Be2_Coeff; + Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); + auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); + vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_Func = [B_Func](const auto& x) + { + return B_Func(x)[2]; + }; + VectorCT Be3_Coeff; + Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); + auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); + vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + + VectorCT B_vec_Coeff; + Functions::interpolate(basis_CE, B_vec_Coeff, B_vec_Func); + auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, B_vec_Coeff); + vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + + FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; + } + + + void vtkProblem3DRod(const GV& gridView_R3D, double eps, + const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncScalar& mu_Func, + std::string filename) + { + + std::cout << "vtkProblem ...\n"; + + VTKWriter<GV> vtkWriter(gridView_R3D); + + // Vector data + const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + VectorCT domain_Coeff; + Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); + auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); + vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[0]; + }; + VectorCT Be1_R3D_Coeff; + Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); + auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); + vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[1]; + }; + VectorCT Be2_R3D_Coeff; + Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); + auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); + vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[2]; + }; + VectorCT Be3_R3D_Coeff; + Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); + auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); + vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); + + FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); + FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return normB_Func(x_Ce); + }; + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; + } + + void vtkProblem3DRodBVec(const GV& gridView_R3D, double eps, + const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, + std::string filename) + { + + std::cout << "vtkProblem ...\n"; + + VTKWriter<GV> vtkWriter(gridView_R3D); + + // Vector data + const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + VectorCT domain_Coeff; + Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); + auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); + vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[0]; + }; + VectorCT Be1_R3D_Coeff; + Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); + auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); + vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[1]; + }; + VectorCT Be2_R3D_Coeff; + Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); + auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); + vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[2]; + }; + VectorCT Be3_R3D_Coeff; + Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); + auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); + vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + FuncVector B_vec_R3D_Func = [B_vec_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_vec_Func(x_Ce); + }; + VectorCT B_vec_Coeff; + Functions::interpolate(basis_R3D, B_vec_Coeff, B_vec_R3D_Func); + auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_R3D, B_vec_Coeff); + vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); + + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); + + FuncScalar normB_Func = PrestrainImp<dim>().getNormPrestrain(B_Func); + FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return normB_Func(x_Ce); + }; + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + FuncScalar mu_R3D_Func = [mu_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return mu_Func(x_Ce); + }; + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_R3D_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; + } }; /* - template<int dim> - void vtkProblemCell(const typename UGGrid<dim>::LeafGridView& gridView_CE, - const std::function< MatrixRT(const typename UGGrid<dim>::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate&)& B_Func, - const std::function< ScalarRT(const typename UGGrid<dim>::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate&)& mu_Func, - std::string filename) + template<int dim> + void vtkProblemCell(const typename UGGrid<dim>::LeafGridView& gridView_CE, + const std::function< MatrixRT(const typename UGGrid<dim>::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate&)& B_Func, + const std::function< ScalarRT(const typename UGGrid<dim>::LeafGridView::template Codim<0>::Geometry::GlobalCoordinate&)& mu_Func, + std::string filename) { - using GT = UGGrid<dim>; - using GV = typename GT::LeafGridView; - using Domain = typename GV::template Codim<0>::Geometry::GlobalCoordinate; - using FuncMatrix = std::function< MatrixRT(const Domain&) >; - using FuncVector = std::function< VectorRT(const Domain&) >; - using FuncScalar = std::function< ScalarRT(const Domain&) >; - std::cout << "vtkProblemCell ...\n"; - - VTKWriter<GV> vtkWriter(gridView_CE); - - // Vector data - const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - - FuncVector Be1_Func = [B_Func](const auto& x) - { - return B_Func(x)[0]; - }; - VectorCT Be1_Coeff; - Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); - auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); - vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be2_Func = [B_Func](const auto& x) - { - return B_Func(x)[1]; - }; - VectorCT Be2_Coeff; - Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); - auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); - vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_Func = [B_Func](const auto& x) - { - return B_Func(x)[2]; - }; - VectorCT Be3_Coeff; - Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); - auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); - vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); - - FuncScalar normB_Func = getNormPrestrain(B_Func); - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; + using GT = UGGrid<dim>; + using GV = typename GT::LeafGridView; + using Domain = typename GV::template Codim<0>::Geometry::GlobalCoordinate; + using FuncMatrix = std::function< MatrixRT(const Domain&) >; + using FuncVector = std::function< VectorRT(const Domain&) >; + using FuncScalar = std::function< ScalarRT(const Domain&) >; + std::cout << "vtkProblemCell ...\n"; + + VTKWriter<GV> vtkWriter(gridView_CE); + + // Vector data + const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + + FuncVector Be1_Func = [B_Func](const auto& x) + { + return B_Func(x)[0]; + }; + VectorCT Be1_Coeff; + Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); + auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); + vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_Func = [B_Func](const auto& x) + { + return B_Func(x)[1]; + }; + VectorCT Be2_Coeff; + Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); + auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); + vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_Func = [B_Func](const auto& x) + { + return B_Func(x)[2]; + }; + VectorCT Be3_Coeff; + Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); + auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); + vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + + FuncScalar normB_Func = getNormPrestrain(B_Func); + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; } void vtkProblemCellBVec(const GV& gridView_CE, - const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, - std::string filename) + const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, + std::string filename) { - std::cout << "vtkProblemCell ...\n"; + std::cout << "vtkProblemCell ...\n"; - VTKWriter<GV> vtkWriter(gridView_CE); + VTKWriter<GV> vtkWriter(gridView_CE); - // Vector data - const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + // Vector data + const auto basis_CE = makeBasis(gridView_CE, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - FuncVector Be1_Func = [B_Func](const auto& x) - { - return B_Func(x)[0]; - }; - VectorCT Be1_Coeff; - Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); - auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); - vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + FuncVector Be1_Func = [B_Func](const auto& x) + { + return B_Func(x)[0]; + }; + VectorCT Be1_Coeff; + Functions::interpolate(basis_CE, Be1_Coeff, Be1_Func); + auto Be1_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be1_Coeff)); + vtkWriter.addVertexData(Be1_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - FuncVector Be2_Func = [B_Func](const auto& x) - { - return B_Func(x)[1]; - }; - VectorCT Be2_Coeff; - Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); - auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); - vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + FuncVector Be2_Func = [B_Func](const auto& x) + { + return B_Func(x)[1]; + }; + VectorCT Be2_Coeff; + Functions::interpolate(basis_CE, Be2_Coeff, Be2_Func); + auto Be2_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be2_Coeff)); + vtkWriter.addVertexData(Be2_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - FuncVector Be3_Func = [B_Func](const auto& x) - { - return B_Func(x)[2]; - }; - VectorCT Be3_Coeff; - Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); - auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); - vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + FuncVector Be3_Func = [B_Func](const auto& x) + { + return B_Func(x)[2]; + }; + VectorCT Be3_Coeff; + Functions::interpolate(basis_CE, Be3_Coeff, Be3_Func); + auto Be3_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_CE), HierarchicVectorView(Be3_Coeff)); + vtkWriter.addVertexData(Be3_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - VectorCT B_vec_Coeff; - Functions::interpolate(basis_CE, B_vec_Coeff, B_vec_Func); - auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, B_vec_Coeff); - vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); + VectorCT B_vec_Coeff; + Functions::interpolate(basis_CE, B_vec_Coeff, B_vec_Func); + auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_CE, B_vec_Coeff); + vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_CE); - FuncScalar normB_Func = getNormPrestrain(B_Func); - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + FuncScalar normB_Func = getNormPrestrain(B_Func); + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - vtkWriter.write(filename); + vtkWriter.write(filename); - std::cout << "vtkProblem done.\n"; + std::cout << "vtkProblem done.\n"; } void vtkProblem3DRod(const GV& gridView_R3D, double eps, - const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncScalar& mu_Func, - std::string filename) + const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncScalar& mu_Func, + std::string filename) { - std::cout << "vtkProblem ...\n"; - - VTKWriter<GV> vtkWriter(gridView_R3D); - - // Vector data - const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - VectorCT domain_Coeff; - Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); - auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); - vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[0]; - }; - VectorCT Be1_R3D_Coeff; - Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); - auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); - vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[1]; - }; - VectorCT Be2_R3D_Coeff; - Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); - auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); - vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[2]; - }; - VectorCT Be3_R3D_Coeff; - Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); - auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); - vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); - - FuncScalar normB_Func = getNormPrestrain(B_Func); - FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return normB_Func(x_Ce); - }; - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; + std::cout << "vtkProblem ...\n"; + + VTKWriter<GV> vtkWriter(gridView_R3D); + + // Vector data + const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + VectorCT domain_Coeff; + Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); + auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); + vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[0]; + }; + VectorCT Be1_R3D_Coeff; + Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); + auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); + vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[1]; + }; + VectorCT Be2_R3D_Coeff; + Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); + auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); + vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[2]; + }; + VectorCT Be3_R3D_Coeff; + Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); + auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); + vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); + + FuncScalar normB_Func = getNormPrestrain(B_Func); + FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return normB_Func(x_Ce); + }; + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; } void vtkProblem3DRodBVec(const GV& gridView_R3D, double eps, - const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, - std::string filename) + const FuncVector& domain_Func, const FuncMatrix& B_Func, const FuncVector& B_vec_Func, const FuncScalar& mu_Func, + std::string filename) { - std::cout << "vtkProblem ...\n"; - - VTKWriter<GV> vtkWriter(gridView_R3D); - - // Vector data - const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() - - VectorCT domain_Coeff; - Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); - auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); - vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[0]; - }; - VectorCT Be1_R3D_Coeff; - Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); - auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); - vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[1]; - }; - VectorCT Be2_R3D_Coeff; - Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); - auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); - vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); - - - FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_Func(x_Ce)[2]; - }; - VectorCT Be3_R3D_Coeff; - Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); - auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> - (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); - vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); - - FuncVector B_vec_R3D_Func = [B_vec_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return B_vec_Func(x_Ce); - }; - VectorCT B_vec_Coeff; - Functions::interpolate(basis_R3D, B_vec_Coeff, B_vec_R3D_Func); - auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_R3D, B_vec_Coeff); - vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); - - - - // Scalar data - Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); - - FuncScalar normB_Func = getNormPrestrain(B_Func); - FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return normB_Func(x_Ce); - }; - ScalarCT prestrain_Coeff; - Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); - auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, prestrain_Coeff); - vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); - - FuncScalar mu_R3D_Func = [mu_Func, eps](const auto& x) - { - auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; - return mu_Func(x_Ce); - }; - ScalarCT material_Coeff; - Functions::interpolate(scalarFeBasis, material_Coeff, mu_R3D_Func); - auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > - (scalarFeBasis, material_Coeff); - vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); - - vtkWriter.write(filename); - - std::cout << "vtkProblem done.\n"; + std::cout << "vtkProblem ...\n"; + + VTKWriter<GV> vtkWriter(gridView_R3D); + + // Vector data + const auto basis_R3D = makeBasis(gridView_R3D, power<dimworld>(lagrange<1>(), flatLexicographic())); //flatInterleaved() + + VectorCT domain_Coeff; + Functions::interpolate(basis_R3D, domain_Coeff, domain_Func); + auto domain_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(domain_Coeff)); + vtkWriter.addVertexData(domain_DGBF, VTK::FieldInfo("Domain", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be1_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[0]; + }; + VectorCT Be1_R3D_Coeff; + Functions::interpolate(basis_R3D, Be1_R3D_Coeff, Be1_R3D_Func); + auto Be1_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be1_R3D_Coeff)); + vtkWriter.addVertexData(Be1_R3D_DGBF, VTK::FieldInfo("B_e1", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be2_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[1]; + }; + VectorCT Be2_R3D_Coeff; + Functions::interpolate(basis_R3D, Be2_R3D_Coeff, Be2_R3D_Func); + auto Be2_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be2_R3D_Coeff)); + vtkWriter.addVertexData(Be2_R3D_DGBF, VTK::FieldInfo("B_e2", VTK::FieldInfo::Type::vector, 3)); + + + FuncVector Be3_R3D_Func = [B_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_Func(x_Ce)[2]; + }; + VectorCT Be3_R3D_Coeff; + Functions::interpolate(basis_R3D, Be3_R3D_Coeff, Be3_R3D_Func); + auto Be3_R3D_DGBF = Functions::makeDiscreteGlobalBasisFunction<VectorRT> + (Functions::subspaceBasis(basis_R3D), HierarchicVectorView(Be3_R3D_Coeff)); + vtkWriter.addVertexData(Be3_R3D_DGBF, VTK::FieldInfo("B_e3", VTK::FieldInfo::Type::vector, 3)); + + FuncVector B_vec_R3D_Func = [B_vec_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return B_vec_Func(x_Ce); + }; + VectorCT B_vec_Coeff; + Functions::interpolate(basis_R3D, B_vec_Coeff, B_vec_R3D_Func); + auto B_vec_DGBF = Functions::makeDiscreteGlobalBasisFunction< VectorRT > (basis_R3D, B_vec_Coeff); + vtkWriter.addVertexData(B_vec_DGBF, VTK::FieldInfo("B_vec", VTK::FieldInfo::Type::vector, dimworld)); + + + + // Scalar data + Functions::LagrangeBasis<GV, 1> scalarFeBasis(gridView_R3D); + + FuncScalar normB_Func = getNormPrestrain(B_Func); + FuncScalar normB_R3D_Func = [normB_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return normB_Func(x_Ce); + }; + ScalarCT prestrain_Coeff; + Functions::interpolate(scalarFeBasis, prestrain_Coeff, normB_R3D_Func); + auto normB_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, prestrain_Coeff); + vtkWriter.addVertexData(normB_DGBF, VTK::FieldInfo("normB", VTK::FieldInfo::Type::scalar, 1)); + + FuncScalar mu_R3D_Func = [mu_Func, eps](const auto& x) + { + auto x_Ce = {x[0]/eps - int(x[0]/eps),x[1],x[2]}; + return mu_Func(x_Ce); + }; + ScalarCT material_Coeff; + Functions::interpolate(scalarFeBasis, material_Coeff, mu_R3D_Func); + auto material_DGBF = Functions::makeDiscreteGlobalBasisFunction< ScalarRT > + (scalarFeBasis, material_Coeff); + vtkWriter.addVertexData(material_DGBF, VTK::FieldInfo("mu", VTK::FieldInfo::Type::scalar, 1)); + + vtkWriter.write(filename); + + std::cout << "vtkProblem done.\n"; } -*/ + */ #endif diff --git a/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh index c6c5091307d64b0c7902b242a0732bdae9dfd733..2d2994da6edfa804596e579972e7294c53fd9d42 100644 --- a/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh +++ b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh @@ -11,18 +11,18 @@ #include <dune/localfunctions/lagrange/lagrangesimplex.hh> #include <cmath> -/** - * \brief Assemble the discrete Kirchhoff bending energy for a single element. - * - * The Kirchhoff bending energy consists of two parts: - * - * 1. The energy of Qhom(II - Beff) where II is the second fundamental form of the surface parametrized by the deformation function - * and Beff is a (given) effective prestrain tensor. - * +/** + * \brief Assemble the discrete Kirchhoff bending energy for a single element. + * + * The Kirchhoff bending energy consists of two parts: + * + * 1. The energy of Qhom(II - Beff) where II is the second fundamental form of the surface parametrized by the deformation function + * and Beff is a (given) effective prestrain tensor. + * * This contribution is split intro three parts which corresponds to the binomial formula (a+b)^2 = a^2 + 2ab + b^2 * each term is discretized separately. - * - * 2. An integral over the scalar product of a forcing term and the discrete deformation + * + * 2. An integral over the scalar product of a forcing term and the discrete deformation * (i.e. the evaluation of localFunction_ ). */ namespace Dune::GFE @@ -45,17 +45,17 @@ namespace Dune::GFE public: DiscreteKirchhoffBendingEnergyPrestrained(LocalDiscreteKirchhoffFunction &localFunction, - LocalForce &localForce, - const Dune::ParameterTree& parameterSet) - : localFunction_(localFunction), - localForce_(localForce), - parameterSet_(parameterSet) + LocalForce &localForce, + const Dune::ParameterTree& parameterSet) + : localFunction_(localFunction), + localForce_(localForce), + parameterSet_(parameterSet) {} /** \brief Assemble the energy for a single element */ - virtual RT energy (const typename Basis::LocalView& localView, - const std::vector<TargetSpace>& localSolution) const + virtual RT energy (const typename Basis::LocalView& localView, + const std::vector<TargetSpace>& localSolution) const { RT energy = 0; @@ -70,27 +70,27 @@ namespace Dune::GFE // MatrixType Qhom = quadraticForm_; - /** + /** * @brief Get effective prestrain Tensor */ - Dune::FieldVector<RT,3> Beffvec = parameterSet_.get<Dune::FieldVector<RT,3>>("effectivePrestrain", {0.0, 0.0, 0.0}); + Dune::FieldVector<RT,3> Beffvec = parameterSet_.get<Dune::FieldVector<RT,3> >("effectivePrestrain", {0.0, 0.0, 0.0}); Dune::FieldMatrix<RT,2,2> Beff = {{Beffvec[0], Beffvec[2]}, {Beffvec[2], Beffvec[1]} }; // printmatrix(std::cout, Beff, "effective prestrain (Beff): ", "--"); /** * @brief Get effective quadratic form Qhom - * + * * input-vector: [q_1,q_2,q_3,q_12,q_13,q_23] * is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper) * ( q_1 , 0.5*q_12 , 0.5*q_13 ) * Q = ( 0.5*q_12 , q_2 , 0.5*q_23 ) * ( 0.5*q_13 , 0.5*q_23 , q_3 ) */ - Dune::FieldVector<RT,6> Qhomvec = parameterSet_.get<Dune::FieldVector<RT,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); - MatrixType Qhom = {{Qhomvec[0] , 0.5*Qhomvec[3], 0.5*Qhomvec[4]}, - {0.5*Qhomvec[3], Qhomvec[1], 0.5*Qhomvec[5]}, - {0.5*Qhomvec[4], 0.5*Qhomvec[5], Qhomvec[2]}}; + Dune::FieldVector<RT,6> Qhomvec = parameterSet_.get<Dune::FieldVector<RT,6> >("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); + MatrixType Qhom = {{Qhomvec[0] , 0.5*Qhomvec[3], 0.5*Qhomvec[4]}, + {0.5*Qhomvec[3], Qhomvec[1], 0.5*Qhomvec[5]}, + {0.5*Qhomvec[4], 0.5*Qhomvec[5], Qhomvec[2]}}; // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--"); @@ -110,7 +110,7 @@ namespace Dune::GFE quadOrder = (localFiniteElement.type().isSimplex()) ? (localFiniteElement.localBasis().order() - 1) * 2 : (localFiniteElement.localBasis().order() * gridDim - 1) * 2; #endif - + const auto element = localView.element(); auto geometry = element.geometry(); auto gridView = localFunction_.gridView(); @@ -131,40 +131,40 @@ namespace Dune::GFE // std::cout <<"ELEMENT NUMBER( indexSet.index(element)) ):" << indexSet.index(element) << std::endl; if(PRINT_DEBUG) { - std::cout << "geometry.corner(0): " << geometry.corner(0) << std::endl; - std::cout << "geometry.corner(1)): " << geometry.corner(1) << std::endl; - std::cout << "geometry.corner(2): " << geometry.corner(2) << std::endl; + std::cout << "geometry.corner(0): " << geometry.corner(0) << std::endl; + std::cout << "geometry.corner(1)): " << geometry.corner(1) << std::endl; + std::cout << "geometry.corner(2): " << geometry.corner(2) << std::endl; } /** - * @brief Get Coefficients of the discrete Jacobian - * + * @brief Get Coefficients of the discrete Jacobian + * * The discrete Jacobian is a special linear combination represented in a [P2]^2 - (Lagrange) space * The coefficients of this linear combination correspond to certain linear combinations of the Jacobians of localfunction_ . * The coefficients are stored in the form [Basisfunctions x components x gridDim] * in a BlockVector<FieldMatrix<RT, 3, gridDim>> . */ - BlockVector<FieldMatrix<RT, 3, gridDim>> discreteJacobianCoefficients; + BlockVector<FieldMatrix<RT, 3, gridDim> > discreteJacobianCoefficients; discreteGradientCoefficients(discreteJacobianCoefficients,lagrangeLFE_,localFunction_,element); - - - - + + + + /** * @brief Compute harmonic energy contribution: */ RT harmonicEnergy = 0; - + //VERSION - 1 #if 0 /** - * @brief Setup Quadrature rule. - * + * @brief Setup Quadrature rule. + * */ // Gauss-Quadrature: const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder); @@ -175,7 +175,7 @@ namespace Dune::GFE for (auto&& quadPoint : quadRule) { //Get values of the P2-Basis functions on current quadrature point - std::vector<FieldVector<double,1>> basisValues; + std::vector<FieldVector<double,1> > basisValues; lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues); // if(PRINT_DEBUG) @@ -186,14 +186,14 @@ namespace Dune::GFE // } // Get Jacobians of the P2-Basis functions on current quadrature point - std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients; + std::vector<FieldMatrix<double, 1, gridDim> > referenceGradients; lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients); const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position()); const auto integrationElement = geometry.integrationElement(quadPoint.position()); // printmatrix(std::cout, jacobian , "jacobian : ", "--"); - std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size()); + std::vector<FieldVector<RT, gridDim> > gradients(referenceGradients.size()); for (size_t i = 0; i<gradients.size(); i++) jacobian.mv(referenceGradients[i][0], gradients[i]); @@ -203,30 +203,30 @@ namespace Dune::GFE // lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), gradients); - Tensor3<RT,3,2,2> discreteHessian(0); + Tensor3<RT,3,2,2> discreteHessian(0); FieldMatrix<RT, 3, gridDim> discreteGradient(0); - /** - * @brief Compute the discrete Hessian and discrete Gradient as a linear combination of - * function and gradient evaluations of the P2-basis functions with the coefficients given - * by 'discreteJacobianCoefficients'. - * Since the deformation function has k=3 components we get - * - discreteGradient : 3x2 matrix - * - discreteHessian: 3x2x2 tensor - */ + /** + * @brief Compute the discrete Hessian and discrete Gradient as a linear combination of + * function and gradient evaluations of the P2-basis functions with the coefficients given + * by 'discreteJacobianCoefficients'. + * Since the deformation function has k=3 components we get + * - discreteGradient : 3x2 matrix + * - discreteHessian: 3x2x2 tensor + */ for (int k=0; k<3; k++) - for (int l=0; l<gridDim; l++) - for(std::size_t i=0; i<lagrangeLFE_.size(); i++) - { - // Compute discrete gradient - discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; - // Compute discrete Hessian - discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; - discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; - // discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0][0]; - // discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][0][1]; - } + for (int l=0; l<gridDim; l++) + for(std::size_t i=0; i<lagrangeLFE_.size(); i++) + { + // Compute discrete gradient + discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; + // Compute discrete Hessian + discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; + discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; + // discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0][0]; + // discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][0][1]; + } // DerivativeType whJacobianValue = localFunction_.evaluateDerivative(quadPoint.position()); @@ -239,7 +239,7 @@ namespace Dune::GFE // - + @@ -262,17 +262,17 @@ namespace Dune::GFE // if(PRINT_DEBUG) // { - /** - * @brief print the (two) different 3x2 slices of the discrete Hessian - */ + /** + * @brief print the (two) different 3x2 slices of the discrete Hessian + */ FieldMatrix<RT, 3, 2> discreteHessian_slice1(0); FieldMatrix<RT, 3, 2> discreteHessian_slice2(0); for (int k=0; k<3; k++) - for (int l=0; l<gridDim; l++) - { + for (int l=0; l<gridDim; l++) + { discreteHessian_slice1[k][l] = discreteHessian[k][l][0]; discreteHessian_slice2[k][l] = discreteHessian[k][l][1]; - } + } // printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--"); // printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--"); // } @@ -287,7 +287,7 @@ namespace Dune::GFE /** - * @brief Compute the surface normal given by the cross-product of the two different partial derivatives + * @brief Compute the surface normal given by the cross-product of the two different partial derivatives * of the discrete gradient. * This is needed to compute the second fundamental form. */ @@ -299,7 +299,7 @@ namespace Dune::GFE auto normY = partialY.two_norm(); /** - * @brief Test: normalize + * @brief Test: normalize */ // partialX /= normX; // partialY /= normY; @@ -311,9 +311,9 @@ namespace Dune::GFE // std::cout << "surfaceNormal.two_norm() : " << surfaceNormal.two_norm() << std::endl; // surfaceNormal *= -1.0; - + /** - * @brief Test: normalize + * @brief Test: normalize */ // auto norm = surfaceNormal.two_norm(); // surfaceNormal /= norm; @@ -326,24 +326,24 @@ namespace Dune::GFE FieldMatrix<RT,2,2> secondFF(0); for(size_t m=0; m<2; m++) - for(size_t n=0; n<2; n++) - for(size_t k=0; k<3; k++) - { - secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; - - - //Test: transposed version - // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k]; - // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0]; - // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0]; - // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1]; - // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1]; - } + for(size_t n=0; n<2; n++) + for(size_t k=0; k<3; k++) + { + secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; + + + //Test: transposed version + // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k]; + // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0]; + // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0]; + // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1]; + // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1]; + } // printmatrix(std::cout, secondFF , "secondFF: ", "--"); /** - * @brief Check orthogonality between discrete Hessian and discrete gradient + * @brief Check orthogonality between discrete Hessian and discrete gradient * at nodes. */ // std::cout << "---- ORTHOGONALITY CHECK 1: ----" << std::endl; @@ -402,7 +402,7 @@ namespace Dune::GFE /** * @brief Subtract the effective prestrain */ - auto G = secondFF - Beff; + auto G = secondFF - Beff; // auto symG = 0.5*(G.transposed() + G); @@ -415,7 +415,7 @@ namespace Dune::GFE auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position()); /** - * @brief TEST: Check the difference between the squared Frobenius norm of the + * @brief TEST: Check the difference between the squared Frobenius norm of the * second fundamental form and discrete Hessian. * (Note that for isometries, these should be equal.) */ @@ -441,7 +441,7 @@ namespace Dune::GFE // { // term2 += weight * secondFF[i][j] * Beff[i][j]; // } - // auto term3 = 0.5 * weight * Beff.frobenius_norm2(); + // auto term3 = 0.5 * weight * Beff.frobenius_norm2(); // std::cout << "term1-term2+term3 :" << term1-term2+term3 << std::endl; // } @@ -496,17 +496,17 @@ namespace Dune::GFE // std::cout << "------ print P2-Basis evaluation -----" << std::endl; // for(std::size_t i=0; i<lagrangeLFE_.size(); i++) // { - // std::cout << i << "-th P2-basis function: " << std::endl; + // std::cout << i << "-th P2-basis function: " << std::endl; // printvector(std::cout, basisValues_edge1[i] , "basisValues_edge1[i] ", "--"); // } // for(std::size_t i=0; i<lagrangeLFE_.size(); i++) // { - // std::cout << i << "-th P2-basis function: " << std::endl; + // std::cout << i << "-th P2-basis function: " << std::endl; // printvector(std::cout, basisValues_edge2[i] , "basisValues_edge2[i] ", "--"); // } // for(std::size_t i=0; i<lagrangeLFE_.size(); i++) // { - // std::cout << i << "-th P2-basis function: " << std::endl; + // std::cout << i << "-th P2-basis function: " << std::endl; // printvector(std::cout, basisValues_edge3[i] , "basisValues_edge3[i] ", "--"); // } @@ -538,7 +538,7 @@ namespace Dune::GFE // // std::cout << "cos(geometry.global({0.5,0.5})[0]): " << cos(geometry.global({0.5,0.5})[0]) << std::endl; // // std::cout << "sin(geometry.global({0.0,0.5})[0]): " << sin(geometry.global({0.0,0.5})[0]) << std::endl; // // std::cout << "cos(geometry.global({0.0,0.5})[0]): " << cos(geometry.global({0.0,0.5})[0]) << std::endl; - // // TEST VERTICES + // // TEST VERTICES // // std::cout << "sin(geometry.global({0.0,0.0})[0]): " << sin(geometry.global({0.0,0.0})[0]) << std::endl; // // std::cout << "cos(geometry.global({0.0,0.0})[0]): " << cos(geometry.global({0.0,0.0})[0]) << std::endl; // // std::cout << "sin(geometry.global({1.0,0.0})[0]): " << sin(geometry.global({1.0,0.0})[0]) << std::endl; @@ -550,10 +550,10 @@ namespace Dune::GFE // exit(0); - // #if 0 + // #if 0 /** - * @brief VERSION - 2 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 - * for | II - Beff |^2 and discretize every term individually. + * @brief VERSION - 2 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 + * for | II - Beff |^2 and discretize every term individually. */ // Gauss-Quadrature: const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder); @@ -565,49 +565,49 @@ namespace Dune::GFE { //Get values of the P2-Basis functions on current quadrature point - std::vector<FieldVector<double,1>> basisValues; + std::vector<FieldVector<double,1> > basisValues; lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues); // Get Jacobians of the P2-Basis functions on current quadrature point - std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients; + std::vector<FieldMatrix<double, 1, gridDim> > referenceGradients; lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients); const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position()); const auto integrationElement = geometry.integrationElement(quadPoint.position()); - std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size()); + std::vector<FieldVector<RT, gridDim> > gradients(referenceGradients.size()); for (size_t i = 0; i<gradients.size(); i++) jacobian.mv(referenceGradients[i][0], gradients[i]); - Tensor3<RT,3,2,2> discreteHessian(0); + Tensor3<RT,3,2,2> discreteHessian(0); FieldMatrix<RT, 3, gridDim> discreteGradient(0); for (int k=0; k<3; k++) - for (int l=0; l<gridDim; l++) - for(std::size_t i=0; i<lagrangeLFE_.size(); i++) - { - discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; - discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; - discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; - - } - + for (int l=0; l<gridDim; l++) + for(std::size_t i=0; i<lagrangeLFE_.size(); i++) + { + discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; + discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; + discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; + + } + /** - * @brief print the (three) 2x2 slices of the discrete Hessian (check for symmetry) - */ + * @brief print the (three) 2x2 slices of the discrete Hessian (check for symmetry) + */ FieldMatrix<RT, 2, 2> discreteHessian_slice1(0); FieldMatrix<RT, 2, 2> discreteHessian_slice2(0); FieldMatrix<RT, 2, 2> discreteHessian_slice3(0); for (int i=0; i<2; i++) - for (int l=0; l<gridDim; l++) - { + for (int l=0; l<gridDim; l++) + { discreteHessian_slice1[i][l] = discreteHessian[0][i][l]; discreteHessian_slice2[i][l] = discreteHessian[1][i][l]; discreteHessian_slice3[i][l] = discreteHessian[2][i][l]; - } + } // printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--"); // printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--"); @@ -644,20 +644,20 @@ namespace Dune::GFE FieldMatrix<RT,2,2> secondFF(0); for(size_t m=0; m<2; m++) - for(size_t n=0; n<2; n++) - for(size_t k=0; k<3; k++) - { - secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; - } + for(size_t n=0; n<2; n++) + for(size_t k=0; k<3; k++) + { + secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; + } // To get the right sign: secondFF = -1.0*secondFF; - // substract effective prestrain - // G = G + Beff; + // substract effective prestrain + // G = G + Beff; - //Take symmetric part? + //Take symmetric part? // auto symG = 0.5*(G.transposed() + G); @@ -698,9 +698,9 @@ namespace Dune::GFE for(int k=0; k<3; k++) { // term1 += Qhom[0][0]*pow((2.0*discreteHessian[k][0][0]),2)+ Qhom[0][1]* ... more efficient (TODO) Qhom is symmetric - term1 += Qhom[0][0]*pow(X[k][0],2) + Qhom[0][1]*X[k][1]*X[k][0] + Qhom[0][2]*X[k][2]*X[k][0] - + Qhom[1][0]*X[k][0]*X[k][1] + Qhom[1][1]*pow(X[k][1],2) + Qhom[1][2]*X[k][2]*X[k][1] - + Qhom[2][0]*X[k][0]*X[k][2] + Qhom[2][1]*X[k][1]*X[k][2] + Qhom[2][2]*pow(X[k][2],2); + term1 += Qhom[0][0]*pow(X[k][0],2) + Qhom[0][1]*X[k][1]*X[k][0] + Qhom[0][2]*X[k][2]*X[k][0] + + Qhom[1][0]*X[k][0]*X[k][1] + Qhom[1][1]*pow(X[k][1],2) + Qhom[1][2]*X[k][2]*X[k][1] + + Qhom[2][0]*X[k][0]*X[k][2] + Qhom[2][1]*X[k][1]*X[k][2] + Qhom[2][2]*pow(X[k][2],2); } // term1 = term1 * 0.5 * weight; term1 = term1 * weight; @@ -719,29 +719,29 @@ namespace Dune::GFE // { // term2 += weight * secondFF[i][j] * Beff[i][j]; // } - + FieldVector<RT,3> secondFFCoefficients = matrixToSymCoefficients(secondFF); FieldVector<RT,3> BeffCoefficients = matrixToSymCoefficients(Beff); RT term2 = 0.0; - term2 += Qhom[0][0]*BeffCoefficients[0]*secondFFCoefficients[0] + Qhom[0][1]*BeffCoefficients[1]*secondFFCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*secondFFCoefficients[0] - + Qhom[1][0]*BeffCoefficients[0]*secondFFCoefficients[1] + Qhom[1][1]*BeffCoefficients[1]*secondFFCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*secondFFCoefficients[1] - + Qhom[2][0]*BeffCoefficients[0]*secondFFCoefficients[2] + Qhom[2][1]*BeffCoefficients[1]*secondFFCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*secondFFCoefficients[2]; + term2 += Qhom[0][0]*BeffCoefficients[0]*secondFFCoefficients[0] + Qhom[0][1]*BeffCoefficients[1]*secondFFCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*secondFFCoefficients[0] + + Qhom[1][0]*BeffCoefficients[0]*secondFFCoefficients[1] + Qhom[1][1]*BeffCoefficients[1]*secondFFCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*secondFFCoefficients[1] + + Qhom[2][0]*BeffCoefficients[0]*secondFFCoefficients[2] + Qhom[2][1]*BeffCoefficients[1]*secondFFCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*secondFFCoefficients[2]; term2 = 2.0 * term2 * weight; - // auto term3 = 0.5 * weight* Beff.frobenius_norm2(); + // auto term3 = 0.5 * weight* Beff.frobenius_norm2(); + + RT term3 = 0.0; - RT term3 = 0.0; + term3 += Qhom[0][0]*BeffCoefficients[0]*BeffCoefficients[0] + Qhom[0][1]*BeffCoefficients[1]*BeffCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*BeffCoefficients[0] + + Qhom[1][0]*BeffCoefficients[0]*BeffCoefficients[1] + Qhom[1][1]*BeffCoefficients[1]*BeffCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*BeffCoefficients[1] + + Qhom[2][0]*BeffCoefficients[0]*BeffCoefficients[2] + Qhom[2][1]*BeffCoefficients[1]*BeffCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*BeffCoefficients[2]; - term3 += Qhom[0][0]*BeffCoefficients[0]*BeffCoefficients[0] + Qhom[0][1]*BeffCoefficients[1]*BeffCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*BeffCoefficients[0] - + Qhom[1][0]*BeffCoefficients[0]*BeffCoefficients[1] + Qhom[1][1]*BeffCoefficients[1]*BeffCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*BeffCoefficients[1] - + Qhom[2][0]*BeffCoefficients[0]*BeffCoefficients[2] + Qhom[2][1]*BeffCoefficients[1]*BeffCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*BeffCoefficients[2]; - // term3 = term3 * 0.5 * weight ; term3 = term3 * weight ; @@ -751,7 +751,7 @@ namespace Dune::GFE // std::cout << "term1 - term2 + term3: " << term1 - term2 + term3 << std::endl; // harmonicEnergy += weight * G.frobenius_norm2(); - harmonicEnergy += term1 - term2 + term3; //eigentlich muss man term2 abziehen bei | II - Z | + harmonicEnergy += term1 - term2 + term3; //eigentlich muss man term2 abziehen bei | II - Z | // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl; } @@ -760,8 +760,8 @@ namespace Dune::GFE #if 0 /** - * @brief VERSION - 3 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 - * for | II - Beff |^2 and discretize every term individually. + * @brief VERSION - 3 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 + * for | II - Beff |^2 and discretize every term individually. * *But with |II|^2 instead of |D^2y|^2 */ // Gauss-Quadrature: @@ -774,34 +774,34 @@ namespace Dune::GFE { //Get values of the P2-Basis functions on current quadrature point - std::vector<FieldVector<double,1>> basisValues; + std::vector<FieldVector<double,1> > basisValues; lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues); // Get Jacobians of the P2-Basis functions on current quadrature point - std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients; + std::vector<FieldMatrix<double, 1, gridDim> > referenceGradients; lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients); const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position()); const auto integrationElement = geometry.integrationElement(quadPoint.position()); - std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size()); + std::vector<FieldVector<RT, gridDim> > gradients(referenceGradients.size()); for (size_t i = 0; i<gradients.size(); i++) jacobian.mv(referenceGradients[i][0], gradients[i]); - Tensor3<RT,3,2,2> discreteHessian(0); + Tensor3<RT,3,2,2> discreteHessian(0); FieldMatrix<RT, 3, gridDim> discreteGradient(0); for (int k=0; k<3; k++) - for (int l=0; l<gridDim; l++) - for(std::size_t i=0; i<lagrangeLFE_.size(); i++) - { - discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; - discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; - discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; - - } + for (int l=0; l<gridDim; l++) + for(std::size_t i=0; i<lagrangeLFE_.size(); i++) + { + discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i]; + discreteHessian[k][l][0] += discreteJacobianCoefficients[i][k][l]*gradients[i][0]; + discreteHessian[k][l][1] += discreteJacobianCoefficients[i][k][l]*gradients[i][1]; + + } //compute normal vector (cross product of partial derivatives) @@ -831,22 +831,22 @@ namespace Dune::GFE FieldMatrix<RT,2,2> secondFF(0); for(size_t m=0; m<2; m++) - for(size_t n=0; n<2; n++) - for(size_t k=0; k<3; k++) - { - secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; - //Test: transposed version - // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k]; - // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0]; - // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0]; - // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1]; - // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1]; - } - - // substract effective prestrain - // G = G + Beff; - - //Take symmetric part? + for(size_t n=0; n<2; n++) + for(size_t k=0; k<3; k++) + { + secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m]; + //Test: transposed version + // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k]; + // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0]; + // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0]; + // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1]; + // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1]; + } + + // substract effective prestrain + // G = G + Beff; + + //Take symmetric part? // auto symG = 0.5*(G.transposed() + G); @@ -885,12 +885,12 @@ namespace Dune::GFE RT term2 = 0.0; for(size_t i=0; i<2; i++) - for(size_t j=0; j<2; j++) - { - term2 += weight * secondFF[i][j] * Beff[i][j]; - } + for(size_t j=0; j<2; j++) + { + term2 += weight * secondFF[i][j] * Beff[i][j]; + } - auto term3 = 0.5 * weight* Beff.frobenius_norm2(); + auto term3 = 0.5 * weight* Beff.frobenius_norm2(); // std::cout << "term1: " << term1 << std::endl; // std::cout << "term2: " << term2 << std::endl; @@ -898,7 +898,7 @@ namespace Dune::GFE // std::cout << "term1 - term2 + term3: " << term1 - term2 + term3 << std::endl; // harmonicEnergy += weight * G.frobenius_norm2(); - harmonicEnergy += term1 - term2 + term3; //eigentlich muss man term2 abziehen bei | II - Z | + harmonicEnergy += term1 - term2 + term3; //eigentlich muss man term2 abziehen bei | II - Z | // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl; } @@ -907,8 +907,8 @@ namespace Dune::GFE /** * @brief Compute contribution of the force Term - * - * Integrate the scalar product of the force 'f' + * + * Integrate the scalar product of the force 'f' * with the local deformation function 'localFunction_' * over the current element. */ @@ -918,17 +918,17 @@ namespace Dune::GFE { for (auto&& quadPoint : quadRule) { - auto deformationValue = localFunction_.evaluate(quadPoint.position()); - auto forceValue = localForce_(quadPoint.position()); - // printvector(std::cout, deformationValue.globalCoordinates(), "deformationValue", "--"); - // printvector(std::cout, forceValue, "forceValue", "--"); - // const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position()); - auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position()); - forceTermEnergy += deformationValue.globalCoordinates() * forceValue * weight; - // std::cout << "forceTermEnergy:" << forceTermEnergy << std::endl; + auto deformationValue = localFunction_.evaluate(quadPoint.position()); + auto forceValue = localForce_(quadPoint.position()); + // printvector(std::cout, deformationValue.globalCoordinates(), "deformationValue", "--"); + // printvector(std::cout, forceValue, "forceValue", "--"); + // const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position()); + auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position()); + forceTermEnergy += deformationValue.globalCoordinates() * forceValue * weight; + // std::cout << "forceTermEnergy:" << forceTermEnergy << std::endl; } } - + return harmonicEnergy - forceTermEnergy; } @@ -947,4 +947,4 @@ namespace Dune::GFE }; } // namespace Dune::GFE -#endif \ No newline at end of file +#endif diff --git a/dune/microstructure/matrix_operations.hh b/dune/microstructure/matrix_operations.hh index e99a6112b9dc22746703dbf6a3aae01e7ccc3fb5..0a0e01124c5d3f0b6218e3480724497fa0c994a9 100644 --- a/dune/microstructure/matrix_operations.hh +++ b/dune/microstructure/matrix_operations.hh @@ -3,230 +3,230 @@ namespace MatrixOperations { - using MatrixRT = Dune::FieldMatrix< double, 3, 3>; - using VectorRT = Dune::FieldVector< double, 3>; - - using std::sin; - using std::cos; - - - - static MatrixRT sym (MatrixRT M) { // 1/2 (M^T + M) - MatrixRT ret(0); - for (int i=0; i<3; i++) - { - ret[i][i] = M[i][i]; - for (int j=i+1; j<3; j++) - { - ret[i][j] = 0.5*(M[i][j] + M[j][i]); - ret[j][i] = ret[i][j]; - } - } - return ret; - } - - - static VectorRT crossProduct (VectorRT v, VectorRT w) { // v otimes w - return {v[1]*w[2] - v[2]*w[1], -1*(v[0]*w[2] - v[2]*w[0]), v[0]*w[1] - v[1]*w[0]}; - } - - static MatrixRT rankoneTensorproduct (VectorRT v, VectorRT w) { // v otimes w - return - {{v[0]*w[0], v[1]*w[0], v[2]*w[0]}, - {v[0]*w[1], v[1]*w[1], v[2]*w[1]}, - {v[0]*w[2], v[1]*w[2], v[2]*w[2]}}; - } - - static MatrixRT nematicLiquidCrystal (double p, VectorRT n){ //B = 1/6*p*Id + 1/2*p*(n otimes n) - MatrixRT B(0); - for (int i=0;i<3;i++) - B[i][i]=p/6.0; - MatrixRT n_ot_n = rankoneTensorproduct(n,n); - n_ot_n*=p/2.0; - B += n_ot_n; - return B; - } - - static MatrixRT biotStrainApprox (VectorRT U, VectorRT k, VectorRT e_cs){ //E_h = (U + k x e_cs, 0, 0) - VectorRT k_x_ecs = crossProduct(k, e_cs); - VectorRT U_plus_k_x_ecs = U + k_x_ecs; - VectorRT e_1 = {1, 0, 0}; - return rankoneTensorproduct(U_plus_k_x_ecs, e_1); - } - - - static MatrixRT crossSectionDirectionScaling(double w, MatrixRT M){ - return {{M[0][0], M[0][1], w*M[0][2]}, - {M[1][0], M[1][1], w*M[1][2]}, - {M[2][0], M[2][1], w*M[2][2]} - }; - } - - static double trace (MatrixRT M){ - return M[0][0]+ M[1][1] + M[2][2]; - } - - static double scalarProduct (MatrixRT M1, MatrixRT M2){ - double sum = 0.0; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - sum += M1[i][j] * M2[i][j]; - 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. Choose between 0: x-axis, 1: y-axis, 2: z-axis"); - } - } - - /** - * @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[1][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]} - }; - } - - - /** - * @brief Scale last three columns of stiffness matrix by a factor of 2. - * Inserting this facotr in the stiffness matrix allows to use the - * same Matrix-to-Vector mapping for both the stress and the strain. - * - * @param S Stiffness matrix - */ - static void scaleStiffnessMatrix(Dune::FieldMatrix<double,6,6>& S){ - for(size_t i = 0; i<6; i++) + using MatrixRT = Dune::FieldMatrix< double, 3, 3>; + using VectorRT = Dune::FieldVector< double, 3>; + + using std::sin; + using std::cos; + + + + static MatrixRT sym (MatrixRT M) { // 1/2 (M^T + M) + MatrixRT ret(0); + for (int i=0; i<3; i++) + { + ret[i][i] = M[i][i]; + for (int j=i+1; j<3; j++) + { + ret[i][j] = 0.5*(M[i][j] + M[j][i]); + ret[j][i] = ret[i][j]; + } + } + return ret; + } + + + static VectorRT crossProduct (VectorRT v, VectorRT w) { // v otimes w + return {v[1]*w[2] - v[2]*w[1], -1*(v[0]*w[2] - v[2]*w[0]), v[0]*w[1] - v[1]*w[0]}; + } + + static MatrixRT rankoneTensorproduct (VectorRT v, VectorRT w) { // v otimes w + return + {{v[0]*w[0], v[1]*w[0], v[2]*w[0]}, + {v[0]*w[1], v[1]*w[1], v[2]*w[1]}, + {v[0]*w[2], v[1]*w[2], v[2]*w[2]}}; + } + + static MatrixRT nematicLiquidCrystal (double p, VectorRT n){ //B = 1/6*p*Id + 1/2*p*(n otimes n) + MatrixRT B(0); + for (int i=0; i<3; i++) + B[i][i]=p/6.0; + MatrixRT n_ot_n = rankoneTensorproduct(n,n); + n_ot_n*=p/2.0; + B += n_ot_n; + return B; + } + + static MatrixRT biotStrainApprox (VectorRT U, VectorRT k, VectorRT e_cs){ //E_h = (U + k x e_cs, 0, 0) + VectorRT k_x_ecs = crossProduct(k, e_cs); + VectorRT U_plus_k_x_ecs = U + k_x_ecs; + VectorRT e_1 = {1, 0, 0}; + return rankoneTensorproduct(U_plus_k_x_ecs, e_1); + } + + + static MatrixRT crossSectionDirectionScaling(double w, MatrixRT M){ + return {{M[0][0], M[0][1], w*M[0][2]}, + {M[1][0], M[1][1], w*M[1][2]}, + {M[2][0], M[2][1], w*M[2][2]} + }; + } + + static double trace (MatrixRT M){ + return M[0][0]+ M[1][1] + M[2][2]; + } + + static double scalarProduct (MatrixRT M1, MatrixRT M2){ + double sum = 0.0; + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + sum += M1[i][j] * M2[i][j]; + 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. Choose between 0: x-axis, 1: y-axis, 2: z-axis"); + } + } + + /** + * @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[1][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]} + }; + } + + + /** + * @brief Scale last three columns of stiffness matrix by a factor of 2. + * Inserting this facotr in the stiffness matrix allows to use the + * same Matrix-to-Vector mapping for both the stress and the strain. + * + * @param S Stiffness matrix + */ + static void scaleStiffnessMatrix(Dune::FieldMatrix<double,6,6>& S){ + for(size_t i = 0; i<6; i++) for(size_t j = 3; j<6; j++) { S[i][j] = 2.0*S[i][j]; } - } - - static double linearizedStVenantKirchhoffDensity(double mu, double lambda, MatrixRT E1, MatrixRT E2) // CHANGED - { - auto t1 = 2.0 * mu * sym(E1) + MatrixRT(Dune::ScaledIdentityMatrix<double,3>(lambda * trace(sym(E1)))); - auto tmp1 = scalarProduct(t1,sym(E2)); - return tmp1; - - } - - - - // --- Generalization: Define Quadratic QuadraticForm - static double QuadraticForm(const double mu, const double lambda, const MatrixRT M){ - - auto tmp1 = sym(M); - double tmp2 = tmp1.frobenius_norm(); -// double tmp2 = norm(M); //TEST - return lambda*std::pow(trace(M),2) + 2.0*mu*pow( tmp2 ,2); -// return lambda*std::pow(trace(M),2) + 2*mu*pow( norm( sym(M) ),2); - } + } + + static double linearizedStVenantKirchhoffDensity(double mu, double lambda, MatrixRT E1, MatrixRT E2) // CHANGED + { + auto t1 = 2.0 * mu * sym(E1) + MatrixRT(Dune::ScaledIdentityMatrix<double,3>(lambda * trace(sym(E1)))); + auto tmp1 = scalarProduct(t1,sym(E2)); + return tmp1; + + } + + + + // --- Generalization: Define Quadratic QuadraticForm + static double QuadraticForm(const double mu, const double lambda, const MatrixRT M){ + + auto tmp1 = sym(M); + double tmp2 = tmp1.frobenius_norm(); + // double tmp2 = norm(M); //TEST + return lambda*std::pow(trace(M),2) + 2.0*mu*pow( tmp2 ,2); + // return lambda*std::pow(trace(M),2) + 2*mu*pow( norm( sym(M) ),2); + } + + + + static double generalizedDensity(const double mu, const double lambda, MatrixRT F, MatrixRT G){ + /// Write this whole File as a Class that uses lambda,mu as members ? + + // Define L via Polarization-Identity from QuadratifForm + // <LF,G> := (1/2)*(Q(F+G) - Q(F) - Q(G) ) + return (1.0/2.0)*(QuadraticForm(mu,lambda,F+G) - QuadraticForm(mu,lambda,F) - QuadraticForm(mu,lambda,G) ); + } + + static MatrixRT matrixSqrt(MatrixRT M){ + std::cout << "matrixSqrt not implemented!!!" << std::endl; //implement this + return M; + } + + static double lameMu(double E, double nu){ + return 0.5 * 1.0/(1.0 + nu) * E; + } + + static double lameLambda(double E, double nu){ + return nu/(1.0-2.0*nu) * 1.0/(1.0+nu) * E; + } + + static bool isInRotatedPlane(double phi, double x1, double x2){ + return cos(phi)*x1 + sin(phi)*x2 > 0; + } + - + extern "C" + { - static double generalizedDensity(const double mu, const double lambda, MatrixRT F, MatrixRT G){ - /// Write this whole File as a Class that uses lambda,mu as members ? - - // Define L via Polarization-Identity from QuadratifForm - // <LF,G> := (1/2)*(Q(F+G) - Q(F) - Q(G) ) - return (1.0/2.0)*(QuadraticForm(mu,lambda,F+G) - QuadraticForm(mu,lambda,F) - QuadraticForm(mu,lambda,G) ); + MatrixRT new_sym(MatrixRT M) + { + return sym(M); } - static MatrixRT matrixSqrt(MatrixRT M){ - std::cout << "matrixSqrt not implemented!!!" << std::endl;//implement this - return M; - } - - static double lameMu(double E, double nu){ - return 0.5 * 1.0/(1.0 + nu) * E; - } - - static double lameLambda(double E, double nu){ - return nu/(1.0-2.0*nu) * 1.0/(1.0+nu) * E; - } - - static bool isInRotatedPlane(double phi, double x1, double x2){ - return cos(phi)*x1 + sin(phi)*x2 > 0; - } - - - extern "C" - { - - MatrixRT new_sym(MatrixRT M) - { - return sym(M); - } - - } - - - /** - * @brief This is used to convert FieldMatrices to 'adouble' - * since adouble-type can not be read from ParSet. - * is there a better way? - * - * @tparam Rtype - * @tparam IMatrixType - * @param A - * @param B - */ - template<class Rtype> - static void convertFieldMatrix(auto& A, - auto& B) - { - for(size_t i=0; i<B.N(); i++) - for(size_t j=0; j<B.M(); j++) - B[i][j] = (Rtype)A[i][j]; - - return; - } + } + + + /** + * @brief This is used to convert FieldMatrices to 'adouble' + * since adouble-type can not be read from ParSet. + * is there a better way? + * + * @tparam Rtype + * @tparam IMatrixType + * @param A + * @param B + */ + template<class Rtype> + static void convertFieldMatrix(auto& A, + auto& B) + { + for(size_t i=0; i<B.N(); i++) + for(size_t j=0; j<B.M(); j++) + B[i][j] = (Rtype)A[i][j]; + + return; + } diff --git a/dune/microstructure/microproblem.hh b/dune/microstructure/microproblem.hh index 4ba87eb1d42d634e23e38cc0d5b1d69ac7a8ca6b..621f0ea8b29f282f7d68f88c8a1215c425f407ec 100644 --- a/dune/microstructure/microproblem.hh +++ b/dune/microstructure/microproblem.hh @@ -26,7 +26,7 @@ #include <dune/istl/spqr.hh> #include <dune/istl/preconditioners.hh> #include <dune/istl/io.hh> -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/functions/functionspacebases/interpolate.hh> #include <dune/functions/backends/istlvectorbackend.hh> @@ -41,11 +41,11 @@ #include <dune/functions/gridfunctions/gridviewfunction.hh> #include <dune/microstructure/matrix_operations.hh> -#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> +#include <dune/solvers/solvers/umfpacksolver.hh> // #include <iomanip> // needed when working with relative paths e.g. from python-scripts @@ -53,7 +53,7 @@ // using namespace MatrixOperations; - // method to print types of objects: +// method to print types of objects: // template <class T> // constexpr std::string_view type_name() // { @@ -78,254 +78,254 @@ //-------------------------------------------------------- class MicroProblem { - private: - static const int dim = 3; - using CellGridType = Dune::YaspGrid<dim, Dune::EquidistantOffsetCoordinates<double, dim> >; - using GridView = typename CellGridType::LeafGridView; - // typedef typename Dune::Functions::DefaultGlobalBasis<Dune::Functions::PowerPreBasis<Dune::Functions::BasisFactory::FlatLexicographic, \ - // Dune::Functions::Experimental::TransformedIndexPreBasis<Dune::Functions::LagrangePreBasis<Dune::GridView< \ - // Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, dim> > > >, 1, double>, \ - // Dune::Functions::BasisFactory::Experimental::Impl::PeriodicIndexingTransformation>, dim> > BasisType; - - - using BasisType = typename Dune::Functions::DefaultGlobalBasis<Dune::Functions::PowerPreBasis<Dune::Functions::BasisFactory::FlatLexicographic, \ - Dune::Functions::Experimental::TransformedIndexPreBasis<Dune::Functions::LagrangePreBasis<Dune::GridView< \ - Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, dim> > > >, 1, double>, \ - Dune::Functions::BasisFactory::Experimental::Impl::PeriodicIndexingTransformation>, dim> >; - - using MaterialType = prestrainedMaterial<GridView>; - - - Python::Reference microstructure_; - const Dune::ParameterTree parameterSet_; - const Python::Module module_; - const CellGridType grid_; - const GridView gridView_; - const BasisType basis_; - // Dune::ParameterTree parameterSet_; - // Python::Module module_; - // CellGridType grid_; - // GridView gridView_; - // BasisType basis_; - - - // std::fstream log_; // deprecated: only used to define CorrectorComputer object. - - - // MaterialType material_; - std::shared_ptr<MaterialType> material_; - - // CorrectorComputer<BasisType, MaterialType> correctorComputer_; - std::shared_ptr<CorrectorComputer<BasisType, MaterialType> > correctorComputer_; - EffectiveQuantitiesComputer<BasisType,MaterialType> effectiveQuantitiesComputer_; - - - - public: - - - //Constructor - MicroProblem(const Python::Reference microstructure, - const Dune::ParameterTree& parameterSet, - const Python::Module pyModule) - : microstructure_(microstructure), - parameterSet_(parameterSet), - module_(pyModule), - grid_(createGrid()), - gridView_(grid_.leafGridView()), - basis_(createPeriodicBasis()), - // material_(setupMaterial(gridView_)) - // material_(gridView_,microstructure_,parameterSet_,module_), - material_(std::make_shared<MaterialType>(gridView_,microstructure_,parameterSet_,module_)), - correctorComputer_(std::make_shared<CorrectorComputer<BasisType, MaterialType>>(basis_, material_, parameterSet_)), - // correctorComputer_(basis_, material_, parameterSet_), - effectiveQuantitiesComputer_(correctorComputer_) - // effectiveQuantitiesComputer_(correctorComputer_,material_) // Remove material dependency - {}; - // //Constructor - // MicroProblem(const Dune::ParameterTree& parameterSet, - // Python::Module pyModule) - // : parameterSet_(parameterSet), - // module_(pyModule), - // grid_(createGrid()), - // gridView_(grid_.leafGridView()), - // basis_(createPeriodicBasis()) - // { - // initialSetup(); - // }; - - - // Create a default constructor like this? - // MicroProblem() = default; - - - // MaterialType setupMaterial(const GridView& gridView) const - // { - // return MaterialType(gridView,microstructure_,parameterSet_,module_); - // } - - - - /** - * @brief Infrastructure for handling periodicity. - * Check whether two points are equal on R/Z x R/Z x R - */ - static constexpr auto equivalent = [](const Dune::FieldVector<double,3>& x, const Dune::FieldVector<double,3>& y) +private: + static const int dim = 3; + using CellGridType = Dune::YaspGrid<dim, Dune::EquidistantOffsetCoordinates<double, dim> >; + using GridView = typename CellGridType::LeafGridView; + // typedef typename Dune::Functions::DefaultGlobalBasis<Dune::Functions::PowerPreBasis<Dune::Functions::BasisFactory::FlatLexicographic, \ + // Dune::Functions::Experimental::TransformedIndexPreBasis<Dune::Functions::LagrangePreBasis<Dune::GridView< \ + // Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, dim> > > >, 1, double>, \ + // Dune::Functions::BasisFactory::Experimental::Impl::PeriodicIndexingTransformation>, dim> > BasisType; + + + using BasisType = typename Dune::Functions::DefaultGlobalBasis<Dune::Functions::PowerPreBasis<Dune::Functions::BasisFactory::FlatLexicographic, \ + Dune::Functions::Experimental::TransformedIndexPreBasis<Dune::Functions::LagrangePreBasis<Dune::GridView< \ + Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, dim> > > >, 1, double>, \ + Dune::Functions::BasisFactory::Experimental::Impl::PeriodicIndexingTransformation>, dim> >; + + using MaterialType = prestrainedMaterial<GridView>; + + + Python::Reference microstructure_; + const Dune::ParameterTree parameterSet_; + const Python::Module module_; + const CellGridType grid_; + const GridView gridView_; + const BasisType basis_; + // Dune::ParameterTree parameterSet_; + // Python::Module module_; + // CellGridType grid_; + // GridView gridView_; + // BasisType basis_; + + + // std::fstream log_; // deprecated: only used to define CorrectorComputer object. + + + // MaterialType material_; + std::shared_ptr<MaterialType> material_; + + // CorrectorComputer<BasisType, MaterialType> correctorComputer_; + std::shared_ptr<CorrectorComputer<BasisType, MaterialType> > correctorComputer_; + EffectiveQuantitiesComputer<BasisType,MaterialType> effectiveQuantitiesComputer_; + + + +public: + + + //Constructor + MicroProblem(const Python::Reference microstructure, + const Dune::ParameterTree& parameterSet, + const Python::Module pyModule) + : microstructure_(microstructure), + parameterSet_(parameterSet), + module_(pyModule), + grid_(createGrid()), + gridView_(grid_.leafGridView()), + basis_(createPeriodicBasis()), + // material_(setupMaterial(gridView_)) + // material_(gridView_,microstructure_,parameterSet_,module_), + material_(std::make_shared<MaterialType>(gridView_,microstructure_,parameterSet_,module_)), + correctorComputer_(std::make_shared<CorrectorComputer<BasisType, MaterialType> >(basis_, material_, parameterSet_)), + // correctorComputer_(basis_, material_, parameterSet_), + effectiveQuantitiesComputer_(correctorComputer_) + // effectiveQuantitiesComputer_(correctorComputer_,material_) // Remove material dependency + {}; + // //Constructor + // MicroProblem(const Dune::ParameterTree& parameterSet, + // Python::Module pyModule) + // : parameterSet_(parameterSet), + // module_(pyModule), + // grid_(createGrid()), + // gridView_(grid_.leafGridView()), + // basis_(createPeriodicBasis()) + // { + // initialSetup(); + // }; + + + // Create a default constructor like this? + // MicroProblem() = default; + + + // MaterialType setupMaterial(const GridView& gridView) const + // { + // return MaterialType(gridView,microstructure_,parameterSet_,module_); + // } + + + + /** + * @brief Infrastructure for handling periodicity. + * Check whether two points are equal on R/Z x R/Z x R + */ + static constexpr auto equivalent = [](const Dune::FieldVector<double,3>& x, const Dune::FieldVector<double,3>& y) + { + return ( (Dune::FloatCmp::eq(x[0],y[0]) or Dune::FloatCmp::eq(x[0]+1,y[0]) or Dune::FloatCmp::eq(x[0]-1,y[0])) + and (Dune::FloatCmp::eq(x[1],y[1]) or Dune::FloatCmp::eq(x[1]+1,y[1]) or Dune::FloatCmp::eq(x[1]-1,y[1])) + and (Dune::FloatCmp::eq(x[2],y[2])) + ); + }; + + + /** + * @brief Generate the grid. + * Corrector Problem Domain (-1/2,1/2)^3. + */ + const CellGridType createGrid() const + { + Dune::FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0}); + Dune::FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0}); + int microGridLevel = parameterSet_.get<int>("microGridLevel", 0); + std::array<int, dim> nElements = {(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel)}; + // std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; + std::cout << "Number of Micro Grid-Elements in each direction: " << (int)std::pow(2,microGridLevel) << std::endl; + + return CellGridType(lower,upper,nElements); + } + + const BasisType createPeriodicBasis() const + { + // using namespace Functions::BasisFactory; + Dune::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_)) + for (const auto& v2 : vertices(gridView_)) + if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0))) { - return ( (Dune::FloatCmp::eq(x[0],y[0]) or Dune::FloatCmp::eq(x[0]+1,y[0]) or Dune::FloatCmp::eq(x[0]-1,y[0])) - and (Dune::FloatCmp::eq(x[1],y[1]) or Dune::FloatCmp::eq(x[1]+1,y[1]) or Dune::FloatCmp::eq(x[1]-1,y[1])) - and (Dune::FloatCmp::eq(x[2],y[2])) - ); - }; - - - /** - * @brief Generate the grid. - * Corrector Problem Domain (-1/2,1/2)^3. - */ - const CellGridType createGrid() const - { - Dune::FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0}); - Dune::FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0}); - int microGridLevel = parameterSet_.get<int>("microGridLevel", 0); - std::array<int, dim> nElements = {(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel)}; - // std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; - std::cout << "Number of Micro Grid-Elements in each direction: " << (int)std::pow(2,microGridLevel) << std::endl; - - return CellGridType(lower,upper,nElements); + periodicIndices.unifyIndexPair({gridView_.indexSet().index(v1)}, {gridView_.indexSet().index(v2)}); } - const BasisType createPeriodicBasis() const - { - // using namespace Functions::BasisFactory; - Dune::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_)) - for (const auto& v2 : vertices(gridView_)) - if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0))) - { - periodicIndices.unifyIndexPair({gridView_.indexSet().index(v1)}, {gridView_.indexSet().index(v2)}); - } - - return makeBasis(gridView_, - power<dim>( - Dune::Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), - flatLexicographic() - )); - } + return makeBasis(gridView_, + power<dim>( + Dune::Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), + flatLexicographic() + )); + } - void updateMicrostructure(Python::Reference microstructure) - { - microstructure_ = microstructure; + void updateMicrostructure(Python::Reference microstructure) + { + microstructure_ = microstructure; - // material_.updateMicrostructure(microstructure_); - material_->updateMicrostructure(microstructure_); - correctorComputer_->updateMaterial(material_); - effectiveQuantitiesComputer_.updateCorrectorComputer(correctorComputer_); - } + // material_.updateMicrostructure(microstructure_); + material_->updateMicrostructure(microstructure_); + correctorComputer_->updateMaterial(material_); + effectiveQuantitiesComputer_.updateCorrectorComputer(correctorComputer_); + } - Python::Reference getMicrostructure() - { - return microstructure_; - } + Python::Reference getMicrostructure() + { + return microstructure_; + } - // template<class Btype,class Qtype> - // void getEffectiveQuantities(Btype& B, Qtype& Q, int count = 0) - template<class Btype,class Qtype> - void getEffectiveQuantities(Btype& B, Qtype& Q) - { - Dune::Timer microProblemTimer; - // std::cout << "getting effective quantities.. " << std::endl; + // template<class Btype,class Qtype> + // void getEffectiveQuantities(Btype& B, Qtype& Q, int count = 0) + template<class Btype,class Qtype> + void getEffectiveQuantities(Btype& B, Qtype& Q) + { + Dune::Timer microProblemTimer; + // std::cout << "getting effective quantities.. " << std::endl; - // --- Get scale ratio - // double gamma = parameterSet_.get<double>("gamma",1.0); - double gamma; - microstructure_.get("gamma").toC<double>(gamma); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - std::cout << "Microstructure scale ratio (gamma) set to : " << gamma << std::endl; + // --- Get scale ratio + // double gamma = parameterSet_.get<double>("gamma",1.0); + double gamma; + microstructure_.get("gamma").toC<double>(gamma); + if (parameterSet_.get<bool>("printMicroOutput ", false)) + std::cout << "Microstructure scale ratio (gamma) set to : " << gamma << std::endl; - // /** - // * @brief Create Log (Remove later) - // * - // */ - // std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); - // std::string outputPath = parameterSet_.get("resultPath", "../../outputs") ; - // //--- setup Log-File - // std::fstream log; - // log.open(outputPath + "/" + baseName + "_log.txt" ,std::ios::out); + // /** + // * @brief Create Log (Remove later) + // * + // */ + // std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); + // std::string outputPath = parameterSet_.get("resultPath", "../../outputs") ; + // //--- setup Log-File + // std::fstream log; + // log.open(outputPath + "/" + baseName + "_log.txt" ,std::ios::out); - // std::cout << "log done" << std::endl; - - // // Create prestrained material object - // auto material = prestrainedMaterial(basis_.gridView(),microstructure_,parameterSet_,module_); + // std::cout << "log done" << std::endl; + // // Create prestrained material object + // auto material = prestrainedMaterial(basis_.gridView(),microstructure_,parameterSet_,module_); - // std::cout << "type_name<decltype(material_)>():" << type_name<decltype(material_)>() << std::endl; - // std::cout << "type_name<decltype(material)>():" << type_name<decltype(material)>() << std::endl; + // std::cout << "type_name<decltype(material_)>():" << type_name<decltype(material_)>() << std::endl; + // std::cout << "type_name<decltype(material)>():" << type_name<decltype(material)>() << std::endl; - // // std::cout << "TEST-VTK write.." << std::endl; - // material.writeVTKMaterialFunctions(parameterSet_.get<int>("microGridLevel", 0)); - // std::cout << "Part1 works." << std::endl; + // // std::cout << "TEST-VTK write.." << std::endl; + // material.writeVTKMaterialFunctions(parameterSet_.get<int>("microGridLevel", 0)); + // std::cout << "Part1 works." << std::endl; - if (parameterSet_.get<bool>("write_materialFunctions", false)) - material_->writeVTKMaterialFunctions(parameterSet_.get<int>("microGridLevel", 0)); - // exit(0); + if (parameterSet_.get<bool>("write_materialFunctions", false)) + material_->writeVTKMaterialFunctions(parameterSet_.get<int>("microGridLevel", 0)); - // std::cout << "Material setup done" << std::endl; + // exit(0); - // // Compute Correctors - // auto correctorComputer = CorrectorComputer(basis_, material, log, parameterSet_); - // #if 0 + // std::cout << "Material setup done" << std::endl; - // std::cout << "Starting Corrector assembly" << std::endl; - correctorComputer_->assemble(); - // std::cout << "Starting Corrector solve..." << std::endl; - correctorComputer_->solve(); + // // Compute Correctors + // auto correctorComputer = CorrectorComputer(basis_, material, log, parameterSet_); + // #if 0 + // std::cout << "Starting Corrector assembly" << std::endl; + correctorComputer_->assemble(); + // std::cout << "Starting Corrector solve..." << std::endl; + correctorComputer_->solve(); - // std::cout << "Corrector done" << std::endl; - // //--- Compute effective quantities - // auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material); - effectiveQuantitiesComputer_.computeEffectiveQuantities(); + // std::cout << "Corrector done" << std::endl; + // //--- Compute effective quantities + // auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material); + effectiveQuantitiesComputer_.computeEffectiveQuantities(); - // std::cout << "effective Quantities done" << std::endl; - // //--- Get effective quantities - auto Beffvec = effectiveQuantitiesComputer_.getBeff(); - // // convert CoefficientVector to matrix - auto Beff = CoefficientsToSymMatrix(Beffvec); - Q = effectiveQuantitiesComputer_.getQeff(); - B = CoefficientsToSymMatrix(Beffvec); + // std::cout << "effective Quantities done" << std::endl; + // //--- Get effective quantities + auto Beffvec = effectiveQuantitiesComputer_.getBeff(); + // // convert CoefficientVector to matrix + auto Beff = CoefficientsToSymMatrix(Beffvec); + Q = effectiveQuantitiesComputer_.getQeff(); + B = CoefficientsToSymMatrix(Beffvec); - if (parameterSet_.get<bool>("printMicroOutput ", false)) - { - printmatrix(std::cout, Q, "Matrix Qeff", "--"); - printmatrix(std::cout, B, "Beff", "--"); - } - std::cout << "Micro-Problem took " << microProblemTimer.elapsed() << " seconds." << std::endl; + if (parameterSet_.get<bool>("printMicroOutput ", false)) + { + printmatrix(std::cout, Q, "Matrix Qeff", "--"); + printmatrix(std::cout, B, "Beff", "--"); + } - // #endif + std::cout << "Micro-Problem took " << microProblemTimer.elapsed() << " seconds." << std::endl; - // exit(0); - } + // #endif + + // exit(0); + } }; -#endif \ No newline at end of file +#endif diff --git a/dune/microstructure/prestrainedMaterial.hh b/dune/microstructure/prestrainedMaterial.hh index 008952bde46cf19fef09e092a8f29c8e60d01ab4..2e2f5460ff3883d5ca7048c1880b1f6c181fc2fb 100644 --- a/dune/microstructure/prestrainedMaterial.hh +++ b/dune/microstructure/prestrainedMaterial.hh @@ -37,13 +37,13 @@ using std::make_shared; * @brief The 'prestrainedMaterial' class descripes the LOCAL microstructure. * It stores all the necessary information to define the local Cell-problem. * This includes: - * + * * Indicatorfunction, #Phases, Prestrain, elasticity/compliance tensors ,scale-ratio 'gamma' - * + * */ -//-------------------------------------------------------- -template <class GridView> +//-------------------------------------------------------- +template <class GridView> class prestrainedMaterial { @@ -56,16 +56,16 @@ public: 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 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&) >; using MatrixPhase = std::function< MatrixRT(const int&) >; - using IndicatorGridViewFunctionType = GridViewFunction<int(const Domain&), GridView>; - using LocalIndicatorFunctionType = LocalFunction<int(const Domain&), typename GridViewEntitySet<GridView, 0>::Element >; + using IndicatorGridViewFunctionType = GridViewFunction<int (const Domain&), GridView>; + using LocalIndicatorFunctionType = LocalFunction<int (const Domain&), typename GridViewEntitySet<GridView, 0>::Element >; // const GridView& gridView_; @@ -91,169 +91,169 @@ public: IndicatorGridViewFunctionType indicatorFunctionGVF_; LocalIndicatorFunctionType localIndicatorFunction_; - double gamma_; + double gamma_; -public: - prestrainedMaterial(const GridView& gridView, - Python::Reference microstructure, - const Dune::ParameterTree& parameterSet, - const Python::Module pyModule) - : gridView_(gridView), - microstructure_(microstructure), - parameterSet_(parameterSet), - module_(pyModule) - { - setup(); - } - ~prestrainedMaterial(){std::cout << "prestrainedMaterial object destroyed!" << std::endl;}; - - // prestrainedMaterial() = default; - - //copy constructor - prestrainedMaterial(const prestrainedMaterial& that) = default; - - // Copy assignment operator - // prestrainedMaterial& operator=(prestrainedMaterial const& that) - // { - // gridView_ = that.gridView_; - // parameterSet_ = that.parameterSet_; - // L_ = that.L_; - // prestrain_ = that.prestrain_; - // module_ = that.module_; - // microstructure_ = that.microstructure_; - - // return *this; - // } - - - void updateMicrostructure(const Python::Reference microstructure) +public: + prestrainedMaterial(const GridView& gridView, + Python::Reference microstructure, + const Dune::ParameterTree& parameterSet, + const Python::Module pyModule) + : gridView_(gridView), + microstructure_(microstructure), + parameterSet_(parameterSet), + module_(pyModule) { - // std::cout << "updateMicrostrucrue of prestrainedMaterial" << std::endl; - microstructure_ = microstructure; + setup(); } + ~prestrainedMaterial(){std::cout << "prestrainedMaterial object destroyed!" << std::endl;}; + // prestrainedMaterial() = default; - void updateGamma(const double gamma) - { - gamma_ = gamma; - } + //copy constructor + prestrainedMaterial(const prestrainedMaterial& that) = default; + // Copy assignment operator + // prestrainedMaterial& operator=(prestrainedMaterial const& that) + // { + // gridView_ = that.gridView_; + // parameterSet_ = that.parameterSet_; + // L_ = that.L_; + // prestrain_ = that.prestrain_; + // module_ = that.module_; + // microstructure_ = that.microstructure_; -/** - * @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 phase material phase - * @return Func2Tensor - */ -Func2Tensor setupPrestrainPhase(const int phase){ - - // auto prestrain = Python::make_function<MatrixRT>(module_.get("prestrain_phase" + std::to_string(phase))); - auto prestrain = Python::make_function<MatrixRT>(Python::Callable(microstructure_.get("prestrain_phase" + std::to_string(phase)))); + // return *this; + // } - //TODO... - int axis = 0; - double angle = 0; - try + void updateMicrostructure(const Python::Reference microstructure) { - // module_.get("phase" + std::to_string(phase) + "_axis").toC<int>(axis); - // module_.get("phase" + std::to_string(phase) + "_angle").toC<double>(angle); - axis = parameterSet_.get<int>("phase" + std::to_string(phase) + "_axis", 0); - angle = parameterSet_.get<double>("phase" + std::to_string(phase) + "_angle", 0); + // std::cout << "updateMicrostrucrue of prestrainedMaterial" << std::endl; + microstructure_ = microstructure; } - catch(Dune::Exception&) + + + void updateGamma(const double gamma) { - //default frame is used. + gamma_ = gamma; } + + /** - * @brief (optional) Tramsform prestrain to the correct frame. + * @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 phase material phase + * @return Func2Tensor */ - 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()); }; + Func2Tensor setupPrestrainPhase(const int phase){ + + // auto prestrain = Python::make_function<MatrixRT>(module_.get("prestrain_phase" + std::to_string(phase))); + auto prestrain = Python::make_function<MatrixRT>(Python::Callable(microstructure_.get("prestrain_phase" + std::to_string(phase)))); - return f; + //TODO... + + 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); + axis = parameterSet_.get<int>("phase" + std::to_string(phase) + "_axis", 0); + angle = parameterSet_.get<double>("phase" + std::to_string(phase) + "_angle", 0); + } + 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; } - 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 int phase) -{ - std::string phaseType; + // Dune::FieldMatrix<double,6,6> setupPhase(const std::string phaseType, Python::Module module, int phase) + Dune::FieldMatrix<double,6,6> setupPhase(const int phase) + { + std::string phaseType; - // phaseType = parameterSet_.get<std::string>("phase" + std::to_string(phase) + "_type"); - microstructure_.get("phase" + std::to_string(phase) + "_type").toC<std::string>(phaseType); + // phaseType = parameterSet_.get<std::string>("phase" + std::to_string(phase) + "_type"); + microstructure_.get("phase" + std::to_string(phase) + "_type").toC<std::string>(phaseType); - std::cout << "Setup phase "<< phase << " as " << phaseType << " material." << std::endl; + std::cout << "Setup phase "<< phase << " as " << phaseType << " material." << std::endl; - if(phaseType == "isotropic") - { + if(phaseType == "isotropic") + { Dune::FieldVector<double,2> materialParameters(0); // module_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,2>>(materialParameters); - microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,2>>(materialParameters); + microstructure_.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]); - } + } - /** - * @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; + /** + * @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 - { - // axis = parameterSet_.get<int>("phase" + std::to_string(phase) + "_axis", 0); - // angle = parameterSet_.get<double>("phase" + std::to_string(phase) + "_angle", 0); - microstructure_.get("phase" + std::to_string(phase) + "_axis").toC<int>(axis); - microstructure_.get("phase" + std::to_string(phase) + "_angle").toC<double>(angle); - } - catch(Dune::Exception& e) - { - std::cout << "(Could not read rotation axis & angle for material phase) " << phase << ": - Canonical Frame (default) is used." << std::endl; - } + try + { + // axis = parameterSet_.get<int>("phase" + std::to_string(phase) + "_axis", 0); + // angle = parameterSet_.get<double>("phase" + std::to_string(phase) + "_angle", 0); + microstructure_.get("phase" + std::to_string(phase) + "_axis").toC<int>(axis); + microstructure_.get("phase" + std::to_string(phase) + "_angle").toC<double>(angle); + } + catch(Dune::Exception& e) + { + std::cout << "(Could not read rotation axis & angle for material phase) " << phase << ": - Canonical Frame (default) is used." << std::endl; + } - if(phaseType == "orthotropic") - { + if(phaseType == "orthotropic") + { Dune::FieldVector<double,9> materialParameters(0); // module_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9>>(materialParameters); - microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9>>(materialParameters); + microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9> >(materialParameters); return orthotropic(axis,angle,materialParameters); - } - if(phaseType == "transversely_isotropic") - { + } + if(phaseType == "transversely_isotropic") + { Dune::FieldVector<double,5> materialParameters(0); // module_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,5>>(materialParameters); - microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,5>>(materialParameters); + microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,5> >(materialParameters); return transversely_isotropic(axis,angle,materialParameters); - } - if(phaseType == "general_anisotropic") - { + } + if(phaseType == "general_anisotropic") + { Dune::FieldMatrix<double,6,6> materialParameters(0); //compliance matric // module_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6>>(materialParameters); - microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6>>(materialParameters); + microstructure_.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6> >(materialParameters); return general_anisotropic(axis,angle,materialParameters); + } + else + DUNE_THROW(Dune::Exception, " Unknown material class for phase " + std::to_string(phase)); } - else - DUNE_THROW(Dune::Exception, " Unknown material class for phase " + std::to_string(phase)); -} /** * @brief Setup method that determines the correct stiffness-matrix (constitutive law) - * for each material phase separately. - * + * for each material phase separately. + * */ void setup() { @@ -269,7 +269,7 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) localIndicatorFunction_ = localFunction(indicatorFunctionGVF_); int phases; - // phases = parameterSet_.get<int>("Phases"); + // phases = parameterSet_.get<int>("Phases"); microstructure_.get("phases").toC<int>(phases); std::cout << "---- Starting material setup... (Number of Phases: "<< phases << ") " << std::endl; @@ -292,13 +292,13 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) /** \brief Isotropic stiffness matrix in Voigt notation but scaled by a factor of 2 in the last three columns. */ 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 } - }; + 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 } + }; } //------------------------------------------------------------------------------- @@ -308,74 +308,74 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) * 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 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 - ) + ) { - 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]; - - std::string axis_string; - switch (axis) - { - case 0: - axis_string = "x - axis"; - break; - case 1: - axis_string = "y - axis"; - break; - case 2: - axis_string = "z - axis"; - break; - default: break; - } - - // 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_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:", "--"); - - // invert Compliance matrix to obtain elasticity/stiffness matrix - Compliance.invert(); - // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); - scaleStiffnessMatrix(Compliance); - // printmatrix(std::cout, Compliance, "Stiffness Tensor scaled", "--"); - // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); - return Compliance; + 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]; + + std::string axis_string; + switch (axis) + { + case 0 : + axis_string = "x - axis"; + break; + case 1 : + axis_string = "y - axis"; + break; + case 2 : + axis_string = "z - axis"; + break; + default : break; + } + + // 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_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:", "--"); + + // invert Compliance matrix to obtain elasticity/stiffness matrix + Compliance.invert(); + // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); + scaleStiffnessMatrix(Compliance); + // printmatrix(std::cout, Compliance, "Stiffness Tensor scaled", "--"); + // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); + return Compliance; } //------------------------------------------------------------------------------- @@ -383,124 +383,124 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) * @brief Definition of transversely isotropic elasticity tensor (in Voigt notation) * (see https://en.wikipedia.org/wiki/Poisson%27s_ratio) * @param axis rotate material frame around axis - * @param angle rotation angle + * @param angle rotation angle * @param p elastic constants: {E1,E2,G12,nu12,nu23} * @return Stiffness matrix */ Dune::FieldMatrix<double,6,6> transversely_isotropic(const int& axis, - const double& angle, - const Dune::FieldVector<double,5>& p - ) + const double& angle, + const Dune::FieldVector<double,5>& p + ) { // (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 - - std::string axis_string; - switch (axis) - { - case 0: - axis_string = "x - axis"; - break; - case 1: - axis_string = "y - axis"; - break; - case 2: - axis_string = "z - axis"; - break; - default: break; - } - - //---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()); - } - - printmatrix(std::cout, Compliance, "Compliance matrix used:", "--"); - - // invert Compliance matrix to obtain elasticity/stiffness matrix - Compliance.invert(); - // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); - - scaleStiffnessMatrix(Compliance); - - return Compliance; + 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 + + std::string axis_string; + switch (axis) + { + case 0 : + axis_string = "x - axis"; + break; + case 1 : + axis_string = "y - axis"; + break; + case 2 : + axis_string = "z - axis"; + break; + default : break; + } + + //---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()); + } + + printmatrix(std::cout, Compliance, "Compliance matrix used:", "--"); + + // invert Compliance matrix to obtain elasticity/stiffness matrix + Compliance.invert(); + // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); + + scaleStiffnessMatrix(Compliance); + + return Compliance; } //------------------------------------------------------------------------------- /** * @brief Definition of general anisotropic elasticity tensor (in Voigt notation) - * + * * @param axis rotate material frame around axis - * @param angle rotation angle + * @param angle rotation angle * @param Compliance Compliance matrix * @return Stiffness 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"; - break; - case 1: - axis_string = "y - axis"; - break; - case 2: - axis_string = "z - axis"; - break; - 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:", "--"); - - - // invert Compliance matrix to obtain elasticity/stiffness matrix - Compliance.invert(); - // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); - - scaleStiffnessMatrix(Compliance); - - return Compliance; + std::string axis_string; + switch (axis) + { + case 0 : + axis_string = "x - axis"; + break; + case 1 : + axis_string = "y - axis"; + break; + case 2 : + axis_string = "z - axis"; + break; + 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:", "--"); + + + // invert Compliance matrix to obtain elasticity/stiffness matrix + Compliance.invert(); + // printmatrix(std::cout, Compliance, "Stiffness Tensor", "--"); + + scaleStiffnessMatrix(Compliance); + + return Compliance; } //------------------------------------------------------------------------------- @@ -515,7 +515,7 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) } - MatrixRT prestrain(const int& phase,const Domain& x) const + MatrixRT prestrain(const int& phase,const Domain& x) const { return prestrain_[phase-1](x); } @@ -527,21 +527,21 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) } - /////////////////////////////// - // Getter - /////////////////////////////// - Dune::ParameterTree getParameterSet() const {return parameterSet_;} - std::vector<VoigtMatrix<double,3>> getElasticityTensor() const {return L_;} + /////////////////////////////// + // Getter + /////////////////////////////// + Dune::ParameterTree getParameterSet() const {return parameterSet_;} + std::vector<VoigtMatrix<double,3> > getElasticityTensor() const {return L_;} - MatrixPhase getPrestrainFunction() const {return prestrain_;} + MatrixPhase getPrestrainFunction() const {return prestrain_;} - auto getLocalIndicatorFunction() const {return localIndicatorFunction_;} //get as localFunction - auto getIndicatorFunctionGVF() const {return indicatorFunctionGVF_;} //get as GridViewFunction - auto getIndicatorFunction() const {return indicatorFunction_;} + auto getLocalIndicatorFunction() const {return localIndicatorFunction_;} //get as localFunction + auto getIndicatorFunctionGVF() const {return indicatorFunctionGVF_;} //get as GridViewFunction + auto getIndicatorFunction() const {return indicatorFunction_;} - auto getGamma() const {return gamma_;} + auto getGamma() const {return gamma_;} /////////////////////////////// @@ -551,53 +551,53 @@ Dune::FieldMatrix<double,6,6> setupPhase(const int phase) /** * @brief Write material indicator function as a grid function to VTK. * The Writer uses piecewise constant (P0) interpolation - * + * * @param level GridLevel */ // void writeVTKMaterialFunctions(const int level, double vtkIndex = 1) const void writeVTKMaterialFunctions(const int level) const { - // std::string outputPath = parameterSet_.get("outputPath", "../../outputs"); - std::string resultPath = parameterSet_.get("resultPath", "../../outputs"); - std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); + // std::string outputPath = parameterSet_.get("outputPath", "../../outputs"); + std::string resultPath = parameterSet_.get("resultPath", "../../outputs"); + std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); + + int subsamplingRefinement = parameterSet_.get<int>("MaterialSubsamplingRefinement", 2); + + Dune::SubsamplingVTKWriter<GridView> MaterialVtkWriter(gridView_, Dune::refinementLevels(subsamplingRefinement)); - int subsamplingRefinement = parameterSet_.get<int>("MaterialSubsamplingRefinement", 2); + MaterialVtkWriter.addCellData( + indicatorFunction_, + Dune::VTK::FieldInfo("materialIndicatorFunction_", Dune::VTK::FieldInfo::Type::scalar, 1)); - Dune::SubsamplingVTKWriter<GridView> MaterialVtkWriter(gridView_, Dune::refinementLevels(subsamplingRefinement)); - - MaterialVtkWriter.addCellData( - indicatorFunction_, - Dune::VTK::FieldInfo("materialIndicatorFunction_", Dune::VTK::FieldInfo::Type::scalar, 1)); + MaterialVtkWriter.write(resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) ); + std::cout << "wrote data to file:" + resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) << std::endl; - MaterialVtkWriter.write(resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) ); - std::cout << "wrote data to file:" + resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) << std::endl; - - //-- Version using the Dune::VTKSequenceWriter - // std::shared_ptr<Dune::SubsamplingVTKWriter<GridView> > MaterialVtkWriter = std::make_shared<Dune::SubsamplingVTKWriter<GridView>>(gridView_, Dune::refinementLevels(subsamplingRefinement)); + //-- Version using the Dune::VTKSequenceWriter + // std::shared_ptr<Dune::SubsamplingVTKWriter<GridView> > MaterialVtkWriter = std::make_shared<Dune::SubsamplingVTKWriter<GridView>>(gridView_, Dune::refinementLevels(subsamplingRefinement)); - // MaterialVtkWriter->addCellData(indicatorFunction_, - // Dune::VTK::FieldInfo("materialIndicatorFunction_", Dune::VTK::FieldInfo::Type::scalar, 1)); + // MaterialVtkWriter->addCellData(indicatorFunction_, + // Dune::VTK::FieldInfo("materialIndicatorFunction_", Dune::VTK::FieldInfo::Type::scalar, 1)); - // Dune::VTKSequenceWriter<GridView> SequenceMaterialVTK(MaterialVtkWriter, resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level)); - // SequenceMaterialVTK.write(vtkIndex); - // std::cout << "wrote data to file:" + resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) + "-" + std::to_string(vtkIndex) << std::endl; + // Dune::VTKSequenceWriter<GridView> SequenceMaterialVTK(MaterialVtkWriter, resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level)); + // SequenceMaterialVTK.write(vtkIndex); + // std::cout << "wrote data to file:" + resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) + "-" + std::to_string(vtkIndex) << std::endl; - //--Version using dune-vtk - // Dune::Vtk::DiscontinuousDataCollector<GridView> discontinuousDataCollector(gridView_); - // Dune::Vtk::YaspDataCollector<GridView, 4> yaspDataCollector(gridView_); - // Dune::Vtk::LagrangeDataCollector<GridView, 4> lagrangeDataCollector(gridView_); - // Dune::Vtk::UnstructuredGridWriter writer(lagrangeDataCollector, Dune::Vtk::FormatTypes::ASCII, Dune::Vtk::DataTypes::FLOAT32); - // // Dune::Vtk::UnstructuredGridWriter writer(discontinuousDataCollector, Dune::Vtk::FormatTypes::ASCII, Dune::Vtk::DataTypes::FLOAT32); + //--Version using dune-vtk + // Dune::Vtk::DiscontinuousDataCollector<GridView> discontinuousDataCollector(gridView_); + // Dune::Vtk::YaspDataCollector<GridView, 4> yaspDataCollector(gridView_); + // Dune::Vtk::LagrangeDataCollector<GridView, 4> lagrangeDataCollector(gridView_); + // Dune::Vtk::UnstructuredGridWriter writer(lagrangeDataCollector, Dune::Vtk::FormatTypes::ASCII, Dune::Vtk::DataTypes::FLOAT32); + // // Dune::Vtk::UnstructuredGridWriter writer(discontinuousDataCollector, Dune::Vtk::FormatTypes::ASCII, Dune::Vtk::DataTypes::FLOAT32); - // auto f2 = Dune::Functions::makeAnalyticGridViewFunction(indicatorFunction_ ,gridView_); - // // writer.addPointData(f2 , "IndicatorFunction"); - // writer.addCellData(f2 , "IndicatorFunction"); - // writer.write(resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) + "_DuneVTK"); - return; + // auto f2 = Dune::Functions::makeAnalyticGridViewFunction(indicatorFunction_ ,gridView_); + // // writer.addPointData(f2 , "IndicatorFunction"); + // writer.addCellData(f2 , "IndicatorFunction"); + // writer.write(resultPath + "/" + baseName + "_MaterialFunction-level"+ std::to_string(level) + "_DuneVTK"); + return; }; }; -#endif \ No newline at end of file +#endif diff --git a/dune/microstructure/voigthelper.hh b/dune/microstructure/voigthelper.hh index 5058f710ec2b21a535b8da7f51aec7082d498646..a3ed64d17e4f1478c57b0eca7539c18a20223c56 100644 --- a/dune/microstructure/voigthelper.hh +++ b/dune/microstructure/voigthelper.hh @@ -17,12 +17,12 @@ using VoigtMatrix = Dune::FieldMatrix<T,dim*(dim+1)/2,dim*(dim+1)/2>; /** - * @brief Voigt-notation(https://de.wikipedia.org/wiki/Voigtsche_Notation) distinguishes + * @brief Voigt-notation(https://de.wikipedia.org/wiki/Voigtsche_Notation) distinguishes * in the transformation from Matrix to Vector between stresses and strains. The transformation - * for strains features an additional factor 2 for the non-diagonal entries. In order to avoid + * for strains features an additional factor 2 for the non-diagonal entries. In order to avoid * the use of different data structures for both stresses & strains we use the same Matrix-to-Vector - * mapping ('matrixToVoigt') and incorporate the factors in suitable places. namely: - * - The Stiffness matrix of the constitutive relation get scaled by a factor of 2 in the last three columns + * mapping ('matrixToVoigt') and incorporate the factors in suitable places. namely: + * - The Stiffness matrix of the constitutive relation get scaled by a factor of 2 in the last three columns * - The 'voigtScalarProduct' scales the lase three products by a factor of 2 */ diff --git a/experiment/macro-problem/L-clamped-Plate.py b/experiment/macro-problem/L-clamped-Plate.py index c48aa2dc9ab9f2710a2d786bbd01496ef86289f3..44bffbef77a9f4227cbe98a93ad863fa58b067ba 100644 --- a/experiment/macro-problem/L-clamped-Plate.py +++ b/experiment/macro-problem/L-clamped-Plate.py @@ -25,15 +25,15 @@ parameterSet.baseName= 'L-clamped-Plate' ############################################# # Grid parameters ############################################# -nX=8 -nY=8 +nX=1 +nY=1 parameterSet.structuredGrid = 'simplex' parameterSet.lower = '0 0' parameterSet.upper = '4 4' parameterSet.elements = str(nX)+' '+ str(nY) -parameterSet.macroGridLevel = 1 +parameterSet.macroGridLevel = 3 ############################################# # Options ############################################# @@ -47,6 +47,8 @@ parameterSet.conforming_DiscreteJacobian = 0 ############################################# # Solver parameters ############################################# +# Choose solver: "RNHM" (Default:Riemannian Newton with Hessian modification), "RiemannianTR" (Riemannain Trust-region method) +parameterSet.Solver = "RNHM" # Tolerance of the multigrid solver parameterSet.tolerance = 1e-12 # Maximum number of multigrid iterations @@ -99,8 +101,8 @@ def dirichlet_indicator(x) : #boundary-values/derivative function -def boundaryValues(x): - return [x[0], x[1], 0] +# def boundaryValues(x): +# return [x[0], x[1], 0] # def boundaryValuesDerivative(x): diff --git a/src/Cell-Problem.cc b/src/Cell-Problem.cc index 68946e5526256a437a2ce22f5a1b3d168e144d4b..9e7670004e88063f3251e53eafa9ec5605eea0d9 100644 --- a/src/Cell-Problem.cc +++ b/src/Cell-Problem.cc @@ -12,7 +12,7 @@ #include <dune/common/float_cmp.hh> #include <dune/common/math.hh> #include <dune/common/fvector.hh> -#include <dune/common/fmatrix.hh> +#include <dune/common/fmatrix.hh> #include <dune/geometry/quadraturerules.hh> @@ -29,7 +29,7 @@ #include <dune/istl/spqr.hh> #include <dune/istl/preconditioners.hh> #include <dune/istl/io.hh> -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/functions/functionspacebases/interpolate.hh> #include <dune/functions/backends/istlvectorbackend.hh> @@ -45,11 +45,11 @@ #include <dune/fufem/dunepython.hh> #include <dune/microstructure/matrix_operations.hh> -#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/solvers/solvers/umfpacksolver.hh> //TEST #include <any> #include <variant> @@ -60,7 +60,7 @@ using namespace Dune; using namespace MatrixOperations; -using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3>>::LeafGridView; +using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3> >::LeafGridView; ////////////////////////////////////////////////////////////////////// // Helper functions for Table-Output @@ -68,28 +68,28 @@ using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3> /*! Center-aligns string within a field of width w. Pads with blank spaces to enforce alignment. */ std::string center(const std::string s, const int w) { - std::stringstream ss, spaces; - int padding = w - s.size(); // count excess room to pad - for(int i=0; i<padding/2; ++i) - spaces << " "; - ss << spaces.str() << s << spaces.str(); // format with padding - if(padding>0 && padding%2!=0) // if odd #, add 1 space - ss << " "; - return ss.str(); + std::stringstream ss, spaces; + int padding = w - s.size(); // count excess room to pad + for(int i=0; i<padding/2; ++i) + spaces << " "; + ss << spaces.str() << s << spaces.str(); // format with padding + if(padding>0 && padding%2!=0) // if odd #, add 1 space + ss << " "; + return ss.str(); } /* Convert double to string with specified number of places after the decimal and left padding. */ template<class type> std::string prd(const type x, const int decDigits, const int width) { - std::stringstream ss; -// ss << std::fixed << std::right; - ss << std::scientific << std::right; // Use scientific Output! - ss.fill(' '); // fill space around displayed # - ss.width(width); // set width around displayed # - ss.precision(decDigits); // set # places after decimal - ss << x; - return ss.str(); + std::stringstream ss; + // ss << std::fixed << std::right; + ss << std::scientific << std::right; // Use scientific Output! + ss.fill(' '); // fill space around displayed # + ss.width(width); // set width around displayed # + ss.precision(decDigits); // set # places after decimal + ss << x; + return ss.str(); } /** @@ -97,12 +97,12 @@ std::string prd(const type x, const int decDigits, const int width) { * 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])) - ); - }; + 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])) + ); + }; @@ -110,30 +110,30 @@ auto equivalent = [](const FieldVector<double,3>& x, const FieldVector<double,3> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { - feenableexcept(FE_INVALID); - MPIHelper::instance(argc, argv); - - Dune::Timer globalTimer; - - if (argc < 3) - DUNE_THROW(Exception, "Usage: ./Cell-Problem <python path> <python module without extension>"); - - // Start Python interpreter - Python::start(); - auto pyMain = Python::main(); - pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; - auto pyModule = pyMain.import(argv[2]); - - ParameterTree parameterSet; - pyModule.get("parameterSet").toC(parameterSet); - // read possible further parameters from the command line - ParameterTreeParser::readOptions(argc, argv, parameterSet); - // Print all parameters, to make them appear in the log file - std::cout << "Input parameters:" << std::endl; - parameterSet.report(); + feenableexcept(FE_INVALID); + MPIHelper::instance(argc, argv); + + Dune::Timer globalTimer; + + if (argc < 3) + DUNE_THROW(Exception, "Usage: ./Cell-Problem <python path> <python module without extension>"); + + // Start Python interpreter + Python::start(); + auto pyMain = Python::main(); + pyMain.runStream() + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; + auto pyModule = pyMain.import(argv[2]); + + ParameterTree parameterSet; + pyModule.get("parameterSet").toC(parameterSet); + // read possible further parameters from the command line + ParameterTreeParser::readOptions(argc, argv, parameterSet); + // Print all parameters, to make them appear in the log file + std::cout << "Input parameters:" << std::endl; + parameterSet.report(); //--- Output setter std::string baseName = parameterSet.get("baseName", "CellProblem-result"); @@ -144,32 +144,32 @@ int main(int argc, char *argv[]) constexpr int dim = 3; - // Debug/Print Options + // Debug/Print Options bool print_debug = parameterSet.get<bool>("print_debug", false); // VTK-write options // bool write_prestrainFunctions = parameterSet.get<bool>("write_prestrainFunctions", false); //Not implemented yet. /** - * @brief Generate the grid. - * Corrector Problem Domain (-1/2,1/2)^3. - */ + * @brief 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}); - std::array<int,2> numLevels = parameterSet.get<std::array<int,2>>("numLevels", {3,3}); + std::array<int,2> numLevels = parameterSet.get<std::array<int,2> >("numLevels", {3,3}); int levelCounter = 0; - - + + /////////////////////////////////// // Create Data Storage /////////////////////////////////// //--- Storage:: #1 level #2 L2SymError #3 L2SymErrorOrder #4 L2Norm(sym) #5 L2Norm(sym-analytic) #6 L2Norm(phi_1) - //std::vector<std::variant<std::string, size_t , double>> Storage_Error; - //--- Storage:: | level | q1 | q2 | q3 | q12 | q13 | q23 | b1 | b2 | b3 | - std::vector<std::variant<std::string, size_t , double>> Storage_Quantities; + //std::vector<std::variant<std::string, size_t , double>> Storage_Error; + //--- Storage:: | level | q1 | q2 | q3 | q12 | q13 | q23 | b1 | b2 | b3 | + std::vector<std::variant<std::string, size_t , double> > Storage_Quantities; //--- GridLevel-Loop: - for(size_t level = numLevels[0] ; level <= numLevels[1]; level++) + for(size_t level = numLevels[0] ; level <= numLevels[1]; level++) { std::cout << " ----------------------------------" << std::endl; std::cout << "GridLevel: " << level << std::endl; @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) using GridView = CellGridType::LeafGridView; const GridView gridView_CE = grid_CE.leafGridView(); if(print_debug) - std::cout << "Host grid has " << gridView_CE.size(dim) << " vertices." << std::endl; + std::cout << "Host grid has " << gridView_CE.size(dim) << " vertices." << std::endl; //--- Choose a finite element space for Cell Problem using namespace Functions::BasisFactory; @@ -194,25 +194,25 @@ int main(int argc, char *argv[]) //--- 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)}); - } + 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)}); + } Dune::Timer basisSetupTimer; //--- Setup first order periodic Lagrange-Basis auto Basis_CE = makeBasis( - gridView_CE, - power<dim>( + gridView_CE, + power<dim>( Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), flatLexicographic() //blockedInterleaved() // Not Implemented - )); + )); std::cout << "Basis setup took " << basisSetupTimer.elapsed() << " seconds " << std::endl; if(print_debug) - std::cout << "power<periodic> basis has " << Basis_CE.dimension() << " degrees of freedom" << std::endl; + std::cout << "power<periodic> basis has " << Basis_CE.dimension() << " degrees of freedom" << std::endl; @@ -239,28 +239,28 @@ int main(int argc, char *argv[]) std::shared_ptr<MaterialType> material = std::make_shared<MaterialType>(gridView_CE,microstructure,parameterSet,pyModule); std::cout << "Material setup took " << materialSetupTimer.elapsed() << " seconds " << std::endl; - // --- Get scale ratio - // double gamma = parameterSet.get<double>("gamma",1.0); + // --- Get scale ratio + // double gamma = parameterSet.get<double>("gamma",1.0); std::cout << "scale ratio (gamma) set to : " << material->gamma_ << std::endl; //--- Compute Correctors // auto correctorComputer = CorrectorComputer(Basis_CE, material, log, parameterSet); // auto correctorComputer = CorrectorComputer(Basis_CE, materialPointer, log, parameterSet); - std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType>>(Basis_CE, material, parameterSet); + std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType> >(Basis_CE, material, parameterSet); correctorComputer->assemble(); correctorComputer->solve(); //--- Check Correctors (options): if(parameterSet.get<bool>("write_L2Error", false)) - correctorComputer->computeNorms(); + correctorComputer->computeNorms(); if(parameterSet.get<bool>("write_VTK", false)) - correctorComputer->writeCorrectorsVTK(level); + correctorComputer->writeCorrectorsVTK(level); //--- Additional Test: check orthogonality (75) from paper: if(parameterSet.get<bool>("write_checkOrthogonality", false)) - correctorComputer->check_Orthogonality(); + correctorComputer->check_Orthogonality(); //--- Check symmetry of stiffness matrix if(print_debug) - correctorComputer->checkSymmetry(); + correctorComputer->checkSymmetry(); //--- Compute effective quantities // auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material); @@ -269,7 +269,7 @@ int main(int argc, char *argv[]) //--- Write material indicator function to VTK if (parameterSet.get<bool>("write_materialFunctions", false)) - material->writeVTKMaterialFunctions(level); + material->writeVTKMaterialFunctions(level); //--- Get effective quantities auto Qeff = effectiveQuantitiesComputer.getQeff(); @@ -281,7 +281,7 @@ int main(int argc, char *argv[]) //--- Write effective quantities to matlab folder (for symbolic minimization) Dune::Timer txtOutputTimer; if(parameterSet.get<bool>("EffectiveQuantitiesToTxt", true)) - effectiveQuantitiesComputer.writeEffectiveQuantitiesToTxt(outputPath); + effectiveQuantitiesComputer.writeEffectiveQuantitiesToTxt(outputPath); std::cout << "Time to write effective quantities to .txt-files:" << txtOutputTimer.elapsed() << std::endl; @@ -318,56 +318,60 @@ int main(int argc, char *argv[]) log << "mu_gamma=" << Qeff[2][2] << std::endl; // added for Python-Script - levelCounter++; + levelCounter++; } // GridLevel-Loop End - ////////////////////////////////////////// - //--- Print Storage - ////////////////////////////////////////// - // Dune::Timer writeTableTimer; - int tableWidth = 12; - std::cout << center("Levels ",tableWidth) << " | " - << center("q1",tableWidth) << " | " - << center("q2",tableWidth) << " | " - << center("q3",tableWidth) << " | " - << center("q12",tableWidth) << " | " - << center("q13",tableWidth) << " | " - << center("q23",tableWidth) << " | " - << center("b1",tableWidth) << " | " - << center("b2",tableWidth) << " | " - << center("b3",tableWidth) << " | " << "\n"; - std::cout << std::string(tableWidth*10 + 3*10, '-') << "\n"; - log << std::string(tableWidth*10 + 3*10, '-') << "\n"; - log << center("Levels ",tableWidth) << " | " - << center("q1",tableWidth) << " | " - << center("q2",tableWidth) << " | " - << center("q3",tableWidth) << " | " - << center("q12",tableWidth) << " | " - << center("q13",tableWidth) << " | " - << center("q23",tableWidth) << " | " - << center("b1",tableWidth) << " | " - << center("b2",tableWidth) << " | " - << center("b3",tableWidth) << " | " << "\n"; - log << std::string(tableWidth*10 + 3*10, '-') << "\n"; - - int StorageCount2 = 0; - for(auto& v: Storage_Quantities) + ////////////////////////////////////////// + //--- Print Storage + ////////////////////////////////////////// + // Dune::Timer writeTableTimer; + int tableWidth = 12; + std::cout << center("Levels ",tableWidth) << " | " + << center("q1",tableWidth) << " | " + << center("q2",tableWidth) << " | " + << center("q3",tableWidth) << " | " + << center("q12",tableWidth) << " | " + << center("q13",tableWidth) << " | " + << center("q23",tableWidth) << " | " + << center("b1",tableWidth) << " | " + << center("b2",tableWidth) << " | " + << center("b3",tableWidth) << " | " << "\n"; + std::cout << std::string(tableWidth*10 + 3*10, '-') << "\n"; + log << std::string(tableWidth*10 + 3*10, '-') << "\n"; + log << center("Levels ",tableWidth) << " | " + << center("q1",tableWidth) << " | " + << center("q2",tableWidth) << " | " + << center("q3",tableWidth) << " | " + << center("q12",tableWidth) << " | " + << center("q13",tableWidth) << " | " + << center("q23",tableWidth) << " | " + << center("b1",tableWidth) << " | " + << center("b2",tableWidth) << " | " + << center("b3",tableWidth) << " | " << "\n"; + log << std::string(tableWidth*10 + 3*10, '-') << "\n"; + + int StorageCount2 = 0; + for(auto& v: Storage_Quantities) + { + std::visit([tableWidth](auto&& arg){ + std::cout << center(prd(arg,5,1),tableWidth) << " | "; + }, v); + std::visit([tableWidth, &log](auto&& arg){ + log << center(prd(arg,5,1),tableWidth) << " & "; + }, v); + StorageCount2++; + if(StorageCount2 % 10 == 0 ) { - std::visit([tableWidth](auto&& arg){std::cout << center(prd(arg,5,1),tableWidth) << " | ";}, v); - std::visit([tableWidth, &log](auto&& arg){log << center(prd(arg,5,1),tableWidth) << " & ";}, v); - StorageCount2++; - if(StorageCount2 % 10 == 0 ) - { - std::cout << std::endl; - log << std::endl; - } + std::cout << std::endl; + log << std::endl; } - std::cout << std::string(tableWidth*10 + 3*10, '-') << "\n"; - log << std::string(tableWidth*10 + 3*10, '-') << "\n"; + } + std::cout << std::string(tableWidth*10 + 3*10, '-') << "\n"; + log << std::string(tableWidth*10 + 3*10, '-') << "\n"; - // std::cout << "Time to write table:" << writeTableTimer.elapsed() << std::endl; + // std::cout << "Time to write table:" << writeTableTimer.elapsed() << std::endl; - log.close(); + log.close(); - std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; + std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; } diff --git a/src/Compute_MuGamma.cc b/src/Compute_MuGamma.cc index 8d15b40160437f6893b3beb537a8a351cd426a67..13cf84d7eeb8ce637f458a42279ab564d3a011a2 100644 --- a/src/Compute_MuGamma.cc +++ b/src/Compute_MuGamma.cc @@ -58,9 +58,9 @@ using namespace Dune; // ------------------------------------------------------------------------ // // Solving the 2D "Poisson-Type" Equation ( (38) in the draft) -// in order to compute mu_Gamma in a faster manner +// in order to compute mu_Gamma in a faster manner // -// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ @@ -69,115 +69,115 @@ void assembleElementStiffnessMatrix(const LocalView& localView, Matrix& elementMatrix, const LocalFunction& mu, const double gamma - ) + ) { - using Element = typename LocalView::Element; - constexpr int dim = Element::dimension; - const Element element = localView.element(); - auto geometry = element.geometry(); + using Element = typename LocalView::Element; + constexpr int dim = Element::dimension; + const Element element = localView.element(); + auto geometry = element.geometry(); - const auto& localFiniteElement = localView.tree().finiteElement(); - const auto nSf = localFiniteElement.localBasis().size(); - - -// std::cout << "nSf:" << nSf << std::endl; - - elementMatrix.setSize(localView.size(),localView.size()); - elementMatrix = 0; - -// int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1) + 5; // doesnt change anything - int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); -// int orderQR = 2 * (localFiniteElement.localBasis().order()-1); - const auto& quadRule = QuadratureRules<double, dim>::rule(element.type(),orderQR); - -// std::cout << "QuadRule-Order:" << orderQR << std::endl; - -// double muValue = 0.0; -// std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; - - for (const auto& quadPoint : quadRule) + const auto& localFiniteElement = localView.tree().finiteElement(); + const auto nSf = localFiniteElement.localBasis().size(); + + + // std::cout << "nSf:" << nSf << std::endl; + + elementMatrix.setSize(localView.size(),localView.size()); + elementMatrix = 0; + + // int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1) + 5; // doesnt change anything + int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); + // int orderQR = 2 * (localFiniteElement.localBasis().order()-1); + const auto& quadRule = QuadratureRules<double, dim>::rule(element.type(),orderQR); + + // std::cout << "QuadRule-Order:" << orderQR << std::endl; + + // double muValue = 0.0; + // std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; + + for (const auto& quadPoint : quadRule) + { + + + const auto& quadPos = quadPoint.position(); + + // std::cout << " quadPOS: " << quadPos << std::endl; + // TEST + // double muValue = mu(quadPos); + // std::cout << "muValue:" << muValue << std::endl; + + const auto jacobian = geometry.jacobianInverseTransposed(quadPos); + const double integrationElement = geometry.integrationElement(quadPos); + + + + std::vector<FieldMatrix<double,1,dim> > referenceGradients; + localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); + + // Compute the shape function gradients on the grid element + std::vector<FieldVector<double,dim> > gradients(referenceGradients.size()); + + for (size_t i=0; i<gradients.size(); i++) + jacobian.mv(referenceGradients[i][0], gradients[i]); //TODO ? passt.. + + + // // print all gradients //TEST + // FieldVector<double,dim> tmp = {0.0 , 0.0}; + // for (size_t i=0; i < nSf; i++) + // { + // printvector(std::cout, gradients[i], "gradients[i]", "--" ); + // + // + // tmp[0] += gradients[i][0]; + // tmp[1] += gradients[i][1]; + // + // // tmp[0] += coeffVector[globalIdx]*gradients[i][0]; // 3D-Version + // // tmp[1] += coeffVector[globalIdx]*gradients[i][2]; + // // printvector(std::cout, tmp, "tmp", "--" ); + // + // } + // printvector(std::cout, tmp, "sum of basisfunction Gradients", "--" ); + + for (size_t p=0; p<elementMatrix.N(); p++) { - - - const auto& quadPos = quadPoint.position(); - -// std::cout << " quadPOS: " << quadPos << std::endl; - // TEST -// double muValue = mu(quadPos); -// std::cout << "muValue:" << muValue << std::endl; - - const auto jacobian = geometry.jacobianInverseTransposed(quadPos); - const double integrationElement = geometry.integrationElement(quadPos); - - - - std::vector<FieldMatrix<double,1,dim> > referenceGradients; - localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); - - // Compute the shape function gradients on the grid element - std::vector<FieldVector<double,dim> > gradients(referenceGradients.size()); - - for (size_t i=0; i<gradients.size(); i++) - jacobian.mv(referenceGradients[i][0], gradients[i]); //TODO ? passt.. - - -// // print all gradients //TEST -// FieldVector<double,dim> tmp = {0.0 , 0.0}; -// for (size_t i=0; i < nSf; i++) -// { -// printvector(std::cout, gradients[i], "gradients[i]", "--" ); -// -// -// tmp[0] += gradients[i][0]; -// tmp[1] += gradients[i][1]; -// -// // tmp[0] += coeffVector[globalIdx]*gradients[i][0]; // 3D-Version -// // tmp[1] += coeffVector[globalIdx]*gradients[i][2]; -// // printvector(std::cout, tmp, "tmp", "--" ); -// -// } -// printvector(std::cout, tmp, "sum of basisfunction Gradients", "--" ); - - for (size_t p=0; p<elementMatrix.N(); p++) - { - for (size_t q=0; q<elementMatrix.M(); q++) - { -// auto localRow = localView.tree().localIndex(p); // VERTAUSCHT?!?! -// auto localCol = localView.tree().localIndex(q); - auto localRow = localView.tree().localIndex(q); - auto localCol = localView.tree().localIndex(p); - -// auto value = mu(quadPos)*(2.0* gradients[p][0] * gradients[q][0])+ mu(quadPos)*((1.0/(std::pow(gamma,2)))*(gradients[p][1] * gradients[q][1])); -// auto value = (mu(quadPos)*gradients[p][0] * gradients[q][0])+ ((1.0/gamma)*(gradients[p][1] * gradients[q][1])); - - - -// std::cout << "gradients[p][0]" << gradients[p][0] << std::endl; -// std::cout << "gradients[q][0]" << gradients[q][0] << std::endl; -// std::cout << "(1.0/std::pow(gamma,2))*gradients[p][1]" << (1.0/std::pow(gamma,2))*gradients[p][1]<< std::endl; - - - -// auto value3 = mu(quadPos)*(1.0/gamma)*gradients[p][2]; // 3D-Version -// auto value4 = value3*gradients[q][2]; // 3D-Version - - auto value1 = 2.0*mu(quadPos)* gradients[p][0] *gradients[q][0]; //#1 -// auto value1 = 2.0*mu(quadPos)*sqrt(2.0)* gradients[p][0] *gradients[q][0]; // TEST TODO warum passt es damit besser bei gamma = 1.0 ??? -// auto value2 = mu(quadPos)*(1.0/std::pow(gamma,2))*gradients[p][1] * gradients[q][1] ; - - - - - - auto value2 = 2.0*mu(quadPos)*(1.0/std::pow(gamma,2))*gradients[p][1] * gradients[q][1] ; //#1 TEST FAKTOR 2 hat hier gefehlt?!?! - - auto value = value1 + value2; - - elementMatrix[localRow][localCol] += value * quadPoint.weight() * integrationElement; - } - } + for (size_t q=0; q<elementMatrix.M(); q++) + { + // auto localRow = localView.tree().localIndex(p); // VERTAUSCHT?!?! + // auto localCol = localView.tree().localIndex(q); + auto localRow = localView.tree().localIndex(q); + auto localCol = localView.tree().localIndex(p); + + // auto value = mu(quadPos)*(2.0* gradients[p][0] * gradients[q][0])+ mu(quadPos)*((1.0/(std::pow(gamma,2)))*(gradients[p][1] * gradients[q][1])); + // auto value = (mu(quadPos)*gradients[p][0] * gradients[q][0])+ ((1.0/gamma)*(gradients[p][1] * gradients[q][1])); + + + + // std::cout << "gradients[p][0]" << gradients[p][0] << std::endl; + // std::cout << "gradients[q][0]" << gradients[q][0] << std::endl; + // std::cout << "(1.0/std::pow(gamma,2))*gradients[p][1]" << (1.0/std::pow(gamma,2))*gradients[p][1]<< std::endl; + + + + // auto value3 = mu(quadPos)*(1.0/gamma)*gradients[p][2]; // 3D-Version + // auto value4 = value3*gradients[q][2]; // 3D-Version + + auto value1 = 2.0*mu(quadPos)* gradients[p][0] *gradients[q][0]; //#1 + // auto value1 = 2.0*mu(quadPos)*sqrt(2.0)* gradients[p][0] *gradients[q][0]; // TEST TODO warum passt es damit besser bei gamma = 1.0 ??? + // auto value2 = mu(quadPos)*(1.0/std::pow(gamma,2))*gradients[p][1] * gradients[q][1] ; + + + + + + auto value2 = 2.0*mu(quadPos)*(1.0/std::pow(gamma,2))*gradients[p][1] * gradients[q][1] ; //#1 TEST FAKTOR 2 hat hier gefehlt?!?! + + auto value = value1 + value2; + + elementMatrix[localRow][localCol] += value * quadPoint.weight() * integrationElement; + } } + } } @@ -190,114 +190,114 @@ void assembleElementVolumeTerm(const LocalView& localView, LocalFunction& mu, const Force& forceTerm) { - using Element = typename LocalView::Element; - auto element = localView.element(); - auto geometry = element.geometry(); - + using Element = typename LocalView::Element; + auto element = localView.element(); + auto geometry = element.geometry(); - constexpr int dim = Element::dimension; - // Set of shape functions for a single element - const auto& localFiniteElement = localView.tree().finiteElement(); - const auto nSf = localFiniteElement.localBasis().size(); - // Set all entries to zero - elementRhs.resize(localFiniteElement.size()); - elementRhs = 0; - - // A quadrature rule -// int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; - int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); -// int orderQR = 2 * (localFiniteElement.localBasis().order()-1); - -// std::cout << "elementRhs.size():" << elementRhs.size() << std::endl; - - - - const auto& quadRule = QuadratureRules<double,dim>::rule(element.type(), orderQR); - - for (const auto& quadPoint : quadRule) + + constexpr int dim = Element::dimension; + // Set of shape functions for a single element + const auto& localFiniteElement = localView.tree().finiteElement(); + const auto nSf = localFiniteElement.localBasis().size(); + // Set all entries to zero + elementRhs.resize(localFiniteElement.size()); + elementRhs = 0; + + // A quadrature rule + // int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; + int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); + // int orderQR = 2 * (localFiniteElement.localBasis().order()-1); + + // std::cout << "elementRhs.size():" << elementRhs.size() << std::endl; + + + + const auto& quadRule = QuadratureRules<double,dim>::rule(element.type(), orderQR); + + for (const auto& quadPoint : quadRule) + { + const FieldVector<double,dim>& quadPos = quadPoint.position(); + + const double integrationElement = element.geometry().integrationElement(quadPos); + // double functionValue = forceTerm(element.geometry().global(quadPos)); + + // Evaluate all shape function values at this point + // std::vector<FieldVector<double,1> > shapeFunctionValues; + // localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues); + + const auto jacobian = geometry.jacobianInverseTransposed(quadPos); + + std::vector<FieldMatrix<double,1,dim> > referenceGradients; + localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); + + // Compute the shape function gradients on the grid element + std::vector<FieldVector<double,dim> > gradients(referenceGradients.size()); + for (size_t i=0; i<gradients.size(); i++) + jacobian.mv(referenceGradients[i][0], gradients[i]); + + + + // Actually compute the vector entries + for (size_t p=0; p<nSf; p++) { - const FieldVector<double,dim>& quadPos = quadPoint.position(); - - const double integrationElement = element.geometry().integrationElement(quadPos); -// double functionValue = forceTerm(element.geometry().global(quadPos)); - - // Evaluate all shape function values at this point -// std::vector<FieldVector<double,1> > shapeFunctionValues; -// localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues); - - const auto jacobian = geometry.jacobianInverseTransposed(quadPos); - - std::vector<FieldMatrix<double,1,dim> > referenceGradients; - localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); - - // Compute the shape function gradients on the grid element - std::vector<FieldVector<double,dim> > gradients(referenceGradients.size()); - for (size_t i=0; i<gradients.size(); i++) - jacobian.mv(referenceGradients[i][0], gradients[i]); - - - - // Actually compute the vector entries - for (size_t p=0; p<nSf; p++) - { - auto localIndex = localView.tree().localIndex(p); -// elementRhs[localIndex] += shapeFunctionValues[p] * forceTerm(quadPos) * quadPoint.weight() * integrationElement; -// auto value = shapeFunctionValues[p]* (sqrt(2.0)*mu(quadPos) *forceTerm(quadPos)); -// auto value = -1.0*gradients[p][0] * (sqrt(2.0)*mu(quadPos) *forceTerm(quadPos)); //NEGATIVE!!! TODO -// auto value = -2.0*mu(quadPos)*(sqrt(2.0)*forceTerm(quadPos))*gradients[p][0] ; -// auto value = -1.0*mu(quadPos)*forceTerm(quadPos)*gradients[p][0] ; - - - - -// auto value = -2.0*sqrt(2.0)*mu(quadPos)*forceTerm(quadPos)*gradients[p][0]; //#1 - - - auto value = 2.0*sqrt(2.0)*mu(quadPos)*forceTerm(quadPos)*gradients[p][0]; // TEST - - - - - -// auto value = 2.0*mu(quadPos)*sqrt(2.0)*forceTerm(quadPos)*gradients[p][0]; -// auto value = -2.0*mu(quadPos)*sqrt(2.0)*quadPos[1]*gradients[p][0]; //TEST -// std::cout << "value:" << value << std::endl; - -// std::cout << "forceTerm(quadPos):" << forceTerm(quadPos) << std::endl; -// std::cout << "quadPos:" << quadPos << std::endl; -// std::cout << "integrationElement:" << integrationElement << std::endl; - -// auto value = -1.0*sqrt(2.0)*forceTerm(quadPos)*gradients[p][0] ; //TEST - -// auto value = -1.0*mu(quadPos)*sqrt(2.0)*forceTerm(quadPos)*forceTerm(quadPos)*gradients[p][0]; //TEST - - elementRhs[localIndex] += value * quadPoint.weight() * integrationElement; - } + auto localIndex = localView.tree().localIndex(p); + // elementRhs[localIndex] += shapeFunctionValues[p] * forceTerm(quadPos) * quadPoint.weight() * integrationElement; + // auto value = shapeFunctionValues[p]* (sqrt(2.0)*mu(quadPos) *forceTerm(quadPos)); + // auto value = -1.0*gradients[p][0] * (sqrt(2.0)*mu(quadPos) *forceTerm(quadPos)); //NEGATIVE!!! TODO + // auto value = -2.0*mu(quadPos)*(sqrt(2.0)*forceTerm(quadPos))*gradients[p][0] ; + // auto value = -1.0*mu(quadPos)*forceTerm(quadPos)*gradients[p][0] ; + + + + + // auto value = -2.0*sqrt(2.0)*mu(quadPos)*forceTerm(quadPos)*gradients[p][0]; //#1 + + + auto value = 2.0*sqrt(2.0)*mu(quadPos)*forceTerm(quadPos)*gradients[p][0]; // TEST + + + + + + // auto value = 2.0*mu(quadPos)*sqrt(2.0)*forceTerm(quadPos)*gradients[p][0]; + // auto value = -2.0*mu(quadPos)*sqrt(2.0)*quadPos[1]*gradients[p][0]; //TEST + // std::cout << "value:" << value << std::endl; + + // std::cout << "forceTerm(quadPos):" << forceTerm(quadPos) << std::endl; + // std::cout << "quadPos:" << quadPos << std::endl; + // std::cout << "integrationElement:" << integrationElement << std::endl; + + // auto value = -1.0*sqrt(2.0)*forceTerm(quadPos)*gradients[p][0] ; //TEST + + // auto value = -1.0*mu(quadPos)*sqrt(2.0)*forceTerm(quadPos)*forceTerm(quadPos)*gradients[p][0]; //TEST + + elementRhs[localIndex] += value * quadPoint.weight() * integrationElement; } + } } // Get the occupation pattern of the stiffness matrix template<class Basis> void getOccupationPattern(const Basis& basis, MatrixIndexSet& nb) { - nb.resize(basis.size(), basis.size()); - auto gridView = basis.gridView(); - // A loop over all elements of the grid - auto localView = basis.localView(); - for (const auto& element : elements(gridView)) + nb.resize(basis.size(), basis.size()); + auto gridView = basis.gridView(); + // A loop over all elements of the grid + auto localView = basis.localView(); + for (const auto& element : elements(gridView)) + { + localView.bind(element); + for (size_t i=0; i<localView.size(); i++) { - localView.bind(element); - for (size_t i=0; i<localView.size(); i++) - { - // The global index of the i-th vertex of the element - auto row = localView.index(i); - for (size_t j=0; j<localView.size(); j++ ) - { - // The global index of the j-th vertex of the element - auto col = localView.index(j); - nb.add(row,col); - } - } + // The global index of the i-th vertex of the element + auto row = localView.index(i); + for (size_t j=0; j<localView.size(); j++ ) + { + // The global index of the j-th vertex of the element + auto col = localView.index(j); + nb.add(row,col); + } } + } } /** \brief Assemble the Laplace stiffness matrix on the given grid view */ template<class Basis, class Matrix, class Vector, class LocalFunction, class Force> @@ -308,61 +308,61 @@ void assemblePoissonProblem(const Basis& basis, const Force& forceTerm, const double gamma) { - auto gridView = basis.gridView(); + auto gridView = basis.gridView(); + + + MatrixIndexSet occupationPattern; + getOccupationPattern(basis, occupationPattern); + occupationPattern.exportIdx(matrix); + matrix = 0; + + + auto loadGVF = Dune::Functions::makeGridViewFunction(forceTerm, basis.gridView()); + auto loadFunctional = localFunction(loadGVF); + b.resize(basis.dimension()); + b = 0; + + auto localView = basis.localView(); + + for (const auto& element : elements(gridView)) + { + + localView.bind(element); + muLocal.bind(element); + loadFunctional.bind(element); - MatrixIndexSet occupationPattern; - getOccupationPattern(basis, occupationPattern); - occupationPattern.exportIdx(matrix); - matrix = 0; - - - auto loadGVF = Dune::Functions::makeGridViewFunction(forceTerm, basis.gridView()); - auto loadFunctional = localFunction(loadGVF); - b.resize(basis.dimension()); - b = 0; + // Dune::Matrix<double> elementMatrix; + Dune::Matrix<FieldMatrix<double,1,1> > elementMatrix; + // Dune::Matrix<FieldMatrix<double,1,1> > elementMatrix; + assembleElementStiffnessMatrix(localView, elementMatrix, muLocal, gamma); - auto localView = basis.localView(); - - for (const auto& element : elements(gridView)) + // std::cout << "elementMatrix.N() "<< elementMatrix.N() << std::endl; + // std::cout << "elementMatrix.M() " << elementMatrix.M() << std::endl; + + + for(size_t p=0; p<elementMatrix.N(); p++) { + auto row = localView.index(p); + for (size_t q=0; q<elementMatrix.M(); q++ ) + { + auto col = localView.index(q); + matrix[row][col] += elementMatrix[p][q]; + } + } - localView.bind(element); - muLocal.bind(element); - loadFunctional.bind(element); - - -// Dune::Matrix<double> elementMatrix; - Dune::Matrix<FieldMatrix<double,1,1> > elementMatrix; -// Dune::Matrix<FieldMatrix<double,1,1> > elementMatrix; - assembleElementStiffnessMatrix(localView, elementMatrix, muLocal, gamma); - -// std::cout << "elementMatrix.N() "<< elementMatrix.N() << std::endl; -// std::cout << "elementMatrix.M() " << elementMatrix.M() << std::endl; - - - for(size_t p=0; p<elementMatrix.N(); p++) - { - auto row = localView.index(p); - for (size_t q=0; q<elementMatrix.M(); q++ ) - { - auto col = localView.index(q); - matrix[row][col] += elementMatrix[p][q]; - } - } - -// BlockVector<double> elementRhs; - BlockVector<FieldVector<double,1> > elementRhs; - assembleElementVolumeTerm(localView, elementRhs, muLocal, loadFunctional); - for (size_t p=0; p<elementRhs.size(); p++) - { - // The global index of the p-th vertex of the element - auto row = localView.index(p); - b[row] += elementRhs[p]; - } + // BlockVector<double> elementRhs; + BlockVector<FieldVector<double,1> > elementRhs; + assembleElementVolumeTerm(localView, elementRhs, muLocal, loadFunctional); + for (size_t p=0; p<elementRhs.size(); p++) + { + // The global index of the p-th vertex of the element + auto row = localView.index(p); + b[row] += elementRhs[p]; } + } } @@ -372,145 +372,145 @@ void assemblePoissonProblem(const Basis& basis, template<class Basis, class Vector, class LocalFunc1, class LocalFunc2> double computeMuGamma(const Basis& basis, Vector& coeffVector, - const double gamma, + const double gamma, LocalFunc1& mu, LocalFunc2& Func - ) + ) { -// constexpr int dim = Basis::LocalView::Element::dimension; - + // constexpr int dim = Basis::LocalView::Element::dimension; + double output = 0.0; double Term1 = 0.0; double Term2 = 0.0; double Term11 = 0.0; constexpr int dim = 2; -// constexpr int dim = 3; + // constexpr int dim = 3; auto localView = basis.localView(); - -// auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<double>(basis, coeffVector); -// auto localSol = localFunction(solutionFunction); - -// auto loadGVF = Dune::Functions::makeGridViewFunction(x3Fun, basis.gridView()); -// auto x3Functional = localFunction(loadGVF); - - - - + + // auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<double>(basis, coeffVector); + // auto localSol = localFunction(solutionFunction); + + // auto loadGVF = Dune::Functions::makeGridViewFunction(x3Fun, basis.gridView()); + // auto x3Functional = localFunction(loadGVF); + + + + double area = 0.0; - + for(const auto& element : elements(basis.gridView())) { - -// std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; - double elementEnergy1 = 0.0; - double elementEnergy2 = 0.0; - - localView.bind(element); - mu.bind(element); + + // std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; + double elementEnergy1 = 0.0; + double elementEnergy2 = 0.0; + + localView.bind(element); + mu.bind(element); // x3Functional.bind(element); - Func.bind(element); - - auto geometry = element.geometry(); - const auto& localFiniteElement = localView.tree().finiteElement(); - const auto nSf = localFiniteElement.localBasis().size(); + Func.bind(element); -// int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; - int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); + auto geometry = element.geometry(); + const auto& localFiniteElement = localView.tree().finiteElement(); + const auto nSf = localFiniteElement.localBasis().size(); + + // int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; + int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); // int orderQR = 2 * (localFiniteElement.localBasis().order()-1); - const auto& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR); // TODO WARUM HIER KEINE COLOR ?? ERROR - + const auto& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR); // TODO WARUM HIER KEINE COLOR ?? ERROR + // std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; - for(const auto& quadPoint : quad) - { - const auto& quadPos = quadPoint.position(); - // const FieldVector<double,dim>& quadPos = quadPoint.position(); - // std::cout << " quadPOS: " << quadPos << std::endl; + for(const auto& quadPoint : quad) + { + const auto& quadPos = quadPoint.position(); + // const FieldVector<double,dim>& quadPos = quadPoint.position(); + // std::cout << " quadPOS: " << quadPos << std::endl; - - const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos); - const double integrationElement = geometry.integrationElement(quadPos); - - area += quadPoint.weight() * integrationElement; - - std::vector< FieldMatrix<double, 1, dim>> referenceGradients; - localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); - - // Compute the shape function gradients on the grid element - std::vector<FieldVector<double,dim>> gradients(referenceGradients.size()); - - for (size_t i=0; i<gradients.size(); i++) - jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]); - - FieldVector<double,dim> tmp(0.0); - // std::cout << "integrationElement :" << integrationElement << std::endl; - // std::cout << "quadPoint.weight() :" << quadPoint.weight() << std::endl; - - for (size_t i=0; i < nSf; i++) - { - size_t localIdx = localView.tree().localIndex(i); // hier i:leafIdx - size_t globalIdx = localView.index(localIdx); - // printvector(std::cout, gradients[i], "gradients[i]", "--" ); + + const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos); + const double integrationElement = geometry.integrationElement(quadPos); + + area += quadPoint.weight() * integrationElement; + + std::vector< FieldMatrix<double, 1, dim> > referenceGradients; + localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); + + // Compute the shape function gradients on the grid element + std::vector<FieldVector<double,dim> > gradients(referenceGradients.size()); + + for (size_t i=0; i<gradients.size(); i++) + jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]); + + FieldVector<double,dim> tmp(0.0); + // std::cout << "integrationElement :" << integrationElement << std::endl; + // std::cout << "quadPoint.weight() :" << quadPoint.weight() << std::endl; + + for (size_t i=0; i < nSf; i++) + { + size_t localIdx = localView.tree().localIndex(i); // hier i:leafIdx + size_t globalIdx = localView.index(localIdx); + // printvector(std::cout, gradients[i], "gradients[i]", "--" ); // std::cout << "coeffVector[globalIdx]:" << coeffVector[globalIdx] << std::endl; - tmp[0] += coeffVector[globalIdx]*gradients[i][0]; - tmp[1] += coeffVector[globalIdx]*gradients[i][1]; + tmp[0] += coeffVector[globalIdx]*gradients[i][0]; + tmp[1] += coeffVector[globalIdx]*gradients[i][1]; // tmp[0] += coeffVector[globalIdx]*gradients[i][0]; // 3D-Version // tmp[1] += coeffVector[globalIdx]*gradients[i][2]; - // printvector(std::cout, tmp, "tmp", "--" ); - } - // printvector(std::cout, tmp, "gradient_w", "--" ); - - // auto value1 = std::pow( ((quadPos[1]/sqrt(2.0))+ (tmp[0]/2.0)) ,2); //TEST - - - - auto q1 = (Func(quadPos)/sqrt(2.0)); //#1 - auto q2 = (tmp[0]/2.0); //#1 - - -// auto q2 = (tmp[0]/sqrt(2.0)); // TEST !!!!!!!!!! - - - - + // printvector(std::cout, tmp, "tmp", "--" ); + } + // printvector(std::cout, tmp, "gradient_w", "--" ); - // CHECK : BEITRÄGE CHECKEN!!!! - -// std::cout << "Beitrag1: " << q2 << std::endl; -// std::cout << "Beitrag2: " << (tmp[1]/(2.0*gamma)) << std::endl; -// -// -// - - auto q3 = q1 - q2; // TEST - -// auto q3 = q1 + q2; // #1 - auto value1 = std::pow(q3,2); + // auto value1 = std::pow( ((quadPos[1]/sqrt(2.0))+ (tmp[0]/2.0)) ,2); //TEST - - -// auto value2 = std::pow( (tmp[1]/(2.0*gamma) ) , 2); - auto value2 = std::pow( (tmp[1]/(sqrt(2.0)*gamma) ) , 2); - - -// auto value = 2.0*mu(quadPos)*(2.0*value1 + value2); - - - elementEnergy1 += 2.0*mu(quadPos)* 2.0*value1 * quadPoint.weight() * integrationElement; - elementEnergy2 += 2.0*mu(quadPos)* value2 * quadPoint.weight() * integrationElement; - // std::cout << "output:" << output << std::endl; - } -// std::cout << "elementEnergy:" << elementEnergy << std::endl; + auto q1 = (Func(quadPos)/sqrt(2.0)); //#1 + auto q2 = (tmp[0]/2.0); //#1 + + + // auto q2 = (tmp[0]/sqrt(2.0)); // TEST !!!!!!!!!! + + + + + + // CHECK : BEITRÄGE CHECKEN!!!! + + // std::cout << "Beitrag1: " << q2 << std::endl; + // std::cout << "Beitrag2: " << (tmp[1]/(2.0*gamma)) << std::endl; + // + // + // + + auto q3 = q1 - q2; // TEST + + // auto q3 = q1 + q2; // #1 + auto value1 = std::pow(q3,2); + + + + // auto value2 = std::pow( (tmp[1]/(2.0*gamma) ) , 2); + auto value2 = std::pow( (tmp[1]/(sqrt(2.0)*gamma) ) , 2); + - Term1 += elementEnergy1; - Term2 += elementEnergy2; - -// std::cout << "output: " << output << std::endl; - } + + // auto value = 2.0*mu(quadPos)*(2.0*value1 + value2); + + + + elementEnergy1 += 2.0*mu(quadPos)* 2.0*value1 * quadPoint.weight() * integrationElement; + elementEnergy2 += 2.0*mu(quadPos)* value2 * quadPoint.weight() * integrationElement; + // std::cout << "output:" << output << std::endl; + } + // std::cout << "elementEnergy:" << elementEnergy << std::endl; + + Term1 += elementEnergy1; + Term2 += elementEnergy2; + + // std::cout << "output: " << output << std::endl; + } std::cout << "Term1: " << Term1 << std::endl; std::cout << "Term2: " << Term2 << std::endl; output = Term1 + Term2; @@ -522,45 +522,45 @@ double computeMuGamma(const Basis& basis, // // ----------------------------------------------------------- /* -template<class Basis, class Vector, class LocalFunc1, class LocalFunc2> -double computeMuGamma(const Basis& basis, + template<class Basis, class Vector, class LocalFunc1, class LocalFunc2> + double computeMuGamma(const Basis& basis, Vector& coeffVector, - const double gamma, + const double gamma, LocalFunc1& mu, LocalFunc2& Func ) -{ + { -// constexpr int dim = Basis::LocalView::Element::dimension; - - double output = 0.0; - constexpr int dim = 2; -// constexpr int dim = 3; - auto localView = basis.localView(); - -// auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<double>(basis, coeffVector); -// auto localSol = localFunction(solutionFunction); - -// auto loadGVF = Dune::Functions::makeGridViewFunction(x3Fun, basis.gridView()); -// auto x3Functional = localFunction(loadGVF); - - - - - double area = 0.0; - - for(const auto& element : elements(basis.gridView())) - { - -// std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; + // constexpr int dim = Basis::LocalView::Element::dimension; + + double output = 0.0; + constexpr int dim = 2; + // constexpr int dim = 3; + auto localView = basis.localView(); + + // auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<double>(basis, coeffVector); + // auto localSol = localFunction(solutionFunction); + + // auto loadGVF = Dune::Functions::makeGridViewFunction(x3Fun, basis.gridView()); + // auto x3Functional = localFunction(loadGVF); + + + + + double area = 0.0; + + for(const auto& element : elements(basis.gridView())) + { + + // std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; double elementEnergy = 0.0; - + localView.bind(element); mu.bind(element); // x3Functional.bind(element); Func.bind(element); - + auto geometry = element.geometry(); const auto& localFiniteElement = localView.tree().finiteElement(); const auto nSf = localFiniteElement.localBasis().size(); @@ -569,92 +569,92 @@ double computeMuGamma(const Basis& basis, int orderQR = 2 * (dim*localFiniteElement.localBasis().order()-1); // int orderQR = 2 * (localFiniteElement.localBasis().order()-1); const auto& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR); // TODO WARUM HIER KEINE COLOR ?? ERROR - + // std::cout << " ------------------------- one ELEMENT ------------------------" << std::endl; for(const auto& quadPoint : quad) { - + const auto& quadPos = quadPoint.position(); // const FieldVector<double,dim>& quadPos = quadPoint.position(); // std::cout << " quadPOS: " << quadPos << std::endl; - + const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos); const double integrationElement = geometry.integrationElement(quadPos); - + area += quadPoint.weight() * integrationElement; - + std::vector< FieldMatrix<double, 1, dim>> referenceGradients; localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients); - + // Compute the shape function gradients on the grid element std::vector<FieldVector<double,dim>> gradients(referenceGradients.size()); - + for (size_t i=0; i<gradients.size(); i++) jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]); - -// FieldVector<double,dim> tmp = {0.0 , 0.0}; + + // FieldVector<double,dim> tmp = {0.0 , 0.0}; FieldVector<double,dim> tmp(0.0); - // FieldVector<double,dim> tmp = {0.0 ,0.0, 0.0}; //3D-Version - + // FieldVector<double,dim> tmp = {0.0 ,0.0, 0.0}; //3D-Version + // std::cout << "integrationElement :" << integrationElement << std::endl; // std::cout << "quadPoint.weight() :" << quadPoint.weight() << std::endl; - + for (size_t i=0; i < nSf; i++) { size_t localIdx = localView.tree().localIndex(i); // hier i:leafIdx size_t globalIdx = localView.index(localIdx); - - // printvector(std::cout, gradients[i], "gradients[i]", "--" ); + + // printvector(std::cout, gradients[i], "gradients[i]", "--" ); // std::cout << "coeffVector[globalIdx]:" << coeffVector[globalIdx] << std::endl; - + tmp[0] += coeffVector[globalIdx]*gradients[i][0]; tmp[1] += coeffVector[globalIdx]*gradients[i][1]; - + // tmp[0] += coeffVector[globalIdx]*gradients[i][0]; // 3D-Version // tmp[1] += coeffVector[globalIdx]*gradients[i][2]; - // printvector(std::cout, tmp, "tmp", "--" ); + // printvector(std::cout, tmp, "tmp", "--" ); } // printvector(std::cout, tmp, "gradient_w", "--" ); - - + + // auto value1 = std::pow( ((quadPos[1]/sqrt(2.0))+ (tmp[0]/2.0)) ,2); //TEST - - - + + + auto q1 = (Func(quadPos)/sqrt(2.0)); auto q2 = (tmp[0]/2.0); - - -// auto q2 = (tmp[0]/sqrt(2.0)); // TEST !!!!!!!!!! - - - - + + + // auto q2 = (tmp[0]/sqrt(2.0)); // TEST !!!!!!!!!! + + + + // CHECK : BEITRÄGE CHECKEN!!!! - + std::cout << "Beitrag1: " << q2 << std::endl; std::cout << "Beitrag2: " << (tmp[1]/(2.0*gamma)) << std::endl; - - - - + + + + auto q3 = q1 + q2; auto value1 = std::pow(q3,2); -// auto value1 = std::pow( ((Func(quadPos)/sqrt(2.0)) + (tmp[0]/2.0)) , 2); - - + // auto value1 = std::pow( ((Func(quadPos)/sqrt(2.0)) + (tmp[0]/2.0)) , 2); + + auto value2 = std::pow( (tmp[1]/(2.0*gamma) ) , 2); -// auto value2 = std::pow( (tmp[1]/(sqrt(2.0)*gamma) ) , 2); //TEST - - + // auto value2 = std::pow( (tmp[1]/(sqrt(2.0)*gamma) ) , 2); //TEST + + // auto value2 = (1.0/(std::pow(gamma,2)))* std::pow(tmp[1],2)/4.0 ; //TEST - + auto value = 2.0*mu(quadPos)*(2.0*value1 + value2); - + // std::cout << "quadPos[1]:" << quadPos[1]<< std::endl; // std::cout << "Func(quadPos):" << Func(quadPos) << std::endl; // std::cout << "sqrt(2.0):" << sqrt(2.0) << std::endl; @@ -663,38 +663,38 @@ double computeMuGamma(const Basis& basis, // std::cout << "value1:" << value1 << std::endl; // std::cout << "value2:" << value2 << std::endl; // std::cout << "value:" << value << std::endl; - - + + // auto value = 2.0*mu(quadPos)*(2.0*std::pow( ((x3Functional(quadPos)/sqrt(2.0))+ (tmp[0]/2.0)) ,2) + std::pow( (tmp[1]/(2.0*gamma) ) ,2) ); - - - + + + // auto value = 2.0*mu(quadPos)*(2.0* (((x3Functional(quadPos)*x3Functional(quadPos))/2.0) + std::pow( (tmp[0]/2.0) ,2)) + std::pow( (tmp[1]/(2.0*gamma) ) ,2) ); //TEST - + // auto value = 2.0*mu(quadPos)*(2.0*std::pow( ((x3Functional(quadPos)/sqrt(2.0))+ (tmp[0]/2.0)) ,2) ) + std::pow( (tmp[1]/(2.0*gamma) ) ,2) ; //TEST // auto value = 2.0*mu(quadPos)*(2.0*std::pow( ((x3Functional(quadPos)/sqrt(2.0))+ (tmp[0]/2.0)) ,2)) + (1.0/gamma)*std::pow( (tmp[1]/2.0) ,2) ; //TEST // auto value = 2.0*mu(quadPos)*(2.0*std::pow( ((x3Functional(quadPos)/sqrt(2.0))+ (tmp[0]/2.0)) ,2) + (1.0/gamma)*std::pow( (tmp[1]/2.0) ,2) ) ; //TEST - + elementEnergy += value * quadPoint.weight() * integrationElement; // std::cout << "output:" << output << std::endl; } -// std::cout << "elementEnergy:" << elementEnergy << std::endl; + // std::cout << "elementEnergy:" << elementEnergy << std::endl; output += elementEnergy; -// std::cout << "output: " << output << std::endl; - } - std::cout << "Domain-Area: " << area << std::endl; - return (1.0/area) * output; -} -// ------------------------------------------------------------------------- -*/ + // std::cout << "output: " << output << std::endl; + } + std::cout << "Domain-Area: " << area << std::endl; + return (1.0/area) * output; + } + // ------------------------------------------------------------------------- + */ - // Check whether two points are equal on R/Z x R/Z - auto equivalent = [](const FieldVector<double,2>& x, const FieldVector<double,2>& 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])) ); - }; +// Check whether two points are equal on R/Z x R/Z +auto equivalent = [](const FieldVector<double,2>& x, const FieldVector<double,2>& 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])) ); + }; @@ -703,8 +703,8 @@ int main(int argc, char *argv[]) MPIHelper::instance(argc, argv); - - + + ParameterTree parameterSet; if (argc < 2) ParameterTreeParser::readINITree("../../inputs/computeMuGamma.parset", parameterSet); @@ -713,260 +713,262 @@ int main(int argc, char *argv[]) ParameterTreeParser::readINITree(argv[1], parameterSet); ParameterTreeParser::readOptions(argc, argv, parameterSet); } - ///////////////////////////////// - // SET OUTPUT - ///////////////////////////////// - std::string outputPath = parameterSet.get("outputPath", "/home/klaus/Desktop/DUNE/dune-microstructure/outputs"); - std::fstream log; - log.open(outputPath + "/outputMuGamma.txt" ,std::ios::out); - std::cout << "outputPath:" << outputPath << std::endl; - - - ////////////////////////////////// - // Generate the grid - ////////////////////////////////// - constexpr int dim = 2; - - // QUAD-GRID - FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0}); - FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0}); -// std::array<int, dim> nElements = {16,16}; - - std::array<int,2> nElements = parameterSet.get<std::array<int,2>>("nElements", {32,32}); - std::cout << "Number of Elements in each direction: " << nElements << std::endl; - log << "Number of 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 = grid_CE.leafGridView(); - using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate; - - // ----------- INPUT PARAMETERS ----------------------------- - std::string imp = parameterSet.get<std::string>("material_prestrain_imp", "parametrized_Laminate"); - log << "material_prestrain used: "<< imp << std::endl; - double gamma = parameterSet.get<double>("gamma", 1.0); - double theta = parameterSet.get<double>("theta", 1.0/4.0); - double mu1 = parameterSet.get<double>("mu1", 1.0); - double beta = parameterSet.get<double>("beta", 2.0); - double mu2 = beta*mu1; - std::cout << "Gamma:" << gamma << std::endl; - std::cout << "Theta:" << theta << std::endl; - std::cout << "mu1:" << mu1 << std::endl; - std::cout << "mu2:" << mu2 << std::endl; - std::cout << "beta:" << beta << std::endl; - log << "----- Input Parameters -----: " << std::endl; - log << "gamma: " << gamma << std::endl; - log << "theta: " << theta << std::endl; - log << "beta: " << beta << std::endl; - log << "material parameters: " << std::endl; - log << "mu1: " << mu1 << "\nmu2: " << mu2 << std::endl; - -// auto muTerm = [mu1, mu2, theta] (const Domain& z) { -// -// // if (abs(z[0]) > (theta/2.0)) -// if (abs(z[0]) >= (theta/2.0)) -// return mu1; -// else -// return mu2; -// }; - - auto materialImp = IsotropicMaterialImp<dim>(); - auto muTerm = materialImp.getMu(parameterSet); - auto muGridF = Dune::Functions::makeGridViewFunction(muTerm, gridView); - auto muLocal = localFunction(muGridF); - - - ///////////////////////////////////////////////////////// - // Stiffness matrix and right hand side vector - ///////////////////////////////////////////////////////// - using Vector = BlockVector<FieldVector<double,1> >; - using Matrix = BCRSMatrix<FieldMatrix<double,1,1> >; - Matrix stiffnessMatrix; - Vector b; - - ///////////////////////////////////////////////////////// - // Assemble the system - ///////////////////////////////////////////////////////// - using namespace Functions::BasisFactory; - Functions::BasisFactory::Experimental::PeriodicIndexSet periodicIndices; - - // Don't do the following in real life: It has quadratic run-time in the number of vertices. - for (const auto& v1 : vertices(gridView)) - for (const auto& v2 : vertices(gridView)) - if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0))) - periodicIndices.unifyIndexPair({gridView.indexSet().index(v1)}, {gridView.indexSet().index(v2)}); - - auto basis = makeBasis(gridView, Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices)); // flatLexicographic()? - - - auto forceTerm = [](const FieldVector<double,dim>& x){return x[1];}; //2D-Version - auto ForceGridF = Dune::Functions::makeGridViewFunction(forceTerm, gridView); - auto ForceLocal = localFunction(ForceGridF); - - assemblePoissonProblem(basis, stiffnessMatrix, b, muLocal, forceTerm, gamma); -// printmatrix(std::cout, stiffnessMatrix, "StiffnessMatrix", "--"); -// printvector(std::cout, b, "b", "--"); - - - - - - - /////////////////////////// - // Compute solution - /////////////////////////// - - Vector x(basis.size()); - x = b; - - std::cout << "------------ CG - Solver ------------" << std::endl; - MatrixAdapter<Matrix, Vector, Vector> op(stiffnessMatrix); - - - - // Sequential incomplete LU decomposition as the preconditioner - SeqILU<Matrix, Vector, Vector> ilu0(stiffnessMatrix,1.0); - int iter = parameterSet.get<double>("iterations_CG", 999); - // Preconditioned conjugate-gradient solver - CGSolver<Vector> solver(op, - ilu0, //NULL, - 1e-8, // desired residual reduction factorlack - iter, // maximum number of iterations - 2); // verbosity of the solver - InverseOperatorResult statistics; - // Solve! - solver.apply(x, b, statistics); - -// std::cout << "------------ GMRES - Solver ------------" << std::endl; -// // Turn the matrix into a linear operator -// MatrixAdapter<Matrix, Vector, Vector> op(stiffnessMatrix); -// -// // Fancy (but only) way to not have a preconditioner at all -// Richardson<Vector,Vector> preconditioner(1.0); -// -// // Construct the iterative solver -// RestartedGMResSolver<Vector> solver( -// op, // Operator to invert -// preconditioner, // Preconditioner -// 1e-10, // Desired residual reduction factor -// 500, // Number of iterations between restarts, -// // here: no restarting -// 500, // Maximum number of iterations -// 2); // Verbosity of the solver -// -// // Object storing some statistics about the solving process -// InverseOperatorResult statistics; -// -// // solve for different Correctors (alpha = 1,2,3) -// solver.apply(x, b, statistics); -// - -// ----------------------------------------------------------------------------------------------------- - - - using SolutionRange = double; - auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<SolutionRange>(basis, x); - - - // -------- PRINT OUTPUT -------- -// printvector(std::cout, x, "coeffVector", "--" ); - std::cout << "Gamma:" << gamma << std::endl; - double mu_gamma = computeMuGamma(basis, x, gamma, muLocal, ForceLocal); - std::cout << "mu_gamma:" << mu_gamma << std::endl; - log << "----- OUTPUT: -----: " << std::endl; - log << "mu_gamma=" << mu_gamma << std::endl; - log << "q3=" << mu_gamma << std::endl; - -// std::cout.precision(10); -// std::cout << "mu_gamma:" << std::fixed << mu_gamma << std::endl; - - - -// Vector zeroVec(basis.size()); -// zeroVec = 0; -// std::cout << "TEST computeMuGamma:" << computeMuGamma(basis, zeroVec, gamma, muLocal, ForceLocal)<< std::endl; - std::cout << " --- print analytic solutions(if possible) --- " << std::endl; - if (imp == "analytical_Example") + ///////////////////////////////// + // SET OUTPUT + ///////////////////////////////// + std::string outputPath = parameterSet.get("outputPath", "/home/klaus/Desktop/DUNE/dune-microstructure/outputs"); + std::fstream log; + log.open(outputPath + "/outputMuGamma.txt" ,std::ios::out); + std::cout << "outputPath:" << outputPath << std::endl; + + + ////////////////////////////////// + // Generate the grid + ////////////////////////////////// + constexpr int dim = 2; + + // QUAD-GRID + FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0}); + FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0}); + // std::array<int, dim> nElements = {16,16}; + + std::array<int,2> nElements = parameterSet.get<std::array<int,2> >("nElements", {32,32}); + std::cout << "Number of Elements in each direction: " << nElements << std::endl; + log << "Number of 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 = grid_CE.leafGridView(); + using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate; + + // ----------- INPUT PARAMETERS ----------------------------- + std::string imp = parameterSet.get<std::string>("material_prestrain_imp", "parametrized_Laminate"); + log << "material_prestrain used: "<< imp << std::endl; + double gamma = parameterSet.get<double>("gamma", 1.0); + double theta = parameterSet.get<double>("theta", 1.0/4.0); + double mu1 = parameterSet.get<double>("mu1", 1.0); + double beta = parameterSet.get<double>("beta", 2.0); + double mu2 = beta*mu1; + std::cout << "Gamma:" << gamma << std::endl; + std::cout << "Theta:" << theta << std::endl; + std::cout << "mu1:" << mu1 << std::endl; + std::cout << "mu2:" << mu2 << std::endl; + std::cout << "beta:" << beta << std::endl; + log << "----- Input Parameters -----: " << std::endl; + log << "gamma: " << gamma << std::endl; + log << "theta: " << theta << std::endl; + log << "beta: " << beta << std::endl; + log << "material parameters: " << std::endl; + log << "mu1: " << mu1 << "\nmu2: " << mu2 << std::endl; + + // auto muTerm = [mu1, mu2, theta] (const Domain& z) { + // + // // if (abs(z[0]) > (theta/2.0)) + // if (abs(z[0]) >= (theta/2.0)) + // return mu1; + // else + // return mu2; + // }; + + auto materialImp = IsotropicMaterialImp<dim>(); + auto muTerm = materialImp.getMu(parameterSet); + auto muGridF = Dune::Functions::makeGridViewFunction(muTerm, gridView); + auto muLocal = localFunction(muGridF); + + + ///////////////////////////////////////////////////////// + // Stiffness matrix and right hand side vector + ///////////////////////////////////////////////////////// + using Vector = BlockVector<FieldVector<double,1> >; + using Matrix = BCRSMatrix<FieldMatrix<double,1,1> >; + Matrix stiffnessMatrix; + Vector b; + + ///////////////////////////////////////////////////////// + // Assemble the system + ///////////////////////////////////////////////////////// + using namespace Functions::BasisFactory; + Functions::BasisFactory::Experimental::PeriodicIndexSet periodicIndices; + + // Don't do the following in real life: It has quadratic run-time in the number of vertices. + for (const auto& v1 : vertices(gridView)) + for (const auto& v2 : vertices(gridView)) + if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0))) + periodicIndices.unifyIndexPair({gridView.indexSet().index(v1)}, {gridView.indexSet().index(v2)}); + + auto basis = makeBasis(gridView, Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices)); // flatLexicographic()? + + + auto forceTerm = [](const FieldVector<double,dim>& x){ + return x[1]; + }; //2D-Version + auto ForceGridF = Dune::Functions::makeGridViewFunction(forceTerm, gridView); + auto ForceLocal = localFunction(ForceGridF); + + assemblePoissonProblem(basis, stiffnessMatrix, b, muLocal, forceTerm, gamma); + // printmatrix(std::cout, stiffnessMatrix, "StiffnessMatrix", "--"); + // printvector(std::cout, b, "b", "--"); + + + + + + + /////////////////////////// + // Compute solution + /////////////////////////// + + Vector x(basis.size()); + x = b; + + std::cout << "------------ CG - Solver ------------" << std::endl; + MatrixAdapter<Matrix, Vector, Vector> op(stiffnessMatrix); + + + + // Sequential incomplete LU decomposition as the preconditioner + SeqILU<Matrix, Vector, Vector> ilu0(stiffnessMatrix,1.0); + int iter = parameterSet.get<double>("iterations_CG", 999); + // Preconditioned conjugate-gradient solver + CGSolver<Vector> solver(op, + ilu0, //NULL, + 1e-8, // desired residual reduction factorlack + iter, // maximum number of iterations + 2); // verbosity of the solver + InverseOperatorResult statistics; + // Solve! + solver.apply(x, b, statistics); + + // std::cout << "------------ GMRES - Solver ------------" << std::endl; + // // Turn the matrix into a linear operator + // MatrixAdapter<Matrix, Vector, Vector> op(stiffnessMatrix); + // + // // Fancy (but only) way to not have a preconditioner at all + // Richardson<Vector,Vector> preconditioner(1.0); + // + // // Construct the iterative solver + // RestartedGMResSolver<Vector> solver( + // op, // Operator to invert + // preconditioner, // Preconditioner + // 1e-10, // Desired residual reduction factor + // 500, // Number of iterations between restarts, + // // here: no restarting + // 500, // Maximum number of iterations + // 2); // Verbosity of the solver + // + // // Object storing some statistics about the solving process + // InverseOperatorResult statistics; + // + // // solve for different Correctors (alpha = 1,2,3) + // solver.apply(x, b, statistics); + // + + // ----------------------------------------------------------------------------------------------------- + + + using SolutionRange = double; + auto solutionFunction = Functions::makeDiscreteGlobalBasisFunction<SolutionRange>(basis, x); + + + // -------- PRINT OUTPUT -------- + // printvector(std::cout, x, "coeffVector", "--" ); + std::cout << "Gamma:" << gamma << std::endl; + double mu_gamma = computeMuGamma(basis, x, gamma, muLocal, ForceLocal); + std::cout << "mu_gamma:" << mu_gamma << std::endl; + log << "----- OUTPUT: -----: " << std::endl; + log << "mu_gamma=" << mu_gamma << std::endl; + log << "q3=" << mu_gamma << std::endl; + + // std::cout.precision(10); + // std::cout << "mu_gamma:" << std::fixed << mu_gamma << std::endl; + + + + // Vector zeroVec(basis.size()); + // zeroVec = 0; + // std::cout << "TEST computeMuGamma:" << computeMuGamma(basis, zeroVec, gamma, muLocal, ForceLocal)<< std::endl; + std::cout << " --- print analytic solutions(if possible) --- " << std::endl; + if (imp == "analytical_Example") + { + std::cout<< "analytical_Example" << std::endl; + double q1 = ((mu1*mu2)/6.0)/(theta*mu1+ (1.0- theta)*mu2); + double q2 = ((1.0-theta)*mu1+theta*mu2)/6.0; + double hm = mu1*(beta/(theta+(1-theta)*beta)) *(1.0/6.0); + double am = mu1*((1-theta)+theta*beta) *(1.0/6.0); + std::cout << "q1 : " << q1 << std::endl; + std::cout << "q2 : " << q2 << std::endl; + std::cout << "q3 should be between q1 and q2" << std::endl; + std::cout << "hm : " << hm << std::endl; + std::cout << "am : " << am << std::endl; + if(mu_gamma > q2) { - std::cout<< "analytical_Example" << std::endl; - double q1 = ((mu1*mu2)/6.0)/(theta*mu1+ (1.0- theta)*mu2); - double q2 = ((1.0-theta)*mu1+theta*mu2)/6.0; - double hm = mu1*(beta/(theta+(1-theta)*beta)) *(1.0/6.0); - double am = mu1*((1-theta)+theta*beta) *(1.0/6.0); - std::cout << "q1 : " << q1 << std::endl; - std::cout << "q2 : " << q2 << std::endl; - std::cout << "q3 should be between q1 and q2" << std::endl; - std::cout << "hm : " << hm << std::endl; - std::cout << "am : " << am << std::endl; - if(mu_gamma > q2) - { - std::cout << "mu_gamma > q2!!.. (39) not satisfied" << std::endl; - } + std::cout << "mu_gamma > q2!!.. (39) not satisfied" << std::endl; } - if (imp == "parametrized_Laminate") + } + if (imp == "parametrized_Laminate") + { + std::cout<< "parametrized_Laminate" << std::endl; + double hm = mu1*(beta/(theta+(1-theta)*beta)); + double am = mu1*((1-theta)+theta*beta); + double q1 = (1.0/6.0)*hm; + double q2 = (1.0/6.0)*am; + std::cout << "q1 : " << q1 << std::endl; + std::cout << "q2 : " << q2 << std::endl; + std::cout << "q3 should be between q1 and q2" << std::endl; + std::cout << "hm : " << hm << std::endl; + std::cout << "am : " << am << std::endl; + if(mu_gamma > q2) { - std::cout<< "parametrized_Laminate" << std::endl; - double hm = mu1*(beta/(theta+(1-theta)*beta)); - double am = mu1*((1-theta)+theta*beta); - double q1 = (1.0/6.0)*hm; - double q2 = (1.0/6.0)*am; - std::cout << "q1 : " << q1 << std::endl; - std::cout << "q2 : " << q2 << std::endl; - std::cout << "q3 should be between q1 and q2" << std::endl; - std::cout << "hm : " << hm << std::endl; - std::cout << "am : " << am << std::endl; - if(mu_gamma > q2) - { - std::cout << "mu_gamma > q2!!.. (39) not satisfied" << std::endl; - } + std::cout << "mu_gamma > q2!!.. (39) not satisfied" << std::endl; } - - - - std::cout << "beta : " << beta << std::endl; - std::cout << "theta : " << theta << std::endl; - std::cout << "Gamma : " << gamma << std::endl; - std::cout << "mu_gamma:" << mu_gamma << std::endl; - - - // Output result - - std::string VTKOutputName = outputPath + "/Compute_MuGamma-Result"; - - VTKWriter<GridView> vtkWriter(gridView); -// vtkWriter.addVertexData(x, "solution"); //--- Anpassen für P2 - vtkWriter.addVertexData( - solutionFunction, - VTK::FieldInfo("solution", VTK::FieldInfo::Type::scalar, 1)); -// VTK::FieldInfo("solution", VTK::FieldInfo::Type::vector, dim)); - - vtkWriter.write( VTKOutputName ); - std::cout << "wrote data to file: " + VTKOutputName << std::endl; - - - - 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},{64,64}); - using GridViewVTK = VTKGridType::LeafGridView; - const GridViewVTK gridView_VTK = grid_VTK.leafGridView(); - - auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>()); - - std::vector<double> mu_CoeffP0; - Functions::interpolate(scalarP0FeBasis, mu_CoeffP0, muTerm); - auto mu_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, mu_CoeffP0); - - VTKWriter<GridView> MaterialVtkWriter(gridView_VTK); - - MaterialVtkWriter.addCellData( - mu_DGBF_P0, - VTK::FieldInfo("mu_P0", VTK::FieldInfo::Type::scalar, 1)); - - MaterialVtkWriter.write(outputPath + "/MaterialFunctions" ); - std::cout << "wrote data to file:" + outputPath + "/MaterialFunctions" << std::endl; - - log.close(); - + } + + + + std::cout << "beta : " << beta << std::endl; + std::cout << "theta : " << theta << std::endl; + std::cout << "Gamma : " << gamma << std::endl; + std::cout << "mu_gamma:" << mu_gamma << std::endl; + + + // Output result + + std::string VTKOutputName = outputPath + "/Compute_MuGamma-Result"; + + VTKWriter<GridView> vtkWriter(gridView); + // vtkWriter.addVertexData(x, "solution"); //--- Anpassen für P2 + vtkWriter.addVertexData( + solutionFunction, + VTK::FieldInfo("solution", VTK::FieldInfo::Type::scalar, 1)); + // VTK::FieldInfo("solution", VTK::FieldInfo::Type::vector, dim)); + + vtkWriter.write( VTKOutputName ); + std::cout << "wrote data to file: " + VTKOutputName << std::endl; + + + + 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},{64,64}); + using GridViewVTK = VTKGridType::LeafGridView; + const GridViewVTK gridView_VTK = grid_VTK.leafGridView(); + + auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>()); + + std::vector<double> mu_CoeffP0; + Functions::interpolate(scalarP0FeBasis, mu_CoeffP0, muTerm); + auto mu_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, mu_CoeffP0); + + VTKWriter<GridView> MaterialVtkWriter(gridView_VTK); + + MaterialVtkWriter.addCellData( + mu_DGBF_P0, + VTK::FieldInfo("mu_P0", VTK::FieldInfo::Type::scalar, 1)); + + MaterialVtkWriter.write(outputPath + "/MaterialFunctions" ); + std::cout << "wrote data to file:" + outputPath + "/MaterialFunctions" << std::endl; + + log.close(); + } diff --git a/src/micro-problem.cc b/src/micro-problem.cc index ca4ccf85f0891da6ff6771c2cd02be38bf432f73..a5e5a55077e285c22f1d95e6fc0b9bbca743510e 100644 --- a/src/micro-problem.cc +++ b/src/micro-problem.cc @@ -12,7 +12,7 @@ #include <dune/common/float_cmp.hh> #include <dune/common/math.hh> #include <dune/common/fvector.hh> -#include <dune/common/fmatrix.hh> +#include <dune/common/fmatrix.hh> #include <dune/geometry/quadraturerules.hh> @@ -29,7 +29,7 @@ #include <dune/istl/spqr.hh> #include <dune/istl/preconditioners.hh> #include <dune/istl/io.hh> -#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number +#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/functions/functionspacebases/interpolate.hh> #include <dune/functions/backends/istlvectorbackend.hh> @@ -45,11 +45,11 @@ #include <dune/fufem/dunepython.hh> #include <dune/microstructure/matrix_operations.hh> -#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/solvers/solvers/umfpacksolver.hh> //TEST #include <any> #include <variant> @@ -60,7 +60,7 @@ using namespace Dune; using namespace MatrixOperations; -using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3>>::LeafGridView; +using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3> >::LeafGridView; ////////////////////////////////////////////////////////////////////// // Helper functions for Table-Output @@ -68,28 +68,28 @@ using GridView = Dune::YaspGrid<3, Dune::EquidistantOffsetCoordinates<double, 3> /*! Center-aligns string within a field of width w. Pads with blank spaces to enforce alignment. */ std::string center(const std::string s, const int w) { - std::stringstream ss, spaces; - int padding = w - s.size(); // count excess room to pad - for(int i=0; i<padding/2; ++i) - spaces << " "; - ss << spaces.str() << s << spaces.str(); // format with padding - if(padding>0 && padding%2!=0) // if odd #, add 1 space - ss << " "; - return ss.str(); + std::stringstream ss, spaces; + int padding = w - s.size(); // count excess room to pad + for(int i=0; i<padding/2; ++i) + spaces << " "; + ss << spaces.str() << s << spaces.str(); // format with padding + if(padding>0 && padding%2!=0) // if odd #, add 1 space + ss << " "; + return ss.str(); } /* Convert double to string with specified number of places after the decimal and left padding. */ template<class type> std::string prd(const type x, const int decDigits, const int width) { - std::stringstream ss; -// ss << std::fixed << std::right; - ss << std::scientific << std::right; // Use scientific Output! - ss.fill(' '); // fill space around displayed # - ss.width(width); // set width around displayed # - ss.precision(decDigits); // set # places after decimal - ss << x; - return ss.str(); + std::stringstream ss; + // ss << std::fixed << std::right; + ss << std::scientific << std::right; // Use scientific Output! + ss.fill(' '); // fill space around displayed # + ss.width(width); // set width around displayed # + ss.precision(decDigits); // set # places after decimal + ss << x; + return ss.str(); } /** @@ -97,12 +97,12 @@ std::string prd(const type x, const int decDigits, const int width) { * 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])) - ); - }; + 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])) + ); + }; @@ -110,30 +110,30 @@ auto equivalent = [](const FieldVector<double,3>& x, const FieldVector<double,3> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { - feenableexcept(FE_INVALID); - MPIHelper::instance(argc, argv); - - Dune::Timer globalTimer; - - if (argc < 3) - DUNE_THROW(Exception, "Usage: ./Cell-Problem <python path> <python module without extension>"); - - // Start Python interpreter - Python::start(); - auto pyMain = Python::main(); - pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; - auto pyModule = pyMain.import(argv[2]); - - ParameterTree parameterSet; - pyModule.get("parameterSet").toC(parameterSet); - // read possible further parameters from the command line - ParameterTreeParser::readOptions(argc, argv, parameterSet); - // Print all parameters, to make them appear in the log file - std::cout << "Input parameters:" << std::endl; - parameterSet.report(); + feenableexcept(FE_INVALID); + MPIHelper::instance(argc, argv); + + Dune::Timer globalTimer; + + if (argc < 3) + DUNE_THROW(Exception, "Usage: ./Cell-Problem <python path> <python module without extension>"); + + // Start Python interpreter + Python::start(); + auto pyMain = Python::main(); + pyMain.runStream() + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; + auto pyModule = pyMain.import(argv[2]); + + ParameterTree parameterSet; + pyModule.get("parameterSet").toC(parameterSet); + // read possible further parameters from the command line + ParameterTreeParser::readOptions(argc, argv, parameterSet); + // Print all parameters, to make them appear in the log file + std::cout << "Input parameters:" << std::endl; + parameterSet.report(); //--- Output setter std::string baseName = parameterSet.get("baseName", "CellProblem-result"); @@ -144,153 +144,153 @@ int main(int argc, char *argv[]) constexpr int dim = 3; - // Debug/Print Options + // Debug/Print Options bool print_debug = parameterSet.get<bool>("print_debug", false); // VTK-write options // bool write_prestrainFunctions = parameterSet.get<bool>("write_prestrainFunctions", false); //Not implemented yet. /** - * @brief 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}); - -// std::array<int,2> numLevels = parameterSet.get<std::array<int,2>>("numLevels", {3,3}); -// int levelCounter = 0; - -Dune::FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0}); -Dune::FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0}); -int microGridLevel = parameterSet.get<int>("microGridLevel", 1); -std::array<int, dim> nElements = {(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel)}; -// std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; -std::cout << "Number of Grid-Elements in each direction: " << (int)std::pow(2,microGridLevel) << std::endl; - - + * @brief 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}); + + // std::array<int,2> numLevels = parameterSet.get<std::array<int,2>>("numLevels", {3,3}); + // int levelCounter = 0; + + Dune::FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0}); + Dune::FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0}); + int microGridLevel = parameterSet.get<int>("microGridLevel", 1); + std::array<int, dim> nElements = {(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel) ,(int)std::pow(2,microGridLevel)}; + // std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; + std::cout << "Number of Grid-Elements in each direction: " << (int)std::pow(2,microGridLevel) << std::endl; + + /////////////////////////////////// // Create Data Storage /////////////////////////////////// //--- Storage:: #1 level #2 L2SymError #3 L2SymErrorOrder #4 L2Norm(sym) #5 L2Norm(sym-analytic) #6 L2Norm(phi_1) - //std::vector<std::variant<std::string, size_t , double>> Storage_Error; - //--- Storage:: | level | q1 | q2 | q3 | q12 | q13 | q23 | b1 | b2 | b3 | -// std::vector<std::variant<std::string, size_t , double>> Storage_Quantities; + //std::vector<std::variant<std::string, size_t , double>> Storage_Error; + //--- Storage:: | level | q1 | q2 | q3 | q12 | q13 | q23 | b1 | b2 | b3 | + // std::vector<std::variant<std::string, size_t , double>> Storage_Quantities; //--- GridLevel-Loop: -// for(size_t level = numLevels[0] ; level <= numLevels[1]; level++) -// { -// std::cout << " ----------------------------------" << std::endl; -// std::cout << "GridLevel: " << level << std::endl; -// std::cout << " ----------------------------------" << std::endl; - -// // Storage_Error.push_back(level); -// Storage_Quantities.push_back(level); -// std::array<int, dim> nElements = {(int)std::pow(2,level) ,(int)std::pow(2,level) ,(int)std::pow(2,level)}; -// std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; -// log << "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(); - if(print_debug) - std::cout << "Host grid has " << gridView_CE.size(dim) << " vertices." << std::endl; - - //--- 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)}); - } - - Dune::Timer basisSetupTimer; - //--- Setup first order periodic Lagrange-Basis - auto Basis_CE = makeBasis( - gridView_CE, - power<dim>( - Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), - flatLexicographic() - //blockedInterleaved() // Not Implemented - )); - std::cout << "Basis setup took " << basisSetupTimer.elapsed() << " seconds " << std::endl; - - if(print_debug) - std::cout << "power<periodic> basis has " << Basis_CE.dimension() << " degrees of freedom" << std::endl; - - - - // ------------------------------------------------------- - // This needs to be declared as Callable otherwise Class(param) wont work. if _call__(self,x) is not implemented - Python::Callable MicrostructureClass = pyModule.get("Microstructure"); - - // Create instance of class - // This needs to be a 'Python::Reference' and not 'Python::Callable' since Callable only works if __call__(self,x) is implemented in the python module!!! - // Python::Reference microstructure = MicrostructureClass(2); - - //Setup for a constant microstructure. - Python::Reference microstructure = MicrostructureClass(); - - /////////////////////////////////// - // Create prestrained material object - /////////////////////////////////// - Dune::Timer materialSetupTimer; - - using MaterialType = prestrainedMaterial<GridView>; - - // auto material = prestrainedMaterial(gridView_CE,parameterSet,pyModule); - // auto material = prestrainedMaterial(gridView_CE,microstructure,parameterSet,pyModule); - std::shared_ptr<MaterialType> material = std::make_shared<MaterialType>(gridView_CE,microstructure,parameterSet,pyModule); - std::cout << "Material setup took " << materialSetupTimer.elapsed() << " seconds " << std::endl; - - // --- Get scale ratio - // double gamma = parameterSet.get<double>("gamma",1.0); - std::cout << "scale ratio (gamma) set to : " << material->gamma_ << std::endl; - - //--- Compute Correctors - // auto correctorComputer = CorrectorComputer(Basis_CE, material, log, parameterSet); - // auto correctorComputer = CorrectorComputer(Basis_CE, materialPointer, log, parameterSet); - std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType>>(Basis_CE, material, parameterSet); - correctorComputer->assemble(); - correctorComputer->solve(); - - //--- Check Correctors (options): - if(parameterSet.get<bool>("write_L2Error", false)) - correctorComputer->computeNorms(); - if(parameterSet.get<bool>("write_VTK", false)) - correctorComputer->writeCorrectorsVTK(microGridLevel); - //--- Additional Test: check orthogonality (75) from paper: - if(parameterSet.get<bool>("write_checkOrthogonality", false)) - correctorComputer->check_Orthogonality(); - //--- Check symmetry of stiffness matrix - if(print_debug) - correctorComputer->checkSymmetry(); - - //--- Compute effective quantities - // auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material); - auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer); - effectiveQuantitiesComputer.computeEffectiveQuantities(); - - //--- Write material indicator function to VTK - if (parameterSet.get<bool>("write_materialFunctions", false)) - material->writeVTKMaterialFunctions(microGridLevel); - - //--- Get effective quantities - auto Qeff = effectiveQuantitiesComputer.getQeff(); - auto Beff = effectiveQuantitiesComputer.getBeff(); - printmatrix(std::cout, Qeff, "Matrix Qeff", "--"); - printvector(std::cout, Beff, "Beff", "--"); - - - //--- Write effective quantities to matlab folder (for symbolic minimization) - if(parameterSet.get<bool>("write_EffectiveQuantitiesToTxt", true)) - effectiveQuantitiesComputer.writeEffectiveQuantitiesToTxt(resultPath); - - - - - std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; + // for(size_t level = numLevels[0] ; level <= numLevels[1]; level++) + // { + // std::cout << " ----------------------------------" << std::endl; + // std::cout << "GridLevel: " << level << std::endl; + // std::cout << " ----------------------------------" << std::endl; + + // // Storage_Error.push_back(level); + // Storage_Quantities.push_back(level); + // std::array<int, dim> nElements = {(int)std::pow(2,level) ,(int)std::pow(2,level) ,(int)std::pow(2,level)}; + // std::cout << "Number of Grid-Elements in each direction: " << nElements << std::endl; + // log << "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(); + if(print_debug) + std::cout << "Host grid has " << gridView_CE.size(dim) << " vertices." << std::endl; + + //--- 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)}); + } + + Dune::Timer basisSetupTimer; + //--- Setup first order periodic Lagrange-Basis + auto Basis_CE = makeBasis( + gridView_CE, + power<dim>( + Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices), + flatLexicographic() + //blockedInterleaved() // Not Implemented + )); + std::cout << "Basis setup took " << basisSetupTimer.elapsed() << " seconds " << std::endl; + + if(print_debug) + std::cout << "power<periodic> basis has " << Basis_CE.dimension() << " degrees of freedom" << std::endl; + + + + // ------------------------------------------------------- + // This needs to be declared as Callable otherwise Class(param) wont work. if _call__(self,x) is not implemented + Python::Callable MicrostructureClass = pyModule.get("Microstructure"); + + // Create instance of class + // This needs to be a 'Python::Reference' and not 'Python::Callable' since Callable only works if __call__(self,x) is implemented in the python module!!! + // Python::Reference microstructure = MicrostructureClass(2); + + //Setup for a constant microstructure. + Python::Reference microstructure = MicrostructureClass(); + + /////////////////////////////////// + // Create prestrained material object + /////////////////////////////////// + Dune::Timer materialSetupTimer; + + using MaterialType = prestrainedMaterial<GridView>; + + // auto material = prestrainedMaterial(gridView_CE,parameterSet,pyModule); + // auto material = prestrainedMaterial(gridView_CE,microstructure,parameterSet,pyModule); + std::shared_ptr<MaterialType> material = std::make_shared<MaterialType>(gridView_CE,microstructure,parameterSet,pyModule); + std::cout << "Material setup took " << materialSetupTimer.elapsed() << " seconds " << std::endl; + + // --- Get scale ratio + // double gamma = parameterSet.get<double>("gamma",1.0); + std::cout << "scale ratio (gamma) set to : " << material->gamma_ << std::endl; + + //--- Compute Correctors + // auto correctorComputer = CorrectorComputer(Basis_CE, material, log, parameterSet); + // auto correctorComputer = CorrectorComputer(Basis_CE, materialPointer, log, parameterSet); + std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType> >(Basis_CE, material, parameterSet); + correctorComputer->assemble(); + correctorComputer->solve(); + + //--- Check Correctors (options): + if(parameterSet.get<bool>("write_L2Error", false)) + correctorComputer->computeNorms(); + if(parameterSet.get<bool>("write_VTK", false)) + correctorComputer->writeCorrectorsVTK(microGridLevel); + //--- Additional Test: check orthogonality (75) from paper: + if(parameterSet.get<bool>("write_checkOrthogonality", false)) + correctorComputer->check_Orthogonality(); + //--- Check symmetry of stiffness matrix + if(print_debug) + correctorComputer->checkSymmetry(); + + //--- Compute effective quantities + // auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer,material); + auto effectiveQuantitiesComputer = EffectiveQuantitiesComputer(correctorComputer); + effectiveQuantitiesComputer.computeEffectiveQuantities(); + + //--- Write material indicator function to VTK + if (parameterSet.get<bool>("write_materialFunctions", false)) + material->writeVTKMaterialFunctions(microGridLevel); + + //--- Get effective quantities + auto Qeff = effectiveQuantitiesComputer.getQeff(); + auto Beff = effectiveQuantitiesComputer.getBeff(); + printmatrix(std::cout, Qeff, "Matrix Qeff", "--"); + printvector(std::cout, Beff, "Beff", "--"); + + + //--- Write effective quantities to matlab folder (for symbolic minimization) + if(parameterSet.get<bool>("write_EffectiveQuantitiesToTxt", true)) + effectiveQuantitiesComputer.writeEffectiveQuantitiesToTxt(resultPath); + + + + + std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; } diff --git a/test/analyticalcylindertest.cc b/test/analyticalcylindertest.cc index 4eb1b995812e197a773f46520122ccf2462439cd..f0f4587c07bd1548f840bafa29f08d7099fcb19b 100644 --- a/test/analyticalcylindertest.cc +++ b/test/analyticalcylindertest.cc @@ -78,10 +78,10 @@ using namespace Dune; * We consider the special case of a effective prestrain/spontaneous curvature Beff given by * Beff = [1.0 , 0.0] * [0.0 ,0.5] - * on a rectangular domain (0,2*pi)^2 with clampled boundary conditions. - * In this case there is a known exact solution (deformation) u(x,y) = (sin(x), y , 1-cos(x)) - * The analytical energy is given by E[u_ana] = (pi)^2/2.0 . - * That is used to validate the macroscopic minimization problem. + * on a rectangular domain (0,2*pi)^2 with clampled boundary conditions. + * In this case there is a known exact solution (deformation) u(x,y) = (sin(x), y , 1-cos(x)) + * The analytical energy is given by E[u_ana] = (pi)^2/2.0 . + * That is used to validate the macroscopic minimization problem. * (see Bartels,Bonito,Nochetto - Bilayer Plates: Model Reduction, Γ‐Convergent Finite Element Approximation, and Discrete Gradient Flow, p.25) * We measure/test the L2-error between the exact and discrete solution up to a certain tolerance. */ @@ -104,11 +104,11 @@ using namespace Dune; // for (const auto &element : elements(gridView)) // { // auto geometry = element.geometry(); - + // kirchhoffFunction.bind(element); // localDeformation.bind(element); -// localRotation.bind(element); -// localRotation_2.bind(element); +// localRotation.bind(element); +// localRotation_2.bind(element); // //evaluate at nodes: // for (int i=0; i<geometry.corners(); i++) @@ -127,7 +127,7 @@ using namespace Dune; // printvector(std::cout, defOut, "defOut:", "--"); // printmatrix(std::cout, KirchhoffRot, "KirchhoffRot:", "--"); // printmatrix(std::cout, defRot, "defRot:", "--"); -// // printmatrix(std::cout, defRot*jacobian, "defRot*jacobian:", "--"); // deprecated: when ReducedCubicHermite returned values in globalCoordinates, this was actually neccessary to get the right values. +// // printmatrix(std::cout, defRot*jacobian, "defRot*jacobian:", "--"); // deprecated: when ReducedCubicHermite returned values in globalCoordinates, this was actually neccessary to get the right values. // } // } // } @@ -327,7 +327,7 @@ using namespace Dune; // //cross product to get last column of rotation matrix // FieldVector<RT,3> cross = {currentDerivative_x[1]*currentDerivative_y[2] - currentDerivative_x[2]*currentDerivative_y[1], -// currentDerivative_x[2]*currentDerivative_y[0] - currentDerivative_x[0]*currentDerivative_y[2], +// currentDerivative_x[2]*currentDerivative_y[0] - currentDerivative_x[0]*currentDerivative_y[2], // currentDerivative_x[0]*currentDerivative_y[1] - currentDerivative_x[1]*currentDerivative_y[0]}; // FieldMatrix<RT,3,3> rotMatrix(0); @@ -386,9 +386,9 @@ using namespace Dune; // using namespace Dune::Indices; // auto deformation = isometryCoefficients[globalIdx][_0].globalCoordinates(); -// auto rotation1 = isometryCoefficients[globalIdx][_1].director(0); +// auto rotation1 = isometryCoefficients[globalIdx][_1].director(0); // auto rotation2 = isometryCoefficients[globalIdx][_1].director(1); - + // coefficients[globalIdxOut_0[0]][globalIdxOut_0[1]] = deformation[k]; // coefficients[globalIdxOut_1[0]][globalIdxOut_1[1]] = rotation1[k]; // coefficients[globalIdxOut_2[0]][globalIdxOut_2[1]] = rotation2[k]; @@ -402,12 +402,16 @@ int main(int argc, char *argv[]) { /** - * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' + * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' * in RiemannianProximalNewton */ - std::shared_ptr<void(int)> handler( - signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }), - [](__sighandler_t f) { signal(SIGFPE, f); }); + std::shared_ptr<void(int)> handler( + signal(SIGFPE, [](int signum) { + throw std::logic_error("FPE"); + }), + [](__sighandler_t f) { + signal(SIGFPE, f); + }); @@ -439,9 +443,9 @@ int main(int argc, char *argv[]) Python::start(); auto pyMain = Python::main(); pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; auto pyModule = pyMain.import("analyticalcylindertest"); // parse data file @@ -500,7 +504,7 @@ int main(int argc, char *argv[]) /////////////////////////////////////////////////////// // General coefficient vector of a Discrete Kirchhoff deformation function - using VectorSpaceCoefficients = BlockVector<FieldVector<double,3>>; + using VectorSpaceCoefficients = BlockVector<FieldVector<double,3> >; // Coefficient vector of a Discrete Kirchhoff deformation function that is constrained to be an isometry using Coefficient = GFE::ProductManifold<RealTuple<double,3>, Rotation<double,3> >; @@ -521,12 +525,12 @@ int main(int argc, char *argv[]) // A basis for the tangent space (used to set DirichletNodes) auto tangentBasis = makeBasis(gridView, power<Coefficient::TangentVector::dimension>( - lagrange<1>(), - blockedInterleaved())); + lagrange<1>(), + blockedInterleaved())); // /////////////////////////////////////////// - // // Read Dirichlet values + // // Read Dirichlet values // /////////////////////////////////////////// // BitSetVector<1> dirichletVertices(gridView.size(dim), false); // const typename GridView::IndexSet &indexSet = gridView.indexSet(); @@ -542,53 +546,53 @@ int main(int argc, char *argv[]) // BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); - /////////////////////////////////////////// - // Read Dirichlet values (NEW VERSION) - /////////////////////////////////////////// - BitSetVector<1> dirichletVertices(gridView.size(dim), false); - const typename GridView::IndexSet &indexSet = gridView.indexSet(); + /////////////////////////////////////////// + // Read Dirichlet values (NEW VERSION) + /////////////////////////////////////////// + BitSetVector<1> dirichletVertices(gridView.size(dim), false); + const typename GridView::IndexSet &indexSet = gridView.indexSet(); - BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); //tangentBasis.size()=coefficientBasis.size() + BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); //tangentBasis.size()=coefficientBasis.size() - /** + /** * @brief Make Python function that computes which vertices are on the Dirichlet boundary, * based on the vertex positions. */ - auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); + auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); /** - * @brief If we want to clamp DOFs inside the domain, we connot use 'BoundaryPatch' - * and 'constructBoundaryDofs'. This is a workaround for now. - * - * - */ + * @brief If we want to clamp DOFs inside the domain, we connot use 'BoundaryPatch' + * and 'constructBoundaryDofs'. This is a workaround for now. + * + * + */ for (auto &&vertex : vertices(gridView)) { dirichletVertices[indexSet.index(vertex)] = dirichletIndicatorFunction(vertex.geometry().corner(0)); - if(dirichletIndicatorFunction(vertex.geometry().corner(0))) - { - dirichletNodes[indexSet.index(vertex)] = true; - } - - } - - // std::cout << "tangentBasis.size():" << tangentBasis.size() << std::endl; - // std::cout << "coefficientBasis.size():" << coefficientBasis.size() << std::endl; + if(dirichletIndicatorFunction(vertex.geometry().corner(0))) + { + dirichletNodes[indexSet.index(vertex)] = true; + } + + } + + // std::cout << "tangentBasis.size():" << tangentBasis.size() << std::endl; + // std::cout << "coefficientBasis.size():" << coefficientBasis.size() << std::endl; - // // deprecated: - // // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); - // // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); + // // deprecated: + // // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); + // // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); - // // TEST: print dirichletNodes - // std::cout << "print dirichletVertices:" << std::endl; - // std::cout << dirichletVertices << std::endl; + // // TEST: print dirichletNodes + // std::cout << "print dirichletVertices:" << std::endl; + // std::cout << dirichletVertices << std::endl; - // std::cout << "print dirichletNodes:" << std::endl; - // std::cout << dirichletNodes << std::endl; + // std::cout << "print dirichletNodes:" << std::endl; + // std::cout << dirichletNodes << std::endl; @@ -613,8 +617,8 @@ int main(int argc, char *argv[]) /** - * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient - * vector of ctype 'adouble' while the solver gets a coefficient vector + * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient + * vector of ctype 'adouble' while the solver gets a coefficient vector * of ctype 'double'. */ IsometryCoefficients isometryCoefficients(coefficientBasis.size()); @@ -628,17 +632,17 @@ int main(int argc, char *argv[]) // isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients); - /** - * @brief Print coefficient vector: - */ - // for(int i=0; i<x.size(); i++) - // std::cout<< "x[i]:" << x[i] << std::endl; + /** + * @brief Print coefficient vector: + */ + // for(int i=0; i<x.size(); i++) + // std::cout<< "x[i]:" << x[i] << std::endl; - /** - * @brief TEST: compute isometry error - */ - auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x); - // nodewiseIsometryTest(initialDeformationFunction); + /** + * @brief TEST: compute isometry error + */ + auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x); + // nodewiseIsometryTest(initialDeformationFunction); @@ -648,21 +652,21 @@ int main(int argc, char *argv[]) - // /** - // * @brief TEST: conversion of coefficient vectors (back & forth) - // */ - // VectorSpaceCoefficients x_convert = x; - // IsometryCoefficients isometryCoefficientsTMP(coefficientBasis.size()); - // vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); - // isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); - // //Check difference - // for(int i=0; i<x.size(); i++) - // { - // if((x[i]-x_convert[i]).two_norm() > 1e-4) - // std::cout << "Coefficient conversion failed! with x[i]-x_convert[i]:" << x[i]-x_convert[i] << std::endl; - // } - - + // /** + // * @brief TEST: conversion of coefficient vectors (back & forth) + // */ + // VectorSpaceCoefficients x_convert = x; + // IsometryCoefficients isometryCoefficientsTMP(coefficientBasis.size()); + // vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); + // isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); + // //Check difference + // for(int i=0; i<x.size(); i++) + // { + // if((x[i]-x_convert[i]).two_norm() > 1e-4) + // std::cout << "Coefficient conversion failed! with x[i]-x_convert[i]:" << x[i]-x_convert[i] << std::endl; + // } + + using DeformationBasis = decltype(deformationBasis); @@ -674,7 +678,7 @@ int main(int argc, char *argv[]) /** * @brief Get force term */ - auto pythonForce = Python::make_function<FieldVector<double,3>>(pyModule.get("force")); + auto pythonForce = Python::make_function<FieldVector<double,3> >(pyModule.get("force")); // auto forceGVF = Dune::Functions::makeGridViewFunction(dummyForce, gridView); auto forceGVF = Dune::Functions::makeGridViewFunction(pythonForce, gridView); auto localForce = localFunction(forceGVF); @@ -692,7 +696,7 @@ int main(int argc, char *argv[]) // * @brief Get effective quadratic form // */ // Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); - // Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)Qhomvec[3], (adouble)Qhomvec[4]}, + // Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)Qhomvec[3], (adouble)Qhomvec[4]}, // {(adouble)Qhomvec[3], (adouble)Qhomvec[1], (adouble)Qhomvec[5]}, // {(adouble)Qhomvec[4], (adouble)Qhomvec[5], (adouble)Qhomvec[2]}}; // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--"); @@ -725,7 +729,7 @@ int main(int argc, char *argv[]) // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_prestrain(coefficientBasis, localGFEADOLCStiffness_prestrain); - auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule); + auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient> >(localDKFunction, localForce, parameterSet, pyModule); auto localGFEADOLCStiffness_prestrain = std::make_shared<LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> >(localEnergy_prestrain); std::shared_ptr<GeodesicFEAssembler<CoefficientBasis, Coefficient> > assembler_prestrain; assembler_prestrain = std::make_shared<GeodesicFEAssembler<CoefficientBasis, Coefficient> >(coefficientBasis, localGFEADOLCStiffness_prestrain); @@ -734,9 +738,9 @@ int main(int argc, char *argv[]) /** - * @brief Create a solver: - * - Riemannian Newton with Hessian modification - * - Riemannian Trust-region + * @brief Create a solver: + * - Riemannian Newton with Hessian modification + * - Riemannian Trust-region */ RiemannianProximalNewtonSolver<CoefficientBasis, Coefficient> RNHMsolver; RiemannianTrustRegionSolver<CoefficientBasis, Coefficient> RTRsolver; @@ -749,10 +753,10 @@ int main(int argc, char *argv[]) { RNHMsolver.setup(*grid, - &(*assembler_prestrain), - isometryCoefficients, - dirichletNodes, - parameterSet); + &(*assembler_prestrain), + isometryCoefficients, + dirichletNodes, + parameterSet); RNHMsolver.solve(); isometryCoefficients = RNHMsolver.getSol(); @@ -761,15 +765,15 @@ int main(int argc, char *argv[]) { std::cout << "Using Riemannian Trust-region method for energy minimization." << std::endl; RTRsolver.setup(*grid, - &(*assembler_prestrain), - isometryCoefficients, - dirichletNodes, - parameterSet); + &(*assembler_prestrain), + isometryCoefficients, + dirichletNodes, + parameterSet); RTRsolver.solve(); isometryCoefficients = RTRsolver.getSol(); numerical_energy = RTRsolver.getStatistics().finalEnergy; - } else - DUNE_THROW(Dune::Exception, "Unknown Solver type for bending isometries."); + } else + DUNE_THROW(Dune::Exception, "Unknown Solver type for bending isometries."); // Convert coefficient data structure from 'IsometryCoefficients' to 'VectorSpaceCoefficients' @@ -782,16 +786,16 @@ int main(int argc, char *argv[]) std::string baseNameDefault = "bending-isometries-"; std::string baseName = parameterSet.get("baseName", baseNameDefault); std::string resultFileName = parameterSet.get("resultPath", "") - + "/" + baseName - + "_level" + std::to_string(parameterSet.get<int>("numLevels")); + + "/" + baseName + + "_level" + std::to_string(parameterSet.get<int>("numLevels")); if (parameterSet.get<bool>("conforming_DiscreteJacobian", 1)) resultFileName = resultFileName + "_C"; - else + else resultFileName = resultFileName + "_NC"; - // Create a deformation function but this time with double-types. + // Create a deformation function but this time with double-types. using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; LocalDKFunctionD localDKFunctionDouble(deformationBasis, coefficientBasis, isometryCoefficients); @@ -814,8 +818,8 @@ int main(int argc, char *argv[]) displacement -= identity; // std::cout << "displacement.size():" << displacement.size() << std::endl; - auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x_out); - auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacement); + auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x_out); + auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, displacement); /** * @brief We need to subsample, because VTK cannot natively display real third-order functions @@ -828,29 +832,29 @@ int main(int argc, char *argv[]) /** * @brief Basis used to represent normal vector fields - * + * */ auto normalBasis = makeBasis(gridView, - power<3>( - lagrange<1>(), - flatLexicographic())); + power<3>( + lagrange<1>(), + flatLexicographic())); // auto normalBasis = makeBasis(gridView, // power<3>( // lagrange<1>(), // blockedInterleaved())); - // TEST Compute + // TEST Compute // auto normalLambda = [deformationFunction](const FieldVector<double,2>& x) // { // // deformationfunction.derivative() ... //needs binding?! - + // } - + /** @@ -878,38 +882,38 @@ int main(int argc, char *argv[]) // auto deformationFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, y); // vtkWriter.addVertexData(displacementFunctionAnalytical, VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); // vtkWriter.addVertexData(deformationFunctionAnalytical, VTK::FieldInfo("deformation_analytical", VTK::FieldInfo::Type::vector, 3)); - + vtkWriter.addVertexData((pythonAnalyticalSolution), VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); /** - * @brief Get the normal vector field of the surface parametrized + * @brief Get the normal vector field of the surface parametrized * by the analytical solution. * - We represent the normal vector in a first order Lagrange-Power basis ('normalBasis'). */ if (parameterSet.get<bool>("vtkWrite_analyticalSurfaceNormal", 0)) { - // Get the surface normal function. - auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3>>(pyModule.get("surfaceNormal")); + // Get the surface normal function. + auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3> >(pyModule.get("surfaceNormal")); - // deprecated: interpolate ... - // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); - // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); - // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); - // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); + // deprecated: interpolate ... + // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); + // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); + // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); + // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); - vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); + vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); } } //------------------------------------------------------------------------------------- TODO: OUTSOURCE /** - * @brief TEST: Compute the discrete normal vector of the surface parametrized + * @brief TEST: Compute the discrete normal vector of the surface parametrized * by the discrete solution. */ - auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); + auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); //------------------------------------------------------------------------------------- // Create DiscreteGlobalBasisFunctions. - auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, surfaceNormalDiscreteCoefficients); + auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(normalBasis, surfaceNormalDiscreteCoefficients); vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::vector, 3)); vtkWriter.addVertexData(surfaceNormalDiscrete , VTK::FieldInfo("surfaceNormal_discrete", VTK::FieldInfo::Type::vector, 3)); vtkWriter.write(resultFileName); @@ -919,134 +923,134 @@ int main(int argc, char *argv[]) /** * @brief Measure errors. - * Compute the L2-Error and H1-SemiError as well as the energy difference + * Compute the L2-Error and H1-SemiError as well as the energy difference * between the discrete deformation u_h and the analytical deformation u . */ - // auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x_out); - // auto localNumericalSolution = localFunction(deformationFunction); - // auto localNumericalSolutionDerivative = derivative(localNumericalSolution); + // auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x_out); + // auto localNumericalSolution = localFunction(deformationFunction); + // auto localNumericalSolutionDerivative = derivative(localNumericalSolution); - // // Read reference solution and its derivative into a Python function - // using Domain = FieldVector<double, dim>; - // using Range = typename Coefficient::CoordinateType; - // using Range = typename FieldVector<double,3>; - // auto referenceSolution = Python::makeDifferentiableFunction<Range(Domain)>(pyModule.get("udu")); - // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(Domain)>(pyModule.get("udu")); - // auto referenceDerivative = derivative(referenceSolution); - // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); - auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); - auto referenceDerivative = derivative(referenceSolution); + // // Read reference solution and its derivative into a Python function + // using Domain = FieldVector<double, dim>; + // using Range = typename Coefficient::CoordinateType; + // using Range = typename FieldVector<double,3>; + // auto referenceSolution = Python::makeDifferentiableFunction<Range(Domain)>(pyModule.get("udu")); + // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(Domain)>(pyModule.get("udu")); + // auto referenceDerivative = derivative(referenceSolution); + // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); + auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); + auto referenceDerivative = derivative(referenceSolution); - using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; - LocalDKFunctionD localDKFunctionD(deformationBasis, coefficientBasis, isometryCoefficients); + using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; + LocalDKFunctionD localDKFunctionD(deformationBasis, coefficientBasis, isometryCoefficients); - // typedef VirtualDifferentiableFunction<FieldVector<double, dim>, typename Coefficient::CoordinateType> FBase; - // auto referenceSolution = pyModule.get("udu").toC<std::shared_ptr<FBase>>(); + // typedef VirtualDifferentiableFunction<FieldVector<double, dim>, typename Coefficient::CoordinateType> FBase; + // auto referenceSolution = pyModule.get("udu").toC<std::shared_ptr<FBase>>(); - // QuadratureRule for the integral of the L^2 error - QuadratureRuleKey quadKey(dim,6); + // QuadratureRule for the integral of the L^2 error + QuadratureRuleKey quadKey(dim,6); - // Trapezoidal-rule: - // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} }; - // std::cout << "Use Trapezoidal-rule." << std::endl; + // Trapezoidal-rule: + // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} }; + // std::cout << "Use Trapezoidal-rule." << std::endl; - // The error to be computed - double l2ErrorSquared = 0; - double h1ErrorSquared = 0; + // The error to be computed + double l2ErrorSquared = 0; + double h1ErrorSquared = 0; - for (auto&& element : elements(gridView)) - { + for (auto&& element : elements(gridView)) + { - // localNumericalSolution.bind(element); + // localNumericalSolution.bind(element); - localDKFunctionD.bind(element); + localDKFunctionD.bind(element); - // Get quadrature formula - quadKey.setGeometryType(element.type()); - const auto& quadRule = QuadratureRuleCache<double, dim>::rule(quadKey); + // Get quadrature formula + quadKey.setGeometryType(element.type()); + const auto& quadRule = QuadratureRuleCache<double, dim>::rule(quadKey); - for (auto quadPoint : quadRule) - { - auto quadPos = quadPoint.position(); - const auto integrationElement = element.geometry().integrationElement(quadPos); - const auto weight = quadPoint.weight(); + for (auto quadPoint : quadRule) + { + auto quadPos = quadPoint.position(); + const auto integrationElement = element.geometry().integrationElement(quadPos); + const auto weight = quadPoint.weight(); - // auto numValue = localNumericalSolution(quadPos); - auto refValue = referenceSolution(element.geometry().global(quadPos)); - auto numValue = localDKFunctionD.evaluate(quadPos).globalCoordinates(); + // auto numValue = localNumericalSolution(quadPos); + auto refValue = referenceSolution(element.geometry().global(quadPos)); + auto numValue = localDKFunctionD.evaluate(quadPos).globalCoordinates(); - // printvector(std::cout, numValue, "numValue: ", "--"); - // printvector(std::cout, refValue, "refValue: ", "--"); + // printvector(std::cout, numValue, "numValue: ", "--"); + // printvector(std::cout, refValue, "refValue: ", "--"); - auto numDir = localDKFunctionD.evaluateDerivative(quadPos); - auto refDir = referenceDerivative(element.geometry().global(quadPos)); - auto diff = numDir - refDir; + auto numDir = localDKFunctionD.evaluateDerivative(quadPos); + auto refDir = referenceDerivative(element.geometry().global(quadPos)); + auto diff = numDir - refDir; - - // constexpr int blocksize = Coefficient::CoordinateType::dimension; - // FieldVector<double, blocksize> refValue; - // if (std::dynamic_pointer_cast<const VirtualGridViewFunction<GridView, FieldVector<double, blocksize>>>(referenceSolution)) - // std::dynamic_pointer_cast<const VirtualGridViewFunction<GridView, FieldVector<double, blocksize>>>(referenceSolution)->evaluateLocal(element, quadPos, refValue); - // else - // referenceSolution->evaluate(element.geometry().global(quadPos), refValue); + // constexpr int blocksize = Coefficient::CoordinateType::dimension; - // integrate error - l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; - h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; - } + // FieldVector<double, blocksize> refValue; + // if (std::dynamic_pointer_cast<const VirtualGridViewFunction<GridView, FieldVector<double, blocksize>>>(referenceSolution)) + // std::dynamic_pointer_cast<const VirtualGridViewFunction<GridView, FieldVector<double, blocksize>>>(referenceSolution)->evaluateLocal(element, quadPos, refValue); + // else + // referenceSolution->evaluate(element.geometry().global(quadPos), refValue); + + // integrate error + l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; + h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; } - std::cout << "elements: " << gridView.size(0) - << " " - << "L^2 error: " << std::sqrt(l2ErrorSquared) - << " "; - std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; + } + std::cout << "elements: " << gridView.size(0) + << " " + << "L^2 error: " << std::sqrt(l2ErrorSquared) + << " "; + std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; - //Check Quantities - if(std::sqrt(l2ErrorSquared) > 1.0) - { - std::cerr << std::setprecision(9); - std::cerr << "L2-error is to large! " << std::endl; - return 1; - } - if(std::sqrt(h1ErrorSquared) > 1.0) - { - std::cerr << std::setprecision(9); - std::cerr << "H1-error is to large! " << std::endl; - return 1; - } - // Compare energy values. - // auto numerical_energy = solver.getStatistics().finalEnergy; - // auto analytical_energy = (M_PI*M_PI)/2.0 ; - // auto analytical_energy = (M_PI*M_PI); - std::cout << "(Final) Energy of discrete solution: " << numerical_energy<< std::endl; - if (parameterSet.get<bool>("compare_EnergyValues", 0)) + //Check Quantities + if(std::sqrt(l2ErrorSquared) > 1.0) + { + std::cerr << std::setprecision(9); + std::cerr << "L2-error is to large! " << std::endl; + return 1; + } + if(std::sqrt(h1ErrorSquared) > 1.0) + { + std::cerr << std::setprecision(9); + std::cerr << "H1-error is to large! " << std::endl; + return 1; + } + // Compare energy values. + // auto numerical_energy = solver.getStatistics().finalEnergy; + // auto analytical_energy = (M_PI*M_PI)/2.0 ; + // auto analytical_energy = (M_PI*M_PI); + std::cout << "(Final) Energy of discrete solution: " << numerical_energy<< std::endl; + if (parameterSet.get<bool>("compare_EnergyValues", 0)) + { + auto analytical_energy = parameterSet.get<double>("analytical_energy"); + auto energy_difference = std::abs(analytical_energy - numerical_energy); + std::cout << "Analytical energy:" << analytical_energy<< std::endl; // (pi^2)/2.0 + std::cout << "Energy difference: " << energy_difference << std::endl; + + if(energy_difference > 1.0) { - auto analytical_energy = parameterSet.get<double>("analytical_energy"); - auto energy_difference = std::abs(analytical_energy - numerical_energy); - std::cout << "Analytical energy:" << analytical_energy<< std::endl; // (pi^2)/2.0 - std::cout << "Energy difference: " << energy_difference << std::endl; - - if(energy_difference > 1.0) - { - std::cerr << std::setprecision(9); - std::cerr << "Energy difference: " << energy_difference << " is to large! " << std::endl; - return 1; - } + std::cerr << std::setprecision(9); + std::cerr << "Energy difference: " << energy_difference << " is to large! " << std::endl; + return 1; } + } std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; std::cout << "Test: analyticalcylindertest passed." << std::endl; return 0; - } \ No newline at end of file +} diff --git a/test/hermitebasis-evaluation-test.cc b/test/hermitebasis-evaluation-test.cc index 96de70cbe1974dac9681c406d0c25c6d5939c861..3016ce176331c0f4b5e344aa91c81131db556c1c 100644 --- a/test/hermitebasis-evaluation-test.cc +++ b/test/hermitebasis-evaluation-test.cc @@ -64,7 +64,7 @@ using namespace Dune; /** * @brief Test the interpolation in deformation space. * A linear isometry can be represented exactly in that space. - * compare energy values / L2-error / H1-error + * compare energy values / L2-error / H1-error * for die difference | I_h[u] - u | where u is a given analytic linear isometry */ @@ -84,9 +84,9 @@ int main(int argc, char *argv[]) Python::start(); auto pyMain = Python::main(); pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; auto pyModule = pyMain.import("hermitebasis-evaluation-test"); // parse data file @@ -105,8 +105,8 @@ int main(int argc, char *argv[]) ///////////////////////////////////////// using GridType = UGGrid<dim>; std::shared_ptr<GridType> grid; -// FieldVector<double,dim> lower(0), upper(1); -// std::array<unsigned int,dim> elementsArray; + // FieldVector<double,dim> lower(0), upper(1); + // std::array<unsigned int,dim> elementsArray; // create unstructured grid. std::cout << "Read GMSH grid." << std::endl; @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) /////////////////////////////////////////////////////// // General coefficient vector of a Discrete Kirchhoff deformation function - using VectorSpaceCoefficients = BlockVector<FieldVector<double,3>>; + using VectorSpaceCoefficients = BlockVector<FieldVector<double,3> >; using namespace Functions::BasisFactory; auto deformationBasis = makeBasis(gridView, @@ -157,18 +157,18 @@ int main(int argc, char *argv[]) std::string baseNameDefault = "bending-isometries-"; std::string baseName = parameterSet.get("baseName", baseNameDefault); std::string resultFileName = parameterSet.get("resultPath", "") - + "/" + baseName - + "_level" + std::to_string(parameterSet.get<int>("numLevels")); + + "/" + baseName + + "_level" + std::to_string(parameterSet.get<int>("numLevels")); if (parameterSet.get<bool>("conforming_DiscreteJacobian", 1)) resultFileName = resultFileName + "_C"; - else + else resultFileName = resultFileName + "_NC"; /** - * @brief Compute the displacement from the deformation. - * interpolate the identity and substract from the coefficient vector. - */ + * @brief Compute the displacement from the deformation. + * interpolate the identity and substract from the coefficient vector. + */ VectorSpaceCoefficients identity(deformationBasis.size()); IdentityGridEmbedding<double> identityGridEmbedding; interpolate(deformationBasis, identity, identityGridEmbedding); @@ -176,8 +176,8 @@ int main(int argc, char *argv[]) auto displacement = x; displacement -= identity; - auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x); - auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacement); + auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x); + auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, displacement); auto deformationFunctionLocal = localFunction(deformationFunction); auto deformationFunctionLocalDerivative = derivative(deformationFunctionLocal); @@ -211,77 +211,77 @@ int main(int argc, char *argv[]) /** - * @brief Compute the L2-Error and H1-SemiError between the discrete deformation u_h and the analytical deformation u - * + * @brief Compute the L2-Error and H1-SemiError between the discrete deformation u_h and the analytical deformation u + * */ - auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); - auto referenceDerivative = derivative(referenceSolution); + auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); + auto referenceDerivative = derivative(referenceSolution); - // QuadratureRule for the integral of the L^2 error - QuadratureRuleKey quadKey(dim,6); + // QuadratureRule for the integral of the L^2 error + QuadratureRuleKey quadKey(dim,6); - // The error to be computed - double l2ErrorSquared = 0; - double h1ErrorSquared = 0; + // The error to be computed + double l2ErrorSquared = 0; + double h1ErrorSquared = 0; - for (auto&& element : elements(gridView)) - { + for (auto&& element : elements(gridView)) + { - deformationFunctionLocal.bind(element); - deformationFunctionLocalDerivative.bind(element); + deformationFunctionLocal.bind(element); + deformationFunctionLocalDerivative.bind(element); - // Get quadrature formula - quadKey.setGeometryType(element.type()); - const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey); + // Get quadrature formula + quadKey.setGeometryType(element.type()); + const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey); - for (auto quadPoint : quad) - { - auto quadPos = quadPoint.position(); - const auto integrationElement = element.geometry().integrationElement(quadPos); - const auto weight = quadPoint.weight(); + for (auto quadPoint : quad) + { + auto quadPos = quadPoint.position(); + const auto integrationElement = element.geometry().integrationElement(quadPos); + const auto weight = quadPoint.weight(); - auto refValue = referenceSolution(element.geometry().global(quadPos)); - auto numValue = deformationFunctionLocal(quadPos); + auto refValue = referenceSolution(element.geometry().global(quadPos)); + auto numValue = deformationFunctionLocal(quadPos); - auto numDir = deformationFunctionLocalDerivative(quadPos); - auto refDir = referenceDerivative(element.geometry().global(quadPos)); - auto diff = numDir - refDir; + auto numDir = deformationFunctionLocalDerivative(quadPos); + auto refDir = referenceDerivative(element.geometry().global(quadPos)); + auto diff = numDir - refDir; - // // print evaluation difference - // std::cout << "Evaluation difference at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numValue-refValue << std::endl; - std::cout << "Evaluation difference (of derivative) at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< diff << std::endl; - // print discrete function evaluation - // std::cout << "Evaluation of discreteGlobalBasisFunction at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numValue << std::endl; - std::cout << "Evaluation of discreteGlobalBasisFunction-derivative at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numDir << std::endl; + // // print evaluation difference + // std::cout << "Evaluation difference at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numValue-refValue << std::endl; + std::cout << "Evaluation difference (of derivative) at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< diff << std::endl; + // print discrete function evaluation + // std::cout << "Evaluation of discreteGlobalBasisFunction at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numValue << std::endl; + std::cout << "Evaluation of discreteGlobalBasisFunction-derivative at quadPoint:(" << element.geometry().global(quadPos) << ") is : "<< numDir << std::endl; - // integrate error - l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; - h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; - } - } - std::cout << "elements: " << gridView.size(0) - << " " - << "L^2 error: " << std::sqrt(l2ErrorSquared) - << " "; - std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; - - - //Check Quantities - if( std::sqrt(l2ErrorSquared) > 1e-12) - { - std::cerr << std::setprecision(9); - std::cerr << "L2-error is to large! " << std::endl; - return 1; - } - if( std::sqrt(h1ErrorSquared) > 1e-12) - { - std::cerr << std::setprecision(9); - std::cerr << "H1-error is to large! " << std::endl; - return 1; + // integrate error + l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; + h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; } + } + std::cout << "elements: " << gridView.size(0) + << " " + << "L^2 error: " << std::sqrt(l2ErrorSquared) + << " "; + std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; + + + //Check Quantities + if( std::sqrt(l2ErrorSquared) > 1e-12) + { + std::cerr << std::setprecision(9); + std::cerr << "L2-error is to large! " << std::endl; + return 1; + } + if( std::sqrt(h1ErrorSquared) > 1e-12) + { + std::cerr << std::setprecision(9); + std::cerr << "H1-error is to large! " << std::endl; + return 1; + } std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; std::cout << "Test: hermitebasis-evaluation-test passed." << std::endl; return 0; - } \ No newline at end of file +} diff --git a/test/linearisometrytest.cc b/test/linearisometrytest.cc index aba932b26e9f60616c9c9c3053e48c211548d0dd..ad6c62d8d9dc240015fc7d81ad3c4e86a61e2e05 100644 --- a/test/linearisometrytest.cc +++ b/test/linearisometrytest.cc @@ -74,7 +74,7 @@ using namespace Dune; /** * @brief Test the interpolation in deformation space. * A linear isometry can be represented exactly in that space. - * compare energy values / L2-error / H1-error + * compare energy values / L2-error / H1-error * for die difference | I_h[u] - u | where u is a given analytic linear isometry */ @@ -96,11 +96,11 @@ using namespace Dune; // for (const auto &element : elements(gridView)) // { // auto geometry = element.geometry(); - + // kirchhoffFunction.bind(element); // localDeformation.bind(element); -// localRotation.bind(element); -// localRotation_2.bind(element); +// localRotation.bind(element); +// localRotation_2.bind(element); // //evaluate at nodes: // for (int i=0; i<geometry.corners(); i++) @@ -119,7 +119,7 @@ using namespace Dune; // printvector(std::cout, defOut, "defOut:", "--"); // printmatrix(std::cout, KirchhoffRot, "KirchhoffRot:", "--"); // printmatrix(std::cout, defRot, "defRot:", "--"); -// // printmatrix(std::cout, defRot*jacobian, "defRot*jacobian:", "--"); // deprecated: when ReducedCubicHermite returned values in globalCoordinates, this was actually neccessary to get the right values. +// // printmatrix(std::cout, defRot*jacobian, "defRot*jacobian:", "--"); // deprecated: when ReducedCubicHermite returned values in globalCoordinates, this was actually neccessary to get the right values. // } // } // } @@ -319,7 +319,7 @@ using namespace Dune; // //cross product to get last column of rotation matrix // FieldVector<RT,3> cross = {currentDerivative_x[1]*currentDerivative_y[2] - currentDerivative_x[2]*currentDerivative_y[1], -// currentDerivative_x[2]*currentDerivative_y[0] - currentDerivative_x[0]*currentDerivative_y[2], +// currentDerivative_x[2]*currentDerivative_y[0] - currentDerivative_x[0]*currentDerivative_y[2], // currentDerivative_x[0]*currentDerivative_y[1] - currentDerivative_x[1]*currentDerivative_y[0]}; // FieldMatrix<RT,3,3> rotMatrix(0); @@ -378,9 +378,9 @@ using namespace Dune; // using namespace Dune::Indices; // auto deformation = isometryCoefficients[globalIdx][_0].globalCoordinates(); -// auto rotation1 = isometryCoefficients[globalIdx][_1].director(0); +// auto rotation1 = isometryCoefficients[globalIdx][_1].director(0); // auto rotation2 = isometryCoefficients[globalIdx][_1].director(1); - + // coefficients[globalIdxOut_0[0]][globalIdxOut_0[1]] = deformation[k]; // coefficients[globalIdxOut_1[0]][globalIdxOut_1[1]] = rotation1[k]; // coefficients[globalIdxOut_2[0]][globalIdxOut_2[1]] = rotation2[k]; @@ -394,12 +394,16 @@ int main(int argc, char *argv[]) { /** - * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' + * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' * in RiemannianProximalNewton */ - std::shared_ptr<void(int)> handler( - signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }), - [](__sighandler_t f) { signal(SIGFPE, f); }); + std::shared_ptr<void(int)> handler( + signal(SIGFPE, [](int signum) { + throw std::logic_error("FPE"); + }), + [](__sighandler_t f) { + signal(SIGFPE, f); + }); @@ -418,9 +422,9 @@ int main(int argc, char *argv[]) Python::start(); auto pyMain = Python::main(); pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; auto pyModule = pyMain.import("linearisometrytest"); // parse data file @@ -439,8 +443,8 @@ int main(int argc, char *argv[]) ///////////////////////////////////////// using GridType = UGGrid<dim>; std::shared_ptr<GridType> grid; -// FieldVector<double,dim> lower(0), upper(1); -// std::array<unsigned int,dim> elementsArray; + // FieldVector<double,dim> lower(0), upper(1); + // std::array<unsigned int,dim> elementsArray; // create unstructured grid. std::cout << "Read GMSH grid." << std::endl; @@ -462,7 +466,7 @@ int main(int argc, char *argv[]) /////////////////////////////////////////////////////// // General coefficient vector of a Discrete Kirchhoff deformation function - using VectorSpaceCoefficients = BlockVector<FieldVector<double,3>>; + using VectorSpaceCoefficients = BlockVector<FieldVector<double,3> >; // Coefficient vector of a Discrete Kirchhoff deformation function that is constrained to be an isometry using Coefficient = GFE::ProductManifold<RealTuple<double,3>, Rotation<double,3> >; @@ -483,12 +487,12 @@ int main(int argc, char *argv[]) // A basis for the tangent space (used to set DirichletNodes) auto tangentBasis = makeBasis(gridView, power<Coefficient::TangentVector::dimension>( - lagrange<1>(), - blockedInterleaved())); + lagrange<1>(), + blockedInterleaved())); /////////////////////////////////////////// - // Read Dirichlet values + // Read Dirichlet values /////////////////////////////////////////// BitSetVector<1> dirichletVertices(gridView.size(dim), false); const typename GridView::IndexSet &indexSet = gridView.indexSet(); @@ -523,8 +527,8 @@ int main(int argc, char *argv[]) /** - * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient - * vector of ctype 'adouble' while the solver gets a coefficient vector + * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient + * vector of ctype 'adouble' while the solver gets a coefficient vector * of ctype 'double'. */ IsometryCoefficients isometryCoefficients(coefficientBasis.size()); @@ -537,9 +541,9 @@ int main(int argc, char *argv[]) /** - * @brief TEST: compute isometry error - */ - auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x); + * @brief TEST: compute isometry error + */ + auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x); // nodewiseIsometryTest(initialDeformationFunction); @@ -550,20 +554,20 @@ int main(int argc, char *argv[]) vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients_adouble); - // /** - // * @brief TEST: conversion of coefficient vectors (back & forth) - // */ - // VectorSpaceCoefficients x_convert = x; - // IsometryCoefficients isometryCoefficientsTMP(coefficientBasis.size()); - // vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); - // isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); - // //Check difference - // for(int i=0; i<x.size(); i++) - // { - // if((x[i]-x_convert[i]).two_norm() > 1e-4) - // std::cout << "Coefficient conversion failed! with x[i]-x_convert[i]:" << x[i]-x_convert[i] << std::endl; - // } - + // /** + // * @brief TEST: conversion of coefficient vectors (back & forth) + // */ + // VectorSpaceCoefficients x_convert = x; + // IsometryCoefficients isometryCoefficientsTMP(coefficientBasis.size()); + // vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); + // isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_convert,isometryCoefficientsTMP); + // //Check difference + // for(int i=0; i<x.size(); i++) + // { + // if((x[i]-x_convert[i]).two_norm() > 1e-4) + // std::cout << "Coefficient conversion failed! with x[i]-x_convert[i]:" << x[i]-x_convert[i] << std::endl; + // } + @@ -578,7 +582,7 @@ int main(int argc, char *argv[]) /** * @brief Get force term */ - auto pythonForce = Python::make_function<FieldVector<double,3>>(pyModule.get("force")); + auto pythonForce = Python::make_function<FieldVector<double,3> >(pyModule.get("force")); // auto forceGVF = Dune::Functions::makeGridViewFunction(dummyForce, gridView); auto forceGVF = Dune::Functions::makeGridViewFunction(pythonForce, gridView); auto localForce = localFunction(forceGVF); @@ -587,7 +591,7 @@ int main(int argc, char *argv[]) /** * @brief Get effective prestrain Tensor */ - Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3>>("effectivePrestrain", {0.0, 0.0, 0.0}); + Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3> >("effectivePrestrain", {0.0, 0.0, 0.0}); Dune::FieldMatrix<adouble,2,2> effectivePrestrain = {{(adouble)Beffvec[0], (adouble)Beffvec[2]}, {(adouble)Beffvec[2],(adouble)Beffvec[1]} }; printmatrix(std::cout, effectivePrestrain, "effective prestrain (Beff): ", "--"); @@ -595,10 +599,10 @@ int main(int argc, char *argv[]) /** * @brief Get effective quadratic form */ - Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); - Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)Qhomvec[3], (adouble)Qhomvec[4]}, - {(adouble)Qhomvec[3], (adouble)Qhomvec[1], (adouble)Qhomvec[5]}, - {(adouble)Qhomvec[4], (adouble)Qhomvec[5], (adouble)Qhomvec[2]}}; + Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6> >("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); + Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)Qhomvec[3], (adouble)Qhomvec[4]}, + {(adouble)Qhomvec[3], (adouble)Qhomvec[1], (adouble)Qhomvec[5]}, + {(adouble)Qhomvec[4], (adouble)Qhomvec[5], (adouble)Qhomvec[2]}}; printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--"); @@ -616,7 +620,7 @@ int main(int argc, char *argv[]) * @brief Setup energy featuring prestrain */ // auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, Qhom, effectivePrestrain); - auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule); + auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient> >(localDKFunction, localForce, parameterSet, pyModule); auto localGFEADOLCStiffness_prestrain = std::make_shared<LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> >(localEnergy_prestrain); std::shared_ptr<GeodesicFEAssembler<CoefficientBasis, Coefficient> > assembler_prestrain; assembler_prestrain = std::make_shared<GeodesicFEAssembler<CoefficientBasis, Coefficient> >(coefficientBasis, localGFEADOLCStiffness_prestrain); @@ -647,12 +651,12 @@ int main(int argc, char *argv[]) // isometryCoefficients, // dirichletNodes, // parameterSet); - // else + // else // solver.setup(*grid, // &assembler_nonconforming, // isometryCoefficients, // dirichletNodes, - // parameterSet); + // parameterSet); // ///////////////////////////////////////////////////// // Solve! @@ -671,15 +675,15 @@ int main(int argc, char *argv[]) std::string baseNameDefault = "bending-isometries-"; std::string baseName = parameterSet.get("baseName", baseNameDefault); std::string resultFileName = parameterSet.get("resultPath", "") - + "/" + baseName - + "_level" + std::to_string(parameterSet.get<int>("numLevels")); + + "/" + baseName + + "_level" + std::to_string(parameterSet.get<int>("numLevels")); if (parameterSet.get<bool>("conforming_DiscreteJacobian", 1)) resultFileName = resultFileName + "_C"; - else + else resultFileName = resultFileName + "_NC"; - // Create a deformation function but this time with double-types. + // Create a deformation function but this time with double-types. using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; LocalDKFunctionD localDKFunctionDouble(deformationBasis, coefficientBasis, isometryCoefficients); @@ -703,8 +707,8 @@ int main(int argc, char *argv[]) displacement -= identity; // std::cout << "displacement.size():" << displacement.size() << std::endl; - auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x_out); - auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacement); + auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x_out); + auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, displacement); /** * @brief We need to subsample, because VTK cannot natively display real third-order functions @@ -717,29 +721,29 @@ int main(int argc, char *argv[]) /** * @brief Basis used to represent normal vector fields - * + * */ auto normalBasis = makeBasis(gridView, - power<3>( - lagrange<1>(), - flatLexicographic())); + power<3>( + lagrange<1>(), + flatLexicographic())); // auto normalBasis = makeBasis(gridView, // power<3>( // lagrange<1>(), // blockedInterleaved())); - // TEST Compute + // TEST Compute // auto normalLambda = [deformationFunction](const FieldVector<double,2>& x) // { // // deformationfunction.derivative() ... //needs binding?! - + // } - + /** @@ -767,127 +771,127 @@ int main(int argc, char *argv[]) // auto deformationFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, y); // vtkWriter.addVertexData(displacementFunctionAnalytical, VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); // vtkWriter.addVertexData(deformationFunctionAnalytical, VTK::FieldInfo("deformation_analytical", VTK::FieldInfo::Type::vector, 3)); - + vtkWriter.addVertexData((pythonAnalyticalSolution), VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); /** - * @brief Get the normal vector field of the surface parametrized + * @brief Get the normal vector field of the surface parametrized * by the analytical solution. * - We represent the normal vector in a first order Lagrange-Power basis ('normalBasis'). */ if (parameterSet.get<bool>("vtkWrite_analyticalSurfaceNormal", 0)) { - // Get the surface normal function. - auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3>>(pyModule.get("surfaceNormal")); + // Get the surface normal function. + auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3> >(pyModule.get("surfaceNormal")); - // deprecated: interpolate ... - // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); - // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); - // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); - // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); + // deprecated: interpolate ... + // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); + // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); + // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); + // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); - vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); + vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); } } //------------------------------------------------------------------------------------- TODO: OUTSOURCE /** - * @brief TEST: Compute the discrete normal vector of the surface parametrized + * @brief TEST: Compute the discrete normal vector of the surface parametrized * by the discrete solution. */ - auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); + auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); //------------------------------------------------------------------------------------- // Create DiscreteGlobalBasisFunctions. - auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, surfaceNormalDiscreteCoefficients); + auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(normalBasis, surfaceNormalDiscreteCoefficients); vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::vector, 3)); vtkWriter.addVertexData(surfaceNormalDiscrete , VTK::FieldInfo("surfaceNormal_discrete", VTK::FieldInfo::Type::vector, 3)); vtkWriter.write(resultFileName); } /** - * @brief Compute the L2-Error and H1-SemiError between the discrete deformation u_h and the analytical deformation u - * + * @brief Compute the L2-Error and H1-SemiError between the discrete deformation u_h and the analytical deformation u + * */ - // Read reference solution and its derivative into a Python function - // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); - // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("displacement"), pyModule.get("displacementGradient")); - auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); - auto referenceDerivative = derivative(referenceSolution); + // Read reference solution and its derivative into a Python function + // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); + // auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("displacement"), pyModule.get("displacementGradient")); + auto referenceSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("deformation"), pyModule.get("deformationGradient")); + auto referenceDerivative = derivative(referenceSolution); - using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; - LocalDKFunctionD localDKFunctionD(deformationBasis, coefficientBasis, isometryCoefficients); + using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; + LocalDKFunctionD localDKFunctionD(deformationBasis, coefficientBasis, isometryCoefficients); - // QuadratureRule for the integral of the L^2 error - QuadratureRuleKey quadKey(dim,6); + // QuadratureRule for the integral of the L^2 error + QuadratureRuleKey quadKey(dim,6); - // The error to be computed - double l2ErrorSquared = 0; - double h1ErrorSquared = 0; + // The error to be computed + double l2ErrorSquared = 0; + double h1ErrorSquared = 0; - for (auto&& element : elements(gridView)) - { + for (auto&& element : elements(gridView)) + { // localNumericalSolution.bind(element); - localDKFunctionD.bind(element); + localDKFunctionD.bind(element); - // Get quadrature formula - quadKey.setGeometryType(element.type()); - const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey); + // Get quadrature formula + quadKey.setGeometryType(element.type()); + const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey); - for (auto quadPoint : quad) - { - auto quadPos = quadPoint.position(); - const auto integrationElement = element.geometry().integrationElement(quadPos); - const auto weight = quadPoint.weight(); + for (auto quadPoint : quad) + { + auto quadPos = quadPoint.position(); + const auto integrationElement = element.geometry().integrationElement(quadPos); + const auto weight = quadPoint.weight(); - // auto numValue = localNumericalSolution(quadPos); - auto refValue = referenceSolution(element.geometry().global(quadPos)); - auto numValue = localDKFunctionD.evaluate(quadPos).globalCoordinates(); + // auto numValue = localNumericalSolution(quadPos); + auto refValue = referenceSolution(element.geometry().global(quadPos)); + auto numValue = localDKFunctionD.evaluate(quadPos).globalCoordinates(); - auto numDir = localDKFunctionD.evaluateDerivative(quadPos); - auto refDir = referenceDerivative(element.geometry().global(quadPos)); - auto diff = numDir - refDir; + auto numDir = localDKFunctionD.evaluateDerivative(quadPos); + auto refDir = referenceDerivative(element.geometry().global(quadPos)); + auto diff = numDir - refDir; - // integrate error - l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; - h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; - } - } - std::cout << "elements: " << gridView.size(0) - << " " - << "L^2 error: " << std::sqrt(l2ErrorSquared) - << " "; - std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; - - - //Check Quantities - if( std::sqrt(l2ErrorSquared) > 1e-12) - { - std::cerr << std::setprecision(9); - std::cerr << "L2-error is to large! " << std::endl; - return 1; - } - if( std::sqrt(h1ErrorSquared) > 1e-12) - { - std::cerr << std::setprecision(9); - std::cerr << "H1-error is to large! " << std::endl; - return 1; - } - // Compare energy values. - auto numerical_energy = solver.getStatistics().finalEnergy; - auto analytical_energy = 0.0; - std::cout << "Energy difference: " << std::abs(analytical_energy - numerical_energy) << std::endl; - if( std::abs(analytical_energy - numerical_energy) > 1e-12) - { - std::cerr << std::setprecision(9); - std::cerr << "Energy difference: " << std::abs(analytical_energy - numerical_energy) << " is to large! " << std::endl; - return 1; + // integrate error + l2ErrorSquared += (numValue - refValue)* (numValue - refValue) * weight * integrationElement; + h1ErrorSquared += diff.frobenius_norm2() * weight * integrationElement; } + } + std::cout << "elements: " << gridView.size(0) + << " " + << "L^2 error: " << std::sqrt(l2ErrorSquared) + << " "; + std::cout << "h^1 error: " << std::sqrt(h1ErrorSquared) << std::endl; + + + //Check Quantities + if( std::sqrt(l2ErrorSquared) > 1e-12) + { + std::cerr << std::setprecision(9); + std::cerr << "L2-error is to large! " << std::endl; + return 1; + } + if( std::sqrt(h1ErrorSquared) > 1e-12) + { + std::cerr << std::setprecision(9); + std::cerr << "H1-error is to large! " << std::endl; + return 1; + } + // Compare energy values. + auto numerical_energy = solver.getStatistics().finalEnergy; + auto analytical_energy = 0.0; + std::cout << "Energy difference: " << std::abs(analytical_energy - numerical_energy) << std::endl; + if( std::abs(analytical_energy - numerical_energy) > 1e-12) + { + std::cerr << std::setprecision(9); + std::cerr << "Energy difference: " << std::abs(analytical_energy - numerical_energy) << " is to large! " << std::endl; + return 1; + } std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; std::cout << "Test: linearisometrytest passed." << std::endl; return 0; - } \ No newline at end of file +} diff --git a/test/orthotropicrotationtest.cc b/test/orthotropicrotationtest.cc index 9c99eb440abdc759e632c902274095ddd49cee7f..6680f4046c6707d5355c60f0a8b6f3e4ba0f130b 100644 --- a/test/orthotropicrotationtest.cc +++ b/test/orthotropicrotationtest.cc @@ -63,9 +63,9 @@ using namespace MatrixOperations; /** * @brief Compute effective quantities for a trilayer setup with 3 orthotropic phases: - * Once with a canonical orthonormal material frame and once with a material frame + * Once with a canonical orthonormal material frame and once with a material frame * that is rotated pi(180 degree) around different axes. - * Aim of the test is to check the correctness of the material frame transformation. + * Aim of the test is to check the correctness of the material frame transformation. */ @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) MPIHelper::instance(argc, argv); Dune::Timer globalTimer; - //--- setup Log-File + //--- setup Log-File std::fstream log; std::cout << "Current path is " << std::filesystem::current_path() << '\n'; @@ -115,22 +115,22 @@ int main(int argc, char *argv[]) // << std::endl; - // Start Python interpreter - Python::start(); - auto pyMain = Python::main(); - pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; - auto pyModule = pyMain.import("orthotropicrotation_1"); + // Start Python interpreter + Python::start(); + auto pyMain = Python::main(); + pyMain.runStream() + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + auto pyModule = pyMain.import("orthotropicrotation_1"); - ParameterTree parameterSet; - pyModule.get("parameterSet").toC(parameterSet); - // read possible further parameters from the command line - ParameterTreeParser::readOptions(argc, argv, parameterSet); - // Print all parameters, to make them appear in the log file - std::cout << "Input parameters:" << std::endl; - parameterSet.report(); + ParameterTree parameterSet; + pyModule.get("parameterSet").toC(parameterSet); + // read possible further parameters from the command line + ParameterTreeParser::readOptions(argc, argv, parameterSet); + // Print all parameters, to make them appear in the log file + std::cout << "Input parameters:" << std::endl; + parameterSet.report(); @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) // auto correctorComputer = CorrectorComputer(Basis_CE, material_, log, parameterSet); // correctorComputer.assemble(); // correctorComputer.solve(); - std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType>>(Basis_CE, material, parameterSet); + std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType> >(Basis_CE, material, parameterSet); correctorComputer->assemble(); correctorComputer->solve(); @@ -204,16 +204,16 @@ int main(int argc, char *argv[]) //--- get effective quantities auto Qeff = effectiveQuantitiesComputer.getQeff(); auto Beff = effectiveQuantitiesComputer.getBeff(); -// printmatrix(std::cout, Qeff, "Matrix Qeff", "--"); -// printvector(std::cout, Beff, "Beff", "--"); + // printmatrix(std::cout, Qeff, "Matrix Qeff", "--"); + // printvector(std::cout, Beff, "Beff", "--"); /** * @brief Compute "rotated" effective quantitites * */ -// ParameterTreeParser::readINITree("../test/orthotropicrotation_2.parset", parameterSet); -// ParameterTreeParser::readINITree(dir_path + "/orthotropicrotation_2.parset", parameterSet); + // ParameterTreeParser::readINITree("../test/orthotropicrotation_2.parset", parameterSet); + // ParameterTreeParser::readINITree(dir_path + "/orthotropicrotation_2.parset", parameterSet); pyModule = pyMain.import("orthotropicrotation_2"); pyModule.get("parameterSet").toC(parameterSet); @@ -224,7 +224,7 @@ int main(int argc, char *argv[]) - //-- Alternative: + //-- Alternative: material->updateMicrostructure(microstructure_2); correctorComputer->updateMaterial(material); effectiveQuantitiesComputer.updateCorrectorComputer(correctorComputer); @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) /** * @brief Old way: - * + * */ // auto material_2 = prestrainedMaterial(gridView_CE,microstructure_2,parameterSet,pyModule); // std::shared_ptr<MaterialType> material_2 = std::make_shared<MaterialType>(gridView_CE,microstructure_2,parameterSet,pyModule); diff --git a/test/parametrizedlaminatetest.cc b/test/parametrizedlaminatetest.cc index 4aa89738903ec5711bebd995bf147db0165283e4..082000b5ba0e2f497535c77aa7a2deb0aeb93b7d 100644 --- a/test/parametrizedlaminatetest.cc +++ b/test/parametrizedlaminatetest.cc @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) MPIHelper::instance(argc, argv); Dune::Timer globalTimer; - //--- setup Log-File + //--- setup Log-File std::fstream log; std::cout << "Current path is " << std::filesystem::current_path() << '\n'; @@ -134,22 +134,22 @@ int main(int argc, char *argv[]) - // Start Python interpreter - Python::start(); - auto pyMain = Python::main(); - pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; - auto pyModule = pyMain.import("parametrized_laminate"); + // Start Python interpreter + Python::start(); + auto pyMain = Python::main(); + pyMain.runStream() + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + auto pyModule = pyMain.import("parametrized_laminate"); - ParameterTree parameterSet; - pyModule.get("parameterSet").toC(parameterSet); - // read possible further parameters from the command line - ParameterTreeParser::readOptions(argc, argv, parameterSet); - // Print all parameters, to make them appear in the log file - std::cout << "Input parameters:" << std::endl; - parameterSet.report(); + ParameterTree parameterSet; + pyModule.get("parameterSet").toC(parameterSet); + // read possible further parameters from the command line + ParameterTreeParser::readOptions(argc, argv, parameterSet); + // Print all parameters, to make them appear in the log file + std::cout << "Input parameters:" << std::endl; + parameterSet.report(); @@ -220,7 +220,7 @@ int main(int argc, char *argv[]) // auto correctorComputer = CorrectorComputer(Basis_CE, material, log, parameterSet); // correctorComputer.assemble(); // correctorComputer.solve(); - std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType>>(Basis_CE, material, parameterSet); + std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType> >(Basis_CE, material, parameterSet); correctorComputer->assemble(); correctorComputer->solve(); diff --git a/test/properties-shape-test.cc b/test/properties-shape-test.cc index 5cabbaeeb1ca72a03aa7f814a45508c02f0983e1..7bfda39e072cff40ca735276579954ec314f043b 100644 --- a/test/properties-shape-test.cc +++ b/test/properties-shape-test.cc @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) { /** - * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' + * @brief We use this to catch a 'Floating point exception' caused by the 'innerSolver' * in RiemannianProximalNewton */ // std::shared_ptr<void(int)> handler( @@ -98,620 +98,620 @@ int main(int argc, char *argv[]) for(size_t experimentNumber = 1; experimentNumber<4; experimentNumber++) { - MPIHelper::instance(argc, argv); - Dune::Timer globalTimer; + MPIHelper::instance(argc, argv); + Dune::Timer globalTimer; - // if (argc < 3) - // DUNE_THROW(Exception, "Usage: ./bending-isometries <python path> <python module without extension>"); + // if (argc < 3) + // DUNE_THROW(Exception, "Usage: ./bending-isometries <python path> <python module without extension>"); - // Start Python interpreter - // Python::start(); - // auto pyMain = Python::main(); - // pyMain.runStream() - // << std::endl << "import math" - // << std::endl << "import sys" - // << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; - // auto pyModule = pyMain.import(argv[2]); + // Start Python interpreter + // Python::start(); + // auto pyMain = Python::main(); + // pyMain.runStream() + // << std::endl << "import math" + // << std::endl << "import sys" + // << std::endl << "sys.path.append('" << argv[1] << "')" << std::endl; + // auto pyModule = pyMain.import(argv[2]); - 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(); + 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(); - std::string experiment = "properties-shape-test-" + std::to_string(experimentNumber); + std::string experiment = "properties-shape-test-" + std::to_string(experimentNumber); - // Start Python interpreter - Python::start(); - auto pyMain = Python::main(); - pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; - // auto pyModule = pyMain.import("properties-shape-test-2"); - auto pyModule = pyMain.import(experiment); + // Start Python interpreter + Python::start(); + auto pyMain = Python::main(); + pyMain.runStream() + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + // auto pyModule = pyMain.import("properties-shape-test-2"); + auto pyModule = pyMain.import(experiment); - // parse data file - ParameterTree parameterSet; - pyModule.get("parameterSet").toC(parameterSet); + // parse data file + ParameterTree parameterSet; + pyModule.get("parameterSet").toC(parameterSet); - // read possible further parameters from the command line - ParameterTreeParser::readOptions(argc, argv, parameterSet); + // read possible further parameters from the command line + ParameterTreeParser::readOptions(argc, argv, parameterSet); - // Print all parameters, to make them appear in the log file - std::cout << "Executable: bending-isometries, with parameters:" << std::endl; - parameterSet.report(); + // Print all parameters, to make them appear in the log file + std::cout << "Executable: bending-isometries, with parameters:" << std::endl; + parameterSet.report(); - ///////////////////////////////////////// - // Create the grid - ///////////////////////////////////////// - using GridType = UGGrid<dim>; + ///////////////////////////////////////// + // Create the grid + ///////////////////////////////////////// + using GridType = UGGrid<dim>; - std::shared_ptr<GridType> grid; - FieldVector<double,dim> lower(0), upper(1); - std::array<unsigned int,dim> elementsArray; + std::shared_ptr<GridType> grid; + FieldVector<double,dim> lower(0), upper(1); + std::array<unsigned int,dim> elementsArray; - std::string structuredGridType = parameterSet["structuredGrid"]; - if (structuredGridType != "false" ) - { - lower = parameterSet.get<FieldVector<double,dim> >("lower"); - upper = parameterSet.get<FieldVector<double,dim> >("upper"); - elementsArray = parameterSet.get<std::array<unsigned int,dim> >("elements"); - - if (structuredGridType == "simplex") - grid = StructuredGridFactory<GridType>::createSimplexGrid(lower, upper, elementsArray); - else if (structuredGridType == "cube") - grid = StructuredGridFactory<GridType>::createCubeGrid(lower, upper, elementsArray); - else - DUNE_THROW(Exception, "Unknown structured grid type '" << structuredGridType << "' found!"); - } else { - std::cout << "Read GMSH grid." << std::endl; - std::string gridPath = parameterSet.get<std::string>("gridPath"); - std::string gridFile = parameterSet.get<std::string>("gridFile"); - GridFactory<GridType> factory; - Gmsh4::LagrangeGridCreator creator{factory}; - Gmsh4Reader reader{creator}; - reader.read(gridPath + "/" + gridFile); - grid = factory.createGrid(); - } + std::string structuredGridType = parameterSet["structuredGrid"]; + if (structuredGridType != "false" ) + { + lower = parameterSet.get<FieldVector<double,dim> >("lower"); + upper = parameterSet.get<FieldVector<double,dim> >("upper"); + elementsArray = parameterSet.get<std::array<unsigned int,dim> >("elements"); + + if (structuredGridType == "simplex") + grid = StructuredGridFactory<GridType>::createSimplexGrid(lower, upper, elementsArray); + else if (structuredGridType == "cube") + grid = StructuredGridFactory<GridType>::createCubeGrid(lower, upper, elementsArray); + else + DUNE_THROW(Exception, "Unknown structured grid type '" << structuredGridType << "' found!"); + } else { + std::cout << "Read GMSH grid." << std::endl; + std::string gridPath = parameterSet.get<std::string>("gridPath"); + std::string gridFile = parameterSet.get<std::string>("gridFile"); + GridFactory<GridType> factory; + Gmsh4::LagrangeGridCreator creator{factory}; + Gmsh4Reader reader{creator}; + reader.read(gridPath + "/" + gridFile); + grid = factory.createGrid(); + } - const int macroGridLevel = parameterSet.get<int>("macroGridLevel"); - grid->globalRefine(macroGridLevel-1); + const int macroGridLevel = parameterSet.get<int>("macroGridLevel"); + grid->globalRefine(macroGridLevel-1); - using GridView = typename GridType::LeafGridView; - GridView gridView = grid->leafGridView(); + using GridView = typename GridType::LeafGridView; + GridView gridView = grid->leafGridView(); - /////////////////////////////////////////////////////// - // Set up the function spaces - /////////////////////////////////////////////////////// + /////////////////////////////////////////////////////// + // Set up the function spaces + /////////////////////////////////////////////////////// - // General coefficient vector of a Discrete Kirchhoff deformation function - using VectorSpaceCoefficients = BlockVector<FieldVector<double,3>>; + // General coefficient vector of a Discrete Kirchhoff deformation function + using VectorSpaceCoefficients = BlockVector<FieldVector<double,3> >; - /** - * @brief Coefficient vector of a Discrete Kirchhoff deformation function that is constrained to be an isometry. - * we need both 'double' and 'adouble' versions. - */ - using Coefficient = GFE::ProductManifold<RealTuple<double,3>, Rotation<double,3> >; - using IsometryCoefficients = std::vector<Coefficient>; - using ACoefficient = typename Coefficient::template rebind<adouble>::other; - using AIsometryCoefficients = std::vector<ACoefficient>; + /** + * @brief Coefficient vector of a Discrete Kirchhoff deformation function that is constrained to be an isometry. + * we need both 'double' and 'adouble' versions. + */ + using Coefficient = GFE::ProductManifold<RealTuple<double,3>, Rotation<double,3> >; + using IsometryCoefficients = std::vector<Coefficient>; + using ACoefficient = typename Coefficient::template rebind<adouble>::other; + using AIsometryCoefficients = std::vector<ACoefficient>; - using namespace Functions::BasisFactory; - auto deformationBasis = makeBasis(gridView, - power<3>(reducedCubicHermite(), - blockedInterleaved())); + using namespace Functions::BasisFactory; + auto deformationBasis = makeBasis(gridView, + power<3>(reducedCubicHermite(), + blockedInterleaved())); - using DeformationBasis = decltype(deformationBasis); + using DeformationBasis = decltype(deformationBasis); - /** - * @brief The next basis is used to assign (nonlinear) degrees of freedom to the grid vertices. - * The actual basis function values are never used. - */ - using CoefficientBasis = Functions::LagrangeBasis<GridView, 1>; - CoefficientBasis coefficientBasis(gridView); + /** + * @brief The next basis is used to assign (nonlinear) degrees of freedom to the grid vertices. + * The actual basis function values are never used. + */ + using CoefficientBasis = Functions::LagrangeBasis<GridView, 1>; + CoefficientBasis coefficientBasis(gridView); - // A basis for the tangent space (used to set DirichletNodes) - auto tangentBasis = makeBasis(gridView, - power<Coefficient::TangentVector::dimension>( + // A basis for the tangent space (used to set DirichletNodes) + auto tangentBasis = makeBasis(gridView, + power<Coefficient::TangentVector::dimension>( lagrange<1>(), blockedInterleaved())); - // Print some information on the grid and degrees of freedom. - std::cout << "Number of Elements in the grid: " << gridView.size(0)<< std::endl; - std::cout << "Number of Nodes in the grid: " << gridView.size(dim)<< std::endl; - std::cout << "deformationBasis.size(): " << deformationBasis.size() << std::endl; - std::cout << "deformationBasis.dimension(): " << deformationBasis.dimension() << std::endl; - std::cout << "Degrees of Freedom: " << deformationBasis.dimension() << std::endl; + // Print some information on the grid and degrees of freedom. + std::cout << "Number of Elements in the grid: " << gridView.size(0)<< std::endl; + std::cout << "Number of Nodes in the grid: " << gridView.size(dim)<< std::endl; + std::cout << "deformationBasis.size(): " << deformationBasis.size() << std::endl; + std::cout << "deformationBasis.dimension(): " << deformationBasis.dimension() << std::endl; + std::cout << "Degrees of Freedom: " << deformationBasis.dimension() << std::endl; - /////////////////////////////////////////// - // Read Dirichlet values (NEW VERSION) - /////////////////////////////////////////// - BitSetVector<1> dirichletVertices(gridView.size(dim), false); - const typename GridView::IndexSet &indexSet = gridView.indexSet(); + /////////////////////////////////////////// + // Read Dirichlet values (NEW VERSION) + /////////////////////////////////////////// + BitSetVector<1> dirichletVertices(gridView.size(dim), false); + const typename GridView::IndexSet &indexSet = gridView.indexSet(); - BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); //tangentBasis.size()=coefficientBasis.size() + BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); //tangentBasis.size()=coefficientBasis.size() - /** - * @brief Make Python function that computes which vertices are on the Dirichlet boundary, - * based on the vertex positions. - */ - auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); + /** + * @brief Make Python function that computes which vertices are on the Dirichlet boundary, + * based on the vertex positions. + */ + auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); - /** - * @brief If we want to clamp DOFs inside the domain, we connot use 'BoundaryPatch' - * and 'constructBoundaryDofs'. This is a workaround for now. - * - * - */ - for (auto &&vertex : vertices(gridView)) - { - dirichletVertices[indexSet.index(vertex)] = dirichletIndicatorFunction(vertex.geometry().corner(0)); + /** + * @brief If we want to clamp DOFs inside the domain, we connot use 'BoundaryPatch' + * and 'constructBoundaryDofs'. This is a workaround for now. + * + * + */ + for (auto &&vertex : vertices(gridView)) + { + dirichletVertices[indexSet.index(vertex)] = dirichletIndicatorFunction(vertex.geometry().corner(0)); - if(dirichletIndicatorFunction(vertex.geometry().corner(0))) - { - dirichletNodes[indexSet.index(vertex)] = true; - } - + if(dirichletIndicatorFunction(vertex.geometry().corner(0))) + { + dirichletNodes[indexSet.index(vertex)] = true; } - - // std::cout << "tangentBasis.size():" << tangentBasis.size() << std::endl; - // std::cout << "coefficientBasis.size():" << coefficientBasis.size() << std::endl; - // // deprecated: - // // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); - // // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); + } - // // TEST: print dirichletNodes - // std::cout << "print dirichletVertices:" << std::endl; - // std::cout << dirichletVertices << std::endl; + // std::cout << "tangentBasis.size():" << tangentBasis.size() << std::endl; + // std::cout << "coefficientBasis.size():" << coefficientBasis.size() << std::endl; - // std::cout << "print dirichletNodes:" << std::endl; - // std::cout << dirichletNodes << std::endl; + // // deprecated: + // // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); + // // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); + // // TEST: print dirichletNodes + // std::cout << "print dirichletVertices:" << std::endl; + // std::cout << dirichletVertices << std::endl; + // std::cout << "print dirichletNodes:" << std::endl; + // std::cout << dirichletNodes << std::endl; - // /////////////////////////////////////////// - // // Read Dirichlet values (OLD VERSION) - // /////////////////////////////////////////// - // BitSetVector<1> dirichletVertices(gridView.size(dim), false); - // const typename GridView::IndexSet &indexSet = gridView.indexSet(); - // /** - // * @brief Make Python function that computes which vertices are on the Dirichlet boundary, - // * based on the vertex positions. - // */ - // auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); - // for (auto &&vertex : vertices(gridView)) - // { - // dirichletVertices[indexSet.index(vertex)] = dirichletIndicatorFunction(vertex.geometry().corner(0)); - // // if(dirichletIndicatorFunction(vertex.geometry().corner(0))) - // // { - // // std::cout << "Dirichlet Vertex with coordinates:" << vertex.geometry().corner(0) << std::endl; - // // } - // } + // /////////////////////////////////////////// + // // Read Dirichlet values (OLD VERSION) + // /////////////////////////////////////////// + // BitSetVector<1> dirichletVertices(gridView.size(dim), false); + // const typename GridView::IndexSet &indexSet = gridView.indexSet(); - // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); - // BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); - // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); + // /** + // * @brief Make Python function that computes which vertices are on the Dirichlet boundary, + // * based on the vertex positions. + // */ + // auto dirichletIndicatorFunction = Python::make_function<bool>(pyModule.get("dirichlet_indicator")); - /////////////////////////////////////////// - // Get initial Iterate - /////////////////////////////////////////// - auto pythonInitialIterate = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("f"), pyModule.get("df")); - - VectorSpaceCoefficients x(deformationBasis.size()); - interpolate(deformationBasis, x, pythonInitialIterate); + // for (auto &&vertex : vertices(gridView)) + // { + // dirichletVertices[indexSet.index(vertex)] = dirichletIndicatorFunction(vertex.geometry().corner(0)); + // // if(dirichletIndicatorFunction(vertex.geometry().corner(0))) + // // { + // // std::cout << "Dirichlet Vertex with coordinates:" << vertex.geometry().corner(0) << std::endl; + // // } + // } + // BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices); + // BitSetVector<Coefficient::TangentVector::dimension> dirichletNodes(tangentBasis.size(), false); + // constructBoundaryDofs(dirichletBoundary, tangentBasis, dirichletNodes); + /////////////////////////////////////////// + // Get initial Iterate + /////////////////////////////////////////// + auto pythonInitialIterate = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("f"), pyModule.get("df")); + VectorSpaceCoefficients x(deformationBasis.size()); + interpolate(deformationBasis, x, pythonInitialIterate); - /** - * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient - * vector of ctype 'adouble' while the solver gets a coefficient vector - * of ctype 'double'. - */ - IsometryCoefficients isometryCoefficients(coefficientBasis.size()); - AIsometryCoefficients isometryCoefficients_adouble(coefficientBasis.size()); - /** - * @brief Copy the current iterate into a data type that encapsulates the isometry constraint - * i. e. convert coefficient data structure from 'VectorSpaceCoefficients' to 'IsometryCoefficients' - */ - vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients); - vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients_adouble); - /** - * @brief TEST: conversion of coefficient vectors (back & forth) - */ - coefficientConversionTest<VectorSpaceCoefficients, DeformationBasis, CoefficientBasis, IsometryCoefficients>(x, deformationBasis, coefficientBasis); + /** + * @brief We need to setup LocalDiscreteKirchhoffBendingIsometry with a coefficient + * vector of ctype 'adouble' while the solver gets a coefficient vector + * of ctype 'double'. + */ + IsometryCoefficients isometryCoefficients(coefficientBasis.size()); + AIsometryCoefficients isometryCoefficients_adouble(coefficientBasis.size()); - + /** + * @brief Copy the current iterate into a data type that encapsulates the isometry constraint + * i. e. convert coefficient data structure from 'VectorSpaceCoefficients' to 'IsometryCoefficients' + */ + vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients); + vectorToIsometryCoefficientMap(deformationBasis,coefficientBasis,x,isometryCoefficients_adouble); - using LocalDKFunction = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, AIsometryCoefficients>; - LocalDKFunction localDKFunction(deformationBasis, coefficientBasis, isometryCoefficients_adouble); + /** + * @brief TEST: conversion of coefficient vectors (back & forth) + */ + coefficientConversionTest<VectorSpaceCoefficients, DeformationBasis, CoefficientBasis, IsometryCoefficients>(x, deformationBasis, coefficientBasis); - /** - * @brief TEST: check isometry condition on the nodes of the grid for initial deformation. - */ - // auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x); - // nodewiseIsometryTest(initialDeformationFunction); - nodewiseIsometryTest(localDKFunction, gridView); - /** - * @brief Read force term. - */ - auto pythonForce = Python::make_function<FieldVector<double,3>>(pyModule.get("force")); - auto forceGVF = Dune::Functions::makeGridViewFunction(pythonForce, gridView); - auto localForce = localFunction(forceGVF); + using LocalDKFunction = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, AIsometryCoefficients>; + LocalDKFunction localDKFunction(deformationBasis, coefficientBasis, isometryCoefficients_adouble); - /** - * @brief Read effective prestrain Tensor - */ - // Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3>>("effectivePrestrain", {0.0, 0.0, 0.0}); - // Dune::FieldMatrix<adouble,2,2> effectivePrestrain = {{(adouble)Beffvec[0], (adouble)Beffvec[2]}, {(adouble)Beffvec[2],(adouble)Beffvec[1]} }; - // printmatrix(std::cout, effectivePrestrain, "effective prestrain (Beff): ", "--"); + /** + * @brief TEST: check isometry condition on the nodes of the grid for initial deformation. + */ + // auto initialDeformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x); + // nodewiseIsometryTest(initialDeformationFunction); + nodewiseIsometryTest(localDKFunction, gridView); - /** - * @brief Get effective quadratic form Qhom - * - * input-vector: [q_1,q_2,q_3,q_12,q_13,q_23] - * is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper) - * ( q_1 , 0.5*q_12 , 0.5*q_13 ) - * Q = ( 0.5*q_12 , q_2 , 0.5*q_23 ) - * ( 0.5*q_13 , 0.5*q_23 , q_3 ) - */ - // Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); - // Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)0.5*Qhomvec[3], (adouble)0.5*Qhomvec[4]}, - // {(adouble)0.5*Qhomvec[3], (adouble)Qhomvec[1], (adouble)0.5*Qhomvec[5]}, - // {(adouble)0.5*Qhomvec[4], (adouble)0.5*Qhomvec[5], (adouble)Qhomvec[2]}}; - // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--"); + /** + * @brief Read force term. + */ + auto pythonForce = Python::make_function<FieldVector<double,3> >(pyModule.get("force")); + auto forceGVF = Dune::Functions::makeGridViewFunction(pythonForce, gridView); + auto localForce = localFunction(forceGVF); - //////////////////////////////////////////////////////////////////////// - // Create an assembler for the Discrete Kirchhoff Energy Functional (using ADOL-C) - //////////////////////////////////////////////////////////////////////// - /** - * @brief Setup nonconforming energy - */ - // auto localEnergy_nonconforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergy<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); - /** - * @brief Setup conforming energy (WIP) - */ - // auto localEnergy_conforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyZienkiewicz<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); - // auto localEnergy_conforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyZienkiewiczProjected<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); - /** - * @brief Setup energy featuring prestrain - */ - // auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, Qhom, effectivePrestrain, parameterSet); - // auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule); + /** + * @brief Read effective prestrain Tensor + */ + // Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3>>("effectivePrestrain", {0.0, 0.0, 0.0}); + // Dune::FieldMatrix<adouble,2,2> effectivePrestrain = {{(adouble)Beffvec[0], (adouble)Beffvec[2]}, {(adouble)Beffvec[2],(adouble)Beffvec[1]} }; + // printmatrix(std::cout, effectivePrestrain, "effective prestrain (Beff): ", "--"); - // // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_conforming(localEnergy_conforming.get()); - // // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_nonconforming(localEnergy_nonconforming.get()); - // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_prestrain(localEnergy_prestrain.get()); - // // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_conforming(coefficientBasis, localGFEADOLCStiffness_conforming); - // // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_nonconforming(coefficientBasis, localGFEADOLCStiffness_nonconforming); - // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_prestrain(coefficientBasis, localGFEADOLCStiffness_prestrain); - auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule); - auto localGFEADOLCStiffness_prestrain = std::make_shared<LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> >(localEnergy_prestrain); - std::shared_ptr<GeodesicFEAssembler<CoefficientBasis, Coefficient> > assembler_prestrain; - assembler_prestrain = std::make_shared<GeodesicFEAssembler<CoefficientBasis, Coefficient> >(coefficientBasis, localGFEADOLCStiffness_prestrain); + /** + * @brief Get effective quadratic form Qhom + * + * input-vector: [q_1,q_2,q_3,q_12,q_13,q_23] + * is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper) + * ( q_1 , 0.5*q_12 , 0.5*q_13 ) + * Q = ( 0.5*q_12 , q_2 , 0.5*q_23 ) + * ( 0.5*q_13 , 0.5*q_23 , q_3 ) + */ + // Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0}); + // Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)0.5*Qhomvec[3], (adouble)0.5*Qhomvec[4]}, + // {(adouble)0.5*Qhomvec[3], (adouble)Qhomvec[1], (adouble)0.5*Qhomvec[5]}, + // {(adouble)0.5*Qhomvec[4], (adouble)0.5*Qhomvec[5], (adouble)Qhomvec[2]}}; + // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--"); + //////////////////////////////////////////////////////////////////////// + // Create an assembler for the Discrete Kirchhoff Energy Functional (using ADOL-C) + //////////////////////////////////////////////////////////////////////// + /** + * @brief Setup nonconforming energy + */ + // auto localEnergy_nonconforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergy<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); + /** + * @brief Setup conforming energy (WIP) + */ + // auto localEnergy_conforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyZienkiewicz<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); + // auto localEnergy_conforming = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyZienkiewiczProjected<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce); + /** + * @brief Setup energy featuring prestrain + */ + // auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, Qhom, effectivePrestrain, parameterSet); + // auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule); + // // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_conforming(localEnergy_conforming.get()); + // // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_nonconforming(localEnergy_nonconforming.get()); + // LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_prestrain(localEnergy_prestrain.get()); + // // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_conforming(coefficientBasis, localGFEADOLCStiffness_conforming); + // // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_nonconforming(coefficientBasis, localGFEADOLCStiffness_nonconforming); + // GeodesicFEAssembler<CoefficientBasis, Coefficient> assembler_prestrain(coefficientBasis, localGFEADOLCStiffness_prestrain); + auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient> >(localDKFunction, localForce, parameterSet, pyModule); + auto localGFEADOLCStiffness_prestrain = std::make_shared<LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> >(localEnergy_prestrain); + std::shared_ptr<GeodesicFEAssembler<CoefficientBasis, Coefficient> > assembler_prestrain; + assembler_prestrain = std::make_shared<GeodesicFEAssembler<CoefficientBasis, Coefficient> >(coefficientBasis, localGFEADOLCStiffness_prestrain); - /** - * @brief Create a solver: - * - Riemannian Newton with Hessian modification - * - Riemannian Trust-region - */ - RiemannianProximalNewtonSolver<CoefficientBasis, Coefficient> RNHMsolver; - RiemannianTrustRegionSolver<CoefficientBasis, Coefficient> RTRsolver; - std::string Solver_name = parameterSet.get<std::string>("Solver", "RNHM"); - double numerical_energy; //final discrete energy - if(Solver_name == "RNHM") - { - RNHMsolver.setup(*grid, - &(*assembler_prestrain), - isometryCoefficients, - dirichletNodes, - parameterSet); + /** + * @brief Create a solver: + * - Riemannian Newton with Hessian modification + * - Riemannian Trust-region + */ + RiemannianProximalNewtonSolver<CoefficientBasis, Coefficient> RNHMsolver; + RiemannianTrustRegionSolver<CoefficientBasis, Coefficient> RTRsolver; - RNHMsolver.solve(); - isometryCoefficients = RNHMsolver.getSol(); - numerical_energy = RNHMsolver.getStatistics().finalEnergy; - } else if (Solver_name =="RiemannianTR") - { - std::cout << "Using Riemannian Trust-region method for energy minimization." << std::endl; - RTRsolver.setup(*grid, - &(*assembler_prestrain), - isometryCoefficients, - dirichletNodes, - parameterSet); - RTRsolver.solve(); - isometryCoefficients = RTRsolver.getSol(); - numerical_energy = RTRsolver.getStatistics().finalEnergy; - } else - DUNE_THROW(Dune::Exception, "Unknown Solver type for bending isometries."); + std::string Solver_name = parameterSet.get<std::string>("Solver", "RNHM"); + double numerical_energy; //final discrete energy + if(Solver_name == "RNHM") + { - // Convert coefficient data structure from 'IsometryCoefficients' to 'VectorSpaceCoefficients' - VectorSpaceCoefficients x_out(deformationBasis.size()); - isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_out,isometryCoefficients); + RNHMsolver.setup(*grid, + &(*assembler_prestrain), + isometryCoefficients, + dirichletNodes, + parameterSet); - //////////////////////////////// - // Output result - //////////////////////////////// - std::string baseNameDefault = "bending-isometries-"; - std::string baseName = parameterSet.get("baseName", baseNameDefault); - std::string resultFileName = parameterSet.get("resultPath", "") - + "/" + baseName - + "_level" + std::to_string(parameterSet.get<int>("macroGridLevel")); + RNHMsolver.solve(); + isometryCoefficients = RNHMsolver.getSol(); + numerical_energy = RNHMsolver.getStatistics().finalEnergy; + } else if (Solver_name =="RiemannianTR") + { + std::cout << "Using Riemannian Trust-region method for energy minimization." << std::endl; + RTRsolver.setup(*grid, + &(*assembler_prestrain), + isometryCoefficients, + dirichletNodes, + parameterSet); + RTRsolver.solve(); + isometryCoefficients = RTRsolver.getSol(); + numerical_energy = RTRsolver.getStatistics().finalEnergy; + } else + DUNE_THROW(Dune::Exception, "Unknown Solver type for bending isometries."); - if (parameterSet.get<bool>("conforming_DiscreteJacobian", 1)) - resultFileName = resultFileName + "_C"; - else - resultFileName = resultFileName + "_NC"; - // Create a deformation function but this time with double-types. - using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; - LocalDKFunctionD localDKFunctionDouble(deformationBasis, coefficientBasis, isometryCoefficients); + // Convert coefficient data structure from 'IsometryCoefficients' to 'VectorSpaceCoefficients' + VectorSpaceCoefficients x_out(deformationBasis.size()); + isometryToVectorCoefficientMap(deformationBasis,coefficientBasis,x_out,isometryCoefficients); + //////////////////////////////// + // Output result + //////////////////////////////// + std::string baseNameDefault = "bending-isometries-"; + std::string baseName = parameterSet.get("baseName", baseNameDefault); + std::string resultFileName = parameterSet.get("resultPath", "") + + "/" + baseName + + "_level" + std::to_string(parameterSet.get<int>("macroGridLevel")); + if (parameterSet.get<bool>("conforming_DiscreteJacobian", 1)) + resultFileName = resultFileName + "_C"; + else + resultFileName = resultFileName + "_NC"; + // Create a deformation function but this time with double-types. + using LocalDKFunctionD = GFE::LocalDiscreteKirchhoffBendingIsometry<DeformationBasis, CoefficientBasis, IsometryCoefficients>; + LocalDKFunctionD localDKFunctionDouble(deformationBasis, coefficientBasis, isometryCoefficients); - if (parameterSet.get<bool>("writeVTK", 1)) - { - std::cout << "write VTK..." << std::endl; - /** - * @brief Compute the displacement from the deformation. - * interpolate the identity and substract from the coefficient vector. - */ - VectorSpaceCoefficients identity(deformationBasis.size()); - IdentityGridEmbedding<double> identityGridEmbedding; - interpolate(deformationBasis, identity, identityGridEmbedding); - // auto identity_tmp = identity; - // Compute the displacement - auto displacement = x_out; - displacement -= identity; - // std::cout << "displacement.size():" << displacement.size() << std::endl; - auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, x_out); - auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacement); + if (parameterSet.get<bool>("writeVTK", 1)) + { + std::cout << "write VTK..." << std::endl; - /** - * @brief We need to subsample, because VTK cannot natively display real third-order functions - */ - int subsamplingRefinement = parameterSet.get<int>("subsamplingRefinement", 2); - SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(subsamplingRefinement)); - // SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(2)); + /** + * @brief Compute the displacement from the deformation. + * interpolate the identity and substract from the coefficient vector. + */ + VectorSpaceCoefficients identity(deformationBasis.size()); + IdentityGridEmbedding<double> identityGridEmbedding; + interpolate(deformationBasis, identity, identityGridEmbedding); + // auto identity_tmp = identity; + // Compute the displacement + auto displacement = x_out; + displacement -= identity; - /** - * @brief Basis used to represent normal vector fields - * - */ - auto normalBasis = makeBasis(gridView, - power<3>( - lagrange<1>(), - flatLexicographic())); - // auto normalBasis = makeBasis(gridView, - // power<3>( - // lagrange<1>(), - // blockedInterleaved())); + // std::cout << "displacement.size():" << displacement.size() << std::endl; + auto deformationFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, x_out); + auto displacementFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationBasis, displacement); + /** + * @brief We need to subsample, because VTK cannot natively display real third-order functions + */ + int subsamplingRefinement = parameterSet.get<int>("subsamplingRefinement", 2); + SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(subsamplingRefinement)); + // SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(2)); - // TEST Compute - // auto normalLambda = [deformationFunction](const FieldVector<double,2>& x) - // { - // // deformationfunction.derivative() ... //needs binding?! - + /** + * @brief Basis used to represent normal vector fields + * + */ + auto normalBasis = makeBasis(gridView, + power<3>( + lagrange<1>(), + flatLexicographic())); + // auto normalBasis = makeBasis(gridView, + // power<3>( + // lagrange<1>(), + // blockedInterleaved())); - // } - + // TEST Compute - /** - * @brief Interpolate and VTK-write analytical solution "u" from ParamterFile. - */ - if (parameterSet.get<bool>("vtkwrite_analyticalSolution", 0)) - { - // auto pythonAnalyticalSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); - auto pythonAnalyticalSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("displacement"), pyModule.get("displacementGradient")); + // auto normalLambda = [deformationFunction](const FieldVector<double,2>& x) + // { + // // deformationfunction.derivative() ... //needs binding?! - // deprecated: interpolate ... - // VectorSpaceCoefficients y(deformationBasis.size()); - // interpolate(deformationBasis, y, pythonAnalyticalSolution); - // // Compute the displacement - // auto displacementAnalytical = y; - // // displacementAnalytical -= identity_tmp; - // displacementAnalytical -= identity; + // } - // auto pythonIdentity = Python::make_function<FieldVector<double,3>>(IdentityGridEmbedding<double>::operator()) - // auto displacementFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacementAnalytical); - // auto deformationFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, y); - // vtkWriter.addVertexData(displacementFunctionAnalytical, VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); - // vtkWriter.addVertexData(deformationFunctionAnalytical, VTK::FieldInfo("deformation_analytical", VTK::FieldInfo::Type::vector, 3)); - - vtkWriter.addVertexData((pythonAnalyticalSolution), VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); /** - * @brief Get the normal vector field of the surface parametrized - * by the analytical solution. - * - We represent the normal vector in a first order Lagrange-Power basis ('normalBasis'). + * @brief Interpolate and VTK-write analytical solution "u" from ParamterFile. */ - if (parameterSet.get<bool>("vtkWrite_analyticalSurfaceNormal", 0)) + if (parameterSet.get<bool>("vtkwrite_analyticalSolution", 0)) { - // Get the surface normal function. - auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3>>(pyModule.get("surfaceNormal")); + // auto pythonAnalyticalSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("u"), pyModule.get("du")); + auto pythonAnalyticalSolution = Python::makeDifferentiableFunction<FieldVector<double,3>(FieldVector<double,2>)>(pyModule.get("displacement"), pyModule.get("displacementGradient")); - // deprecated: interpolate ... - // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); - // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); - // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); - // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); + // deprecated: interpolate ... + // VectorSpaceCoefficients y(deformationBasis.size()); + // interpolate(deformationBasis, y, pythonAnalyticalSolution); + // // Compute the displacement + // auto displacementAnalytical = y; + // // displacementAnalytical -= identity_tmp; + // displacementAnalytical -= identity; - vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); - } - } - //------------------------------------------------------------------------------------- TODO: OUTSOURCE - /** - * @brief TEST: Compute the discrete normal vector of the surface parametrized - * by the discrete solution. - */ - auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); - //------------------------------------------------------------------------------------- - - // Create DiscreteGlobalBasisFunctions. - auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, surfaceNormalDiscreteCoefficients); - vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::vector, 3)); - vtkWriter.addVertexData(surfaceNormalDiscrete , VTK::FieldInfo("surfaceNormal_discrete", VTK::FieldInfo::Type::vector, 3)); - vtkWriter.write(resultFileName); - } + // auto pythonIdentity = Python::make_function<FieldVector<double,3>>(IdentityGridEmbedding<double>::operator()) + + // auto displacementFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, displacementAnalytical); + // auto deformationFunctionAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(deformationBasis, y); + // vtkWriter.addVertexData(displacementFunctionAnalytical, VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); + // vtkWriter.addVertexData(deformationFunctionAnalytical, VTK::FieldInfo("deformation_analytical", VTK::FieldInfo::Type::vector, 3)); + + vtkWriter.addVertexData((pythonAnalyticalSolution), VTK::FieldInfo("displacement_analytical", VTK::FieldInfo::Type::vector, 3)); /** - * @brief Measure errors. - * 1. Compute the Isometry-Error - * 2. Compute the L2-Error and H1-SemiError as well as the energy difference - * between the discrete deformation u_h and the analytical deformation u . + * @brief Get the normal vector field of the surface parametrized + * by the analytical solution. + * - We represent the normal vector in a first order Lagrange-Power basis ('normalBasis'). */ - if (parameterSet.get<bool>("measure_isometryError", 0)) + if (parameterSet.get<bool>("vtkWrite_analyticalSurfaceNormal", 0)) { - auto isometry_errors = isometryError(localDKFunctionDouble, gridView); - if(isometry_errors[1] > Isometry_threshold[experimentNumber-1]) // Isometry-L2-error - { - std::cerr << std::setprecision(9); - std::cerr << "Isometry-L2-error is to large! " << std::endl; - std::cerr << "Isometry-L2-error is to large: "<< isometry_errors[1] << " but threshold is " << Isometry_threshold[experimentNumber-1] << std::endl; - return 1; - } + // Get the surface normal function. + auto pythonSurfaceNormal = Python::make_function<FieldVector<double,3> >(pyModule.get("surfaceNormal")); - } - - if (parameterSet.get<bool>("measure_analyticalError", 0)) - { - auto discretization_errors = measureAnalyticalError(localDKFunctionDouble,gridView,pyModule); - - - /** - * @brief Check Quantities - * - */ - // L2 - Discretization error - if(discretization_errors[0] > L2_threshold[experimentNumber-1]) - { - std::cerr << std::setprecision(9); - std::cerr << "L2-error is to large: "<<discretization_errors[0] << " but threshold is " << L2_threshold[experimentNumber-1] << std::endl; - return 1; - } - // H1(semi) - Discretization error - if(discretization_errors[1] > H1_threshold[experimentNumber-1]) - { - std::cerr << std::setprecision(9); - std::cerr << "H1-error is to large: "<< discretization_errors[1] << " but threshold is " << H1_threshold[experimentNumber-1] << std::endl; - return 1; - } - } - + // deprecated: interpolate ... + // std::vector<FieldVector<double,3>> normalVectorCoefficients(normalBasis.size()); + // Dune::Functions::interpolate(normalBasis, normalVectorCoefficients, pythonSurfaceNormal); + // auto surfaceNormalAnalytical = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3>>(normalBasis, normalVectorCoefficients); + // vtkWriter.addVertexData(surfaceNormalAnalytical, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); - /** - * @brief Write Energy values. - * - */ - // auto numerical_energy = solver.getStatistics().finalEnergy; - std::cout << "(Final) Energy of discrete solution: " << numerical_energy<< std::endl; - if (parameterSet.get<bool>("compare_EnergyValues", 0)) - { - auto analytical_energy = parameterSet.get<double>("analytical_energy"); - auto energy_difference = analytical_energy - numerical_energy; - std::cout << "Analytical energy: " << analytical_energy<< std::endl; - std::cout << "Energy difference: " << energy_difference << std::endl; - - if(energy_difference > Energy_threshold[experimentNumber-1] ) - { - std::cerr << std::setprecision(9); - std::cerr << "Energy difference is to large:" << energy_difference << " but threshold is " << Energy_threshold[experimentNumber-1] << std::endl; - return 1; - } + vtkWriter.addVertexData(pythonSurfaceNormal, VTK::FieldInfo("surfaceNormal_analytical", VTK::FieldInfo::Type::vector, 3)); } + } + //------------------------------------------------------------------------------------- TODO: OUTSOURCE + /** + * @brief TEST: Compute the discrete normal vector of the surface parametrized + * by the discrete solution. + */ + auto surfaceNormalDiscreteCoefficients = computeDiscreteSurfaceNormal(localDKFunctionDouble, normalBasis); + //------------------------------------------------------------------------------------- + + // Create DiscreteGlobalBasisFunctions. + auto surfaceNormalDiscrete = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(normalBasis, surfaceNormalDiscreteCoefficients); + vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::vector, 3)); + vtkWriter.addVertexData(surfaceNormalDiscrete , VTK::FieldInfo("surfaceNormal_discrete", VTK::FieldInfo::Type::vector, 3)); + vtkWriter.write(resultFileName); + } + + + /** + * @brief Measure errors. + * 1. Compute the Isometry-Error + * 2. Compute the L2-Error and H1-SemiError as well as the energy difference + * between the discrete deformation u_h and the analytical deformation u . + */ + if (parameterSet.get<bool>("measure_isometryError", 0)) + { + auto isometry_errors = isometryError(localDKFunctionDouble, gridView); + if(isometry_errors[1] > Isometry_threshold[experimentNumber-1]) // Isometry-L2-error + { + std::cerr << std::setprecision(9); + std::cerr << "Isometry-L2-error is to large! " << std::endl; + std::cerr << "Isometry-L2-error is to large: "<< isometry_errors[1] << " but threshold is " << Isometry_threshold[experimentNumber-1] << std::endl; + return 1; + } + + } + + if (parameterSet.get<bool>("measure_analyticalError", 0)) + { + auto discretization_errors = measureAnalyticalError(localDKFunctionDouble,gridView,pyModule); + + + /** + * @brief Check Quantities + * + */ + // L2 - Discretization error + if(discretization_errors[0] > L2_threshold[experimentNumber-1]) + { + std::cerr << std::setprecision(9); + std::cerr << "L2-error is to large: "<<discretization_errors[0] << " but threshold is " << L2_threshold[experimentNumber-1] << std::endl; + return 1; + } + // H1(semi) - Discretization error + if(discretization_errors[1] > H1_threshold[experimentNumber-1]) + { + std::cerr << std::setprecision(9); + std::cerr << "H1-error is to large: "<< discretization_errors[1] << " but threshold is " << H1_threshold[experimentNumber-1] << std::endl; + return 1; + } + } - // // Write the corresponding coefficient vector: verbatim in binary, to be completely lossless - // char iFilename[200]; - // sprintf(iFilename, (resultFileName + ".data").c_str()); - // FILE* fpIterate = fopen(iFilename, "wb"); - // if (!fpIterate) - // DUNE_THROW(SolverError, "Couldn't open file " << iFilename << " for writing"); - // for (size_t j=0; j<isometryCoefficients.size(); j++) - // fwrite(&isometryCoefficients[j], sizeof(Coefficient), 1, fpIterate); + /** + * @brief Write Energy values. + * + */ + // auto numerical_energy = solver.getStatistics().finalEnergy; + std::cout << "(Final) Energy of discrete solution: " << numerical_energy<< std::endl; + if (parameterSet.get<bool>("compare_EnergyValues", 0)) + { + auto analytical_energy = parameterSet.get<double>("analytical_energy"); + auto energy_difference = analytical_energy - numerical_energy; + std::cout << "Analytical energy: " << analytical_energy<< std::endl; + std::cout << "Energy difference: " << energy_difference << std::endl; - // fclose(fpIterate); + if(energy_difference > Energy_threshold[experimentNumber-1] ) + { + std::cerr << std::setprecision(9); + std::cerr << "Energy difference is to large:" << energy_difference << " but threshold is " << Energy_threshold[experimentNumber-1] << std::endl; + return 1; + } + } + + // // Write the corresponding coefficient vector: verbatim in binary, to be completely lossless + // char iFilename[200]; + // sprintf(iFilename, (resultFileName + ".data").c_str()); + + // FILE* fpIterate = fopen(iFilename, "wb"); + // if (!fpIterate) + // DUNE_THROW(SolverError, "Couldn't open file " << iFilename << " for writing"); + + // for (size_t j=0; j<isometryCoefficients.size(); j++) + // fwrite(&isometryCoefficients[j], sizeof(Coefficient), 1, fpIterate); + + // fclose(fpIterate); #if 0 - // Write the corresponding coefficient vector: verbatim in binary, to be completely lossless - typedef BlockVector<typename Coefficient::CoordinateType> EmbeddedVectorType; - EmbeddedVectorType xEmbedded(isometryCoefficients.size()); - for (size_t i = 0; i<isometryCoefficients.size(); i++) - { - xEmbedded[i] = isometryCoefficients[i].globalCoordinates(); - std::cout << "isometryCoefficients[i].globalCoordinates():" << isometryCoefficients[i].globalCoordinates() << std::endl; + // Write the corresponding coefficient vector: verbatim in binary, to be completely lossless + typedef BlockVector<typename Coefficient::CoordinateType> EmbeddedVectorType; + EmbeddedVectorType xEmbedded(isometryCoefficients.size()); + for (size_t i = 0; i<isometryCoefficients.size(); i++) + { + xEmbedded[i] = isometryCoefficients[i].globalCoordinates(); + std::cout << "isometryCoefficients[i].globalCoordinates():" << isometryCoefficients[i].globalCoordinates() << std::endl; - } - std::ofstream outFile(resultFileName + ".data", std::ios_base::binary); - MatrixVector::Generic::writeBinary(outFile, xEmbedded); - outFile.close(); - /////////////////////////////////////////// - // (Option) write Solution(DOF)-vector and vertex coordinates to .txt-File - /////////////////////////////////////////// - if (parameterSet.get<bool>("writeDOFvector", 0)) - writeDOFVector(gridView,targetDim, x, "DOFVectorR" + std::to_string(dim) + "_R" + std::to_string(targetDim) + ".txt"); + } + std::ofstream outFile(resultFileName + ".data", std::ios_base::binary); + MatrixVector::Generic::writeBinary(outFile, xEmbedded); + outFile.close(); + /////////////////////////////////////////// + // (Option) write Solution(DOF)-vector and vertex coordinates to .txt-File + /////////////////////////////////////////// + if (parameterSet.get<bool>("writeDOFvector", 0)) + writeDOFVector(gridView,targetDim, x, "DOFVectorR" + std::to_string(dim) + "_R" + std::to_string(targetDim) + ".txt"); #endif - std::cout << "TEST - " << experiment << "passed." << std::endl; - std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; + std::cout << "TEST - " << experiment << "passed." << std::endl; + std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl; } std::cout << "Properties-shape-test passed." << std::endl; return 0; - } \ No newline at end of file +} diff --git a/test/readmicrostructuretest.cc b/test/readmicrostructuretest.cc index 0e728264ed1c943b9e2180e5fe12bedacadd7235..11464e2a359218dca3ee7ffbf1173113bc8d6492 100644 --- a/test/readmicrostructuretest.cc +++ b/test/readmicrostructuretest.cc @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) MPIHelper::instance(argc, argv); Dune::Timer globalTimer; - //--- setup Log-File + //--- setup Log-File std::fstream log; std::cout << "Current path is " << std::filesystem::current_path() << '\n'; @@ -111,9 +111,9 @@ int main(int argc, char *argv[]) Python::start(); auto pyMain = Python::main(); pyMain.runStream() - << std::endl << "import math" - << std::endl << "import sys" - << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; + << std::endl << "import math" + << std::endl << "import sys" + << std::endl << "sys.path.append('" << dir_path << "')" << std::endl; auto pyModule = pyMain.import("readmicrostructuretest"); ParameterTree parameterSet; @@ -175,9 +175,9 @@ int main(int argc, char *argv[]) /** * @brief Create instance of class - * This needs to be a 'Python::Reference' and not 'Python::Callable' + * This needs to be a 'Python::Reference' and not 'Python::Callable' * since Callable only works if __call__(self,x) is implemented in the python module!!! - * + * */ Python::Reference microstructure = MicrostructureClass(); //Setup a constant microstructure @@ -200,7 +200,7 @@ int main(int argc, char *argv[]) std::cout << "microstructure phaseType:" << phaseType << std::endl; Dune::FieldVector<double,2> materialParameters(0); - microstructure.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,2>>(materialParameters); + microstructure.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; @@ -219,24 +219,24 @@ int main(int argc, char *argv[]) std::cout << "orthotropic material with material rotation axis: " << axis << std::endl; std::cout << "orthotropic material with material rotation angle: " << angle << std::endl; - - microstructure.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9>>(materialParameters_orthotropic); + + microstructure.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldVector<double,9> >(materialParameters_orthotropic); printvector(std::cout, materialParameters_orthotropic, "materialParameters_orthotropic: ", "--"); // anisotropic material setup - Dune::FieldMatrix<double,6,6> materialParameters_anisotropic(0); + Dune::FieldMatrix<double,6,6> materialParameters_anisotropic(0); phase = 4; microstructure.get("phase" + std::to_string(phase) + "_type").toC<std::string>(phaseType); std::cout << "microstructure phaseType:" << phaseType << std::endl; - microstructure.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6>>(materialParameters_anisotropic); + microstructure.get("materialParameters_phase" + std::to_string(phase)).toC<Dune::FieldMatrix<double,6,6> >(materialParameters_anisotropic); printmatrix(std::cout, materialParameters_anisotropic, "materialParameters_anisotropic: ", "--"); - //Get prestrain of phase - auto prestrain1 = Python::make_function<Dune::FieldMatrix<double,3,3>>(Python::Callable(microstructure.get("prestrain_phase" + std::to_string(phase)))); + //Get prestrain of phase + auto prestrain1 = Python::make_function<Dune::FieldMatrix<double,3,3> >(Python::Callable(microstructure.get("prestrain_phase" + std::to_string(phase)))); auto localPrestrain1 = localFunction(Dune::Functions::makeGridViewFunction(prestrain1, gridView_CE)); @@ -275,7 +275,7 @@ int main(int argc, char *argv[]) // auto correctorComputer = CorrectorComputer(Basis_CE, material, log, parameterSet); // correctorComputer.assemble(); // correctorComputer.solve(); - std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType>>(Basis_CE, material, parameterSet); + std::shared_ptr<CorrectorComputer<decltype(Basis_CE),MaterialType> > correctorComputer = std::make_shared<CorrectorComputer<decltype(Basis_CE),MaterialType> >(Basis_CE, material, parameterSet); correctorComputer->assemble(); correctorComputer->solve();