#ifndef DUNE_MICROSTRUCTURE_CORRECTORCOMPUTER_HH #define DUNE_MICROSTRUCTURE_CORRECTORCOMPUTER_HH #include <map> #include <dune/common/parametertree.hh> // #include <dune/common/float_cmp.hh> #include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh> #include <dune/istl/matrixindexset.hh> #include <dune/functions/functionspacebases/interpolate.hh> #include <dune/functions/gridfunctions/gridviewfunction.hh> #include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh> #include <dune/microstructure/matrix_operations.hh> #include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number #include <dune/solvers/solvers/umfpacksolver.hh> #include <dune/microstructure/voigthelper.hh> using namespace MatrixOperations; using std::shared_ptr; using std::make_shared; using std::fstream; template <class Basis, class Material> //, class LocalScalar, class Local2Tensor> // LocalFunction derived from basis? 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>; protected: //private: const Basis& basis_; const Material& material_; double gamma_; fstream& log_; // Output-log const Dune::ParameterTree& parameterSet_; // const FuncScalar mu_; // const FuncScalar lambda_; 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 Dune::FieldVector<double,3> m_1_, m_2_, m_3_; // Corrector m_i coefficient vectors // (assembled) corrector matrices M_i std::array<MatrixRT, 3 > mContainer; const std::array<VectorCT, 3> phiContainer = {phi_1_,phi_2_,phi_3_}; // ---- Basis for R_sym^{2x2} // Could really be constexpr static, but then we would need to write the basis here directly in Voigt notation. // However, I suspect that our Voigt representation may still change in the future. 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}}; //TODO könnte hier sign übergeben? }; 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}}; }; 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 const int phiOffset_; public: /////////////////////////////// // constructor /////////////////////////////// CorrectorComputer( const Basis& basis, const Material& material, double gamma, std::fstream& log, const Dune::ParameterTree& parameterSet) : basis_(basis), material_(material), gamma_(gamma), 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(); //write VTK call here... } // ----------------------------------------------------------------- // --- Assemble Corrector problems void assemble() { Dune::Timer StiffnessTimer; assembleCellStiffness(stiffnessMatrix_); std::cout << "Stiffness assembly Timer: " << StiffnessTimer.elapsed() << std::endl; assembleCellLoad(load_alpha1_ ,x3G_1_); assembleCellLoad(load_alpha2_ ,x3G_2_); assembleCellLoad(load_alpha3_ ,x3G_3_); }; /////////////////////////////// // Getter /////////////////////////////// const shared_ptr<Basis> getBasis() {return make_shared<Basis>(basis_);} Dune::ParameterTree getParameterSet() const {return parameterSet_;} fstream* getLog(){return &log_;} double getGamma(){return 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<FuncScalar> getMu(){return make_shared<FuncScalar>(mu_);} // shared_ptr<FuncScalar> getLambda(){return make_shared<FuncScalar>(lambda_);} shared_ptr<Material> getMaterial(){return make_shared<Material>(material_);} // --- Get Correctors // shared_ptr<VectorCT> getMcontainer(){return make_shared<VectorCT>(mContainer);} // auto getMcontainer(){return make_shared<std::array<MatrixRT*, 3 > >(mContainer);} auto getMcontainer(){return mContainer;} shared_ptr<std::array<VectorCT, 3>> getPhicontainer(){return make_shared<std::array<VectorCT, 3>>(phiContainer);} // shared_ptr<std::array<VectorRT, 3>> getBasiscontainer(){return make_shared<std::array<VectorRT, 3>>(basisContainer_);} auto getMatrixBasiscontainer(){return make_shared<std::array<VoigtVector<double,3>,3 >>(matrixBasis_);} // auto getx3MatrixBasiscontainer(){return make_shared<std::array<Func2Tensor, 3>>(x3MatrixBasisContainer_);} auto getx3MatrixBasiscontainer(){return x3MatrixBasisContainer_;} // shared_ptr<VectorCT> getCorr_a(){return make_shared<VectorCT>(x_a_);} 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_);} // Get the occupation pattern of the stiffness matrix void getOccupationPattern(Dune::MatrixIndexSet& nb) { // OccupationPattern: // | phi*phi m*phi | // | phi *m m*m | auto localView = basis_.localView(); const int phiOffset = basis_.dimension(); nb.resize(basis_.size()+3, basis_.size()+3); for (const auto& element : elements(basis_.gridView())) { 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[0],col[0]); // nun würde auch nb.add(row,col) gehen.. } } for (size_t i=0; i<localView.size(); i++) { auto row = localView.index(i); for (size_t j=0; j<3; j++ ) { nb.add(row,phiOffset+j); // m*phi part of StiffnessMatrix nb.add(phiOffset+j,row); // phi*m part of StiffnessMatrix } } for (size_t i=0; i<3; i++ ) for (size_t j=0; j<3; j++ ) { nb.add(phiOffset+i,phiOffset+j); // m*m part of StiffnessMatrix } } ////////////////////////////////////////////////////////////////// // setOneBaseFunctionToZero ////////////////////////////////////////////////////////////////// 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); const auto& localFiniteElement = localView.tree().child(0).finiteElement(); // macht keinen Unterschied ob hier k oder 0.. const auto nSf = localFiniteElement.localBasis().size(); assert(arbitraryLeafIndex < nSf ); assert(arbitraryElementNumber < (std::size_t)basis_.gridView().size(0)); // "arbitraryElementNumber larger than total Number of Elements" //Determine 3 global indices (one for each component of an arbitrary local FE-function) row = arbitraryComponentwiseIndices(arbitraryElementNumber,arbitraryLeafIndex); for (int k = 0; k<3; k++) nb.add(row[k],row[k]); } std::cout << "finished occupation pattern\n"; } // template<class localFunction1, class localFunction2> // void computeElementStiffnessMatrix(const typename Basis::LocalView& localView, // ElementMatrixCT& elementMatrix, // const localFunction1& mu, // const localFunction2& lambda // ) /** \brief Compute the stiffness matrix for one element * * \param quadRule The quadrature rule to be used * \param phaseAtQuadPoint The material phase (i.e., the type of material) at each quadrature point */ void computeElementStiffnessMatrix(const typename Basis::LocalView& localView, const Dune::QuadratureRule<double,dim>& quadRule, const std::vector<int>& phaseAtQuadPoint, ElementMatrixCT& elementMatrix ) { // Local StiffnessMatrix of the form: // | phi*phi m*phi | // | phi *m m*m | auto element = localView.element(); auto geometry = element.geometry(); // using MatrixRT = FieldMatrix< double, dimworld, dimworld>; elementMatrix.setSize(localView.size()+3, localView.size()+3); //extend by dim ´R_sym^{2x2} elementMatrix = 0; // auto elasticityTensor = material_.getElasticityTensor(); // LocalBasis-Offset const int localPhiOffset = localView.size(); const auto& localFiniteElement = localView.tree().child(0).finiteElement(); const auto nSf = localFiniteElement.localBasis().size(); // std::cout << "localView.size(): " << localView.size() << std::endl; // std::cout << "nSf : " << nSf << std::endl; int QPcounter= 0; for (const auto& quadPoint : quadRule) { QPcounter++; const auto& quadPos = quadPoint.position(); const auto geometryJacobianInverse = geometry.jacobianInverse(quadPos); const auto integrationElement = geometry.integrationElement(quadPos); std::vector<Dune::FieldMatrix<double,1,dim> > jacobians; localFiniteElement.localBasis().evaluateJacobian(quadPos, jacobians); for (size_t i=0; i< jacobians.size(); i++) jacobians[i] = jacobians[i] * geometryJacobianInverse; // Compute the scaled deformation gradient for each shape function std::vector<std::array<VoigtVector<double,dim>,dimworld> > deformationGradient(nSf); for (size_t i=0; i < nSf; i++) { for (size_t k=0; k< dimworld; k++) { MatrixRT defGradientV(0); defGradientV[k] = jacobians[i][0]; deformationGradient[i][k] = symVoigt(crossSectionDirectionScaling((1.0/gamma_),defGradientV)); } } // Compute the material phase that the current quadrature point is in const auto phase = phaseAtQuadPoint[QPcounter-1]; for (size_t l=0; l< dimworld; l++) 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++) { // auto etmp = material_.applyElasticityTensor(defGradientU,element.geometry().global(quadPos)); // auto etmp = elasticityTensor(defGradientU,element.geometry().global(quadPos)); // auto etmp = material_.applyElasticityTensorLocal(defGradientU,quadPos); // printmatrix(std::cout, etmp, "etmp", "--"); // double energyDensity= scalarProduct(etmp,defGradientV); // double energyDensity= scalarProduct(material_.applyElasticityTensor(defGradientU,element.geometry().global(quadPos)),defGradientV); // auto tmp_1 = scalarProduct(elasticityTensor(defGradientU,indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)); // auto tmp_2 = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV); // if (abs(tmp_1-tmp_2)>1e-2) // { // std::cout << "difference :" << abs(tmp_1-tmp_2) << std::endl; // std::cout << "scalarProduct(elasticityTensor(defGradientU,indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV))" << scalarProduct(elasticityTensor(defGradientU,indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV))<< std::endl; // std::cout << "linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV)" << linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV)<< std::endl; // } // Python::Module module = Python::import("material_neukamm"); // auto PythonindicatorFunction = Python::make_function<int>(module.get("f")); // if (PythonindicatorFunction(element.geometry().global(quadPos)) != material_.applyIndicatorFunction(element.geometry().global(quadPos))) // { // std::cout <<" element.geometry().global(quadPos): " << element.geometry().global(quadPos) << std::endl; // std::cout << "PythonindicatorFunction(element.geometry().global(quadPos)): " << PythonindicatorFunction(element.geometry().global(quadPos)) << std::endl; // // std::cout << "mu(quadPos):" << mu(quadPos) << std::endl; // std::cout << "indicatorFunction(element.geometry().global(quadPos)): " << indicatorFunction(element.geometry().global(quadPos)) << std::endl; // std::cout << "material_.applyIndicatorFunction(element.geometry().global(quadPos)): " << material_.applyIndicatorFunction(element.geometry().global(quadPos)) << std::endl; // std::cout << "indicatorFunction_material_1: " << indicatorFunction_material_1(element.geometry().global(quadPos)) << std::endl; // } // double energyDensity= scalarProduct(material_.ElasticityTensorGlobal(defGradientU,element.geometry().global(quadPos)),sym(defGradientV)); // std::cout << "scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) " << scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) << std::endl; // std::cout << "linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV)" << linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV) << std::endl; // } // std::cout << "--------------- \n"; // printmatrix(std::cout, defGradientU, "defGradientU", "--"); // printmatrix(std::cout, material_.applyElasticityTensor(defGradientU,localIndicatorFunction(quadPos)), "material_.applyElasticityTensor(defGradientU,localIndicatorFunction(quadPos))", "--"); // printmatrix(std::cout, material_.ElasticityTensor(defGradientU,localIndicatorFunction(quadPos)), "material_.ElasticityTensor(defGradientU,localIndicatorFunction(quadPos)", "--"); double energyDensity= voigtScalarProduct(material_.applyElasticityTensor(deformationGradient[i][k],phase),deformationGradient[j][l]); // double energyDensity= scalarProduct(material_.ElasticityTensor(defGradientU,localIndicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor(defGradientU,localIndicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor(defGradientU,indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor(defGradientU,indicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensor(defGradientU,element.geometry().global(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(material_.localElasticityTensor(defGradientU,quadPos,element),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensor(defGradientU,quadPos),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensorLocal(defGradientU,quadPos),defGradientV); // double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV); // double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), defGradientU, defGradientV); //TEST // double energyDensity = generalizedDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV); // also works.. 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++) { // auto tmp_1 = scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) ; // auto tmp_2 = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV); // if (abs(tmp_1-tmp_2)>1e-2) // { // std::cout << "difference :" << abs(tmp_1-tmp_2) << std::endl; // std::cout << "scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) " << scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) << std::endl; // std::cout << "linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV)" << linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV) << std::endl; // } // double energyDensityGphi = scalarProduct(material_.ElasticityTensorGlobal(basisContainer[m],element.geometry().global(quadPos)),sym(defGradientV)); double energyDensityGphi = voigtScalarProduct(material_.applyElasticityTensor(matrixBasis_[m],phase),deformationGradient[j][l]); // double energyDensityGphi = scalarProduct(material_.ElasticityTensor(basisContainer[m],localIndicatorFunction(quadPos)),sym(defGradientV)); // double energyDensityGphi= scalarProduct(elasticityTensor(basisContainer[m],localIndicatorFunction(quadPos)),sym(defGradientV)); // std::cout << "scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV))" << scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)) <<std::endl; // std::cout << "linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV)" << linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV) << std::endl; // double energyDensityGphi= scalarProduct(material_.applyElasticityTensor(basisContainer[m],element.geometry().global(quadPos)),defGradientV); // double energyDensityGphi= scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)); // double energyDensityGphi= scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(quadPos)),sym(defGradientV)); // double energyDensityGphi= scalarProduct(material_.applyElasticityTensor(basisContainer[m],element.geometry().global(quadPos)),sym(defGradientV)); // double energyDensityGphi= scalarProduct(material_.applyElasticityTensor(basisContainer[m],quadPos),sym(defGradientV)); // double energyDensityGphi= scalarProduct(material_.localElasticityTensor(basisContainer[m],quadPos,element),sym(defGradientV)); // double energyDensityGphi= scalarProduct(elasticityTensor(basisContainer[m],element.geometry().global(quadPos)),defGradientV); // double energyDensityGphi= scalarProduct(material_.applyElasticityTensorLocal(basisContainer[m],quadPos),defGradientV); // double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV); // double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], defGradientV); //TEST 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++) { // std::cout << "QPcounter: " << QPcounter << std::endl; // std::cout << "m= " << m << " n = " << n << std::endl; // printmatrix(std::cout, basisContainer[m] , "basisContainer[m]", "--"); // printmatrix(std::cout, basisContainer[n] , "basisContainer[n]", "--"); // std::cout << "integrationElement:" << integrationElement << std::endl; // std::cout << "quadPoint.weight(): "<< quadPoint.weight() << std::endl; // std::cout << "mu(quadPos): " << mu(quadPos) << std::endl; // std::cout << "lambda(quadPos): " << lambda(quadPos) << std::endl; // auto tmp_1 = scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(basisContainer[n])); // auto tmp_2 = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n]); // if (abs(tmp_1-tmp_2)>1e-2) // { // std::cout << "difference :" << abs(tmp_1-tmp_2) << std::endl; // std::cout << "scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(basisContainer[n])):" << scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(basisContainer[n])) << std::endl; // std::cout << "linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n])" << linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n])<< std::endl; // } // double energyDensityGG = scalarProduct(material_.ElasticityTensorGlobal(basisContainer[m],element.geometry().global(quadPos)),sym(basisContainer[n])); double energyDensityGG = voigtScalarProduct(material_.applyElasticityTensor(matrixBasis_[m],phase),matrixBasis_[n]); // double energyDensityGG = scalarProduct(material_.ElasticityTensor(basisContainer[m],localIndicatorFunction(quadPos)),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(elasticityTensor(basisContainer[m],localIndicatorFunction(quadPos)),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(element.geometry().global(quadPos))),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(elasticityTensor(basisContainer[m],element.geometry().global(quadPos)),basisContainer[n]); // double energyDensityGG= scalarProduct(material_.applyElasticityTensor(basisContainer[m],element.geometry().global(quadPos)),basisContainer[n]); // double energyDensityGG= scalarProduct(elasticityTensor(basisContainer[m],indicatorFunction(quadPos)),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(material_.applyElasticityTensor(basisContainer[m],element.geometry().global(quadPos)),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(material_.applyElasticityTensor(basisContainer[m],quadPos),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(material_.localElasticityTensor(basisContainer[m],quadPos,element),sym(basisContainer[n])); // double energyDensityGG= scalarProduct(material_.applyElasticityTensorLocal(basisContainer[m],quadPos),basisContainer[n]); // double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n]); // double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], basisContainer[n]); //TEST elementMatrix[localPhiOffset+m][localPhiOffset+n] += energyDensityGG * quadPoint.weight() * integrationElement; // += !!!!! (Fixed-Bug) // std::cout << "energyDensityGG:" << energyDensityGG<< std::endl; // std::cout << "product " << energyDensityGG * quadPoint.weight() * integrationElement << std::endl; // printmatrix(std::cout, elementMatrix, "elementMatrix", "--"); } } // std::cout << "Number of QuadPoints:" << QPcounter << std::endl; // printmatrix(std::cout, elementMatrix, "elementMatrix", "--"); } // Compute the source term for a single element // < L (sym[D_gamma*nabla phi_i] + M_i ), x_3G_alpha > // template<class LocalFunction1, class LocalFunction2, class Vector, class LocalForce> // void computeElementLoadVector( const typename Basis::LocalView& localView, // LocalFunction1& mu, // LocalFunction2& lambda, // Vector& elementRhs, // const LocalForce& forceTerm // ) template<class Vector, class LocalForce> void computeElementLoadVector( const typename Basis::LocalView& localView, Vector& elementRhs, const LocalForce& forceTerm ) { // | f*phi| // | --- | // | f*m | // using Element = typename LocalView::Element; const auto element = localView.element(); const auto geometry = element.geometry(); // constexpr int dim = Element::dimension; // constexpr int dimworld = dim; // using MatrixRT = FieldMatrix< double, dimworld, dimworld>; // auto elasticityTensor = material_.getElasticityTensor(); // auto indicatorFunction = material_.getIndicatorFunction(); auto localIndicatorFunction = material_.getLocalIndicatorFunction(); localIndicatorFunction.bind(element); // // auto indicatorFunction = material_.getLocalIndicatorFunction(); // auto indicatorFunctionGVF = material_.getIndicatorFunctionGVF(); // auto indicatorFunction = localFunction(indicatorFunctionGVF); // indicatorFunction.bind(element); // Func2int indicatorFunction = *material_.getIndicatorFunction(); // Set of shape functions for a single element const auto& localFiniteElement= localView.tree().child(0).finiteElement(); const auto nSf = localFiniteElement.localBasis().size(); elementRhs.resize(localView.size() +3); elementRhs = 0; // LocalBasis-Offset const int localPhiOffset = localView.size(); // int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; // TEST // int orderQR = 0; // int orderQR = 1; // int orderQR = 2; // int orderQR = 3; int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); const auto& quad = Dune::QuadratureRules<double,dim>::rule(element.type(), orderQR); // std::cout << "Quad-Rule order used: " << orderQR << std::endl; for (const auto& quadPoint : quad) { const Dune::FieldVector<double,dim>& quadPos = quadPoint.position(); const auto geometryJacobianInverse = geometry.jacobianInverse(quadPos); const double integrationElement = geometry.integrationElement(quadPos); std::vector<Dune::FieldMatrix<double,1,dim> > jacobians; localFiniteElement.localBasis().evaluateJacobian(quadPos, jacobians); for (size_t i=0; i< jacobians.size(); i++) jacobians[i] = jacobians[i] * geometryJacobianInverse; //TEST // std::cout << "forceTerm(element.geometry().global(quadPos)):" << std::endl; // std::cout << forceTerm(element.geometry().global(quadPos)) << std::endl; // std::cout << "forceTerm(quadPos)" << std::endl; // std::cout << forceTerm(quadPos) << std::endl; // // //TEST QUadrature // std::cout << "quadPos:" << quadPos << std::endl; // std::cout << "element.geometry().global(quadPos):" << element.geometry().global(quadPos) << std::endl; // // // // // // // std::cout << "quadPoint.weight() :" << quadPoint.weight() << std::endl; // std::cout << "integrationElement(quadPos):" << integrationElement << std::endl; // std::cout << "mu(quadPos) :" << mu(quadPos) << std::endl; // std::cout << "lambda(quadPos) :" << lambda(quadPos) << std::endl; // "f*phi"-part for (size_t i=0; i < nSf; i++) for (size_t k=0; k < dimworld; k++) { // Deformation gradient of the ansatz basis function MatrixRT tmpDefGradientV(0); tmpDefGradientV[k][0] = jacobians[i][0][0]; // Y tmpDefGradientV[k][1] = jacobians[i][0][1]; // X2 // tmpDefGradientV[k][2] = (1.0/gamma_)*jacobians[i][0][2]; // tmpDefGradientV[k][2] = jacobians[i][0][2]; // X3 VoigtVector<double,3> defGradientV = symVoigt(crossSectionDirectionScaling((1.0/gamma_),tmpDefGradientV)); // double energyDensity= scalarProduct(material_.ElasticityTensorGlobal((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),sym(defGradientV)); double energyDensity= voigtScalarProduct(material_.applyElasticityTensor((-1.0)*matrixToVoigt(forceTerm(quadPos)),localIndicatorFunction(quadPos)),defGradientV); // double energyDensity= scalarProduct(material_.ElasticityTensor((-1.0)*forceTerm(quadPos),localIndicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),localIndicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),indicatorFunction(element.geometry().global(quadPos))),sym(defGradientV)); // double energyDensity= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),indicatorFunction(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),sym(defGradientV)); // double energyDensity= scalarProduct(material_.localElasticityTensor((-1.0)*forceTerm(quadPos),quadPos,element),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),quadPos),sym(defGradientV)); // double energyDensity= scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),defGradientV); // double energyDensity= scalarProduct(material_.applyElasticityTensorLocal((-1.0)*forceTerm(quadPos),quadPos),defGradientV); // double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),(-1.0)*forceTerm(quadPos), defGradientV ); // double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)),forceTerm(quadPos), defGradientV ); //TEST // double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),(-1.0)*forceTerm(quadPos), defGradientV ); //TEST // double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),forceTerm(element.geometry().global(quadPos)), defGradientV ); //TEST size_t row = localView.tree().child(k).localIndex(i); elementRhs[row] += energyDensity * quadPoint.weight() * integrationElement; } // "f*m"-part for (size_t m=0; m<3; m++) { // double energyDensityfG= scalarProduct(material_.ElasticityTensorGlobal((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),sym(basisContainer[m])); double energyDensityfG= voigtScalarProduct(material_.applyElasticityTensor((-1.0)*matrixToVoigt(forceTerm(quadPos)),localIndicatorFunction(quadPos)),matrixBasis_[m]); // double energyDensityfG= scalarProduct(material_.ElasticityTensor((-1.0)*forceTerm(quadPos),localIndicatorFunction(quadPos)),sym(basisContainer[m])); // double energyDensityfG= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),localIndicatorFunction(quadPos)),sym(basisContainer[m])); // double energyDensityfG= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),indicatorFunction(element.geometry().global(quadPos))),sym(basisContainer[m])); // double energyDensityfG= scalarProduct(elasticityTensor((-1.0)*forceTerm(quadPos),indicatorFunction(quadPos)),sym(basisContainer[m])); // double energyDensityfG = scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),sym(basisContainer[m])); // double energyDensityfG = scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),quadPos),sym(basisContainer[m])); // double energyDensityfG = scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),element.geometry().global(quadPos)),basisContainer[m]); // double energyDensityfG = scalarProduct(material_.applyElasticityTensor((-1.0)*forceTerm(quadPos),quadPos),basisContainer[m]); // double energyDensityfG = scalarProduct(material_.localElasticityTensor((-1.0)*forceTerm(quadPos),quadPos,element),basisContainer[m]); // double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), (-1.0)*forceTerm(quadPos),basisContainer[m] ); // double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), forceTerm(quadPos),basisContainer[m] ); //TEST // double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), (-1.0)*forceTerm(quadPos),basisContainer[m] ); //TEST // double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), forceTerm(element.geometry().global(quadPos)),basisContainer[m] );//TEST elementRhs[localPhiOffset+m] += energyDensityfG * quadPoint.weight() * integrationElement; // std::cout << "energyDensityfG * quadPoint.weight() * integrationElement: " << energyDensityfG * quadPoint.weight() * integrationElement << std::endl; } } } void assembleCellStiffness(MatrixCT& matrix) { std::cout << "assemble Stiffness-Matrix begins." << std::endl; Dune::MatrixIndexSet occupationPattern; getOccupationPattern(occupationPattern); occupationPattern.exportIdx(matrix); matrix = 0; auto localView = basis_.localView(); const int phiOffset = basis_.dimension(); // A cache for the element stiffness matrices, if desired bool cacheElementMatrices = true; std::map<std::vector<int>, ElementMatrixCT> elementMatrixCache; // auto muGridF = makeGridViewFunction(mu_, basis_.gridView()); // auto muLocal = localFunction(muGridF); // auto lambdaGridF = makeGridViewFunction(lambda_, basis_.gridView()); // auto lambdaLocal = localFunction(lambdaGridF); for (const auto& element : elements(basis_.gridView())) { localView.bind(element); // muLocal.bind(element); // lambdaLocal.bind(element); const auto localPhiOffset = localView.size(); // Dune::Timer Time; //std::cout << "localPhiOffset : " << localPhiOffset << std::endl; // Determine a suitable quadrature rule const auto& localFiniteElement = localView.tree().child(0).finiteElement(); int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); const auto& quadRule = Dune::QuadratureRules<double,dim>::rule(element.type(), orderQR); // Determine the material phase at each quadrature point auto localIndicatorFunction = material_.getLocalIndicatorFunction(); localIndicatorFunction.bind(element); std::vector<int> phaseAtQuadPoint(quadRule.size()); for (std::size_t i=0; i<quadRule.size(); ++i) phaseAtQuadPoint[i] = localIndicatorFunction(quadRule[i].position()); ElementMatrixCT elementMatrix; // We know that all elements of the grid have the same geometry. Therefore, the element stiffness matrices // depend only on the material phases at the quadrature points. In practice, a few particular phase distributions // dominate (identical phase at all quadrature points). This makes caching the element matrices worthwhile. // // In principle the cache implemented here can get arbitrarily large. If that ever becomes a problem // we need to implement a smarter cache. if (cacheElementMatrices) { auto cachedMatrix = elementMatrixCache.find(phaseAtQuadPoint); if (cachedMatrix != elementMatrixCache.end()) { // This copies the matrix. A smarter implementation would avoid this. elementMatrix = (*cachedMatrix).second; } else { computeElementStiffnessMatrix(localView, quadRule, phaseAtQuadPoint, elementMatrix); // This copies the matrix again. elementMatrixCache.insert({phaseAtQuadPoint, elementMatrix}); } } else // No caching { computeElementStiffnessMatrix(localView, quadRule, phaseAtQuadPoint, elementMatrix); } // std::cout << "local assembly time:" << Time.elapsed() << std::endl; //printmatrix(std::cout, elementMatrix, "ElementMatrix", "--"); //std::cout << "elementMatrix.N() : " << elementMatrix.N() << std::endl; //std::cout << "elementMatrix.M() : " << elementMatrix.M() << std::endl; //TEST //Check Element-Stiffness-Symmetry: if(parameterSet_.get<bool>("print_debug", false)) { 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; } } ////////////////////////////////////////////////////////////////////////////// // GLOBAL STIFFNES ASSEMBLY ////////////////////////////////////////////////////////////////////////////// for (size_t i=0; i<localPhiOffset; i++) 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++) { 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++ ) matrix[phiOffset+m][phiOffset+n] += elementMatrix[localPhiOffset+m][localPhiOffset+n]; // printmatrix(std::cout, matrix, "StiffnessMatrix", "--"); } } void assembleCellLoad(VectorCT& b, const Func2Tensor& forceTerm ) { // std::cout << "assemble load vector." << std::endl; b.resize(basis_.size()+3); b = 0; auto localView = basis_.localView(); const int phiOffset = basis_.dimension(); // Transform G_alpha's to GridViewFunctions/LocalFunctions auto loadGVF = Dune::Functions::makeGridViewFunction(forceTerm, basis_.gridView()); auto loadFunctional = localFunction(loadGVF); // auto muGridF = makeGridViewFunction(mu_, basis_.gridView()); // auto muLocal = localFunction(muGridF); // auto lambdaGridF = makeGridViewFunction(lambda_, basis_.gridView()); // auto lambdaLocal = localFunction(lambdaGridF); // int counter = 1; for (const auto& element : elements(basis_.gridView())) { localView.bind(element); // muLocal.bind(element); // lambdaLocal.bind(element); loadFunctional.bind(element); const auto localPhiOffset = localView.size(); // std::cout << "localPhiOffset : " << localPhiOffset << std::endl; VectorCT elementRhs; // std::cout << "----------------------------------Element : " << counter << std::endl; //TEST // counter++; // computeElementLoadVector(localView, muLocal, lambdaLocal, elementRhs, loadFunctional); computeElementLoadVector(localView, elementRhs, loadFunctional); // computeElementLoadVector(localView, muLocal, lambdaLocal, gamma, elementRhs, forceTerm); //TEST // printvector(std::cout, elementRhs, "elementRhs", "--"); // printvector(std::cout, elementRhs, "elementRhs", "--"); ////////////////////////////////////////////////////////////////////////////// // GLOBAL LOAD ASSEMBLY ////////////////////////////////////////////////////////////////////////////// for (size_t p=0; p<localPhiOffset; p++) { auto row = localView.index(p); b[row] += elementRhs[p]; } for (size_t m=0; m<3; m++ ) b[phiOffset+m] += elementRhs[localPhiOffset+m]; //printvector(std::cout, b, "b", "--"); } } // ----------------------------------------------------------------- // --- Functions for global integral mean equals zero constraint auto arbitraryComponentwiseIndices(const int elementNumber, const int leafIdx ) { // (Local Approach -- works for non Lagrangian-Basis too) // Input : elementNumber & localIdx // Output : determine all Component-Indices that correspond to that basis-function auto localView = basis_.localView(); Dune::FieldVector<int,3> row; int elementCounter = 0; for (const auto& element : elements(basis_.gridView())) { if(elementCounter == elementNumber) // get arbitraryIndex(global) for each Component ..alternativ:gridView.indexSet { localView.bind(element); for (int k = 0; k < 3; k++) { auto rowLocal = localView.tree().child(k).localIndex(leafIdx); //Input: LeafIndex! TODO bräuchte hier (Inverse ) Local-to-Leaf Idx Map row[k] = localView.index(rowLocal); // std::cout << "rowLocal:" << rowLocal << std::endl; // std::cout << "row[k]:" << row[k] << std::endl; } } elementCounter++; } return row; } void setOneBaseFunctionToZero() { std::cout << "Setting one Basis-function to zero" << std::endl; // 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) Dune::FieldVector<std::size_t,3> row = arbitraryComponentwiseIndices(arbitraryElementNumber,arbitraryLeafIndex); for (int k = 0; k<dim; k++) { load_alpha1_[row[k]] = 0.0; load_alpha2_[row[k]] = 0.0; load_alpha3_[row[k]] = 0.0; auto cIt = stiffnessMatrix_[row[k]].begin(); auto cEndIt = stiffnessMatrix_[row[k]].end(); for (; cIt!=cEndIt; ++cIt) *cIt = (cIt.index()==row[k]) ? 1.0 : 0.0; } } auto childToIndexMap(const int k) { // Input : child/component // Output : determine all Indices that belong to that component auto localView = basis_.localView(); std::vector<int> r = { }; // for (int n: r) // std::cout << n << ","<< std::endl; // Determine global indizes for each component k = 1,2,3.. in order to subtract correct (component of) integral Mean // (global) Indices that correspond to component k = 1,2,3 for(const auto& element : elements(basis_.gridView())) { localView.bind(element); const auto& localFiniteElement = localView.tree().child(k).finiteElement(); const auto nSf = localFiniteElement.localBasis().size(); for(size_t j=0; j<nSf; j++) { auto Localidx = localView.tree().child(k).localIndex(j); // local indices r.push_back(localView.index(Localidx)); // global indices } } // Delete duplicate elements // first remove consecutive (adjacent) duplicates auto last = std::unique(r.begin(), r.end()); r.erase(last, r.end()); // sort followed by unique, to remove all duplicates std::sort(r.begin(), r.end()); last = std::unique(r.begin(), r.end()); r.erase(last, r.end()); return r; } auto integralMean(VectorCT& coeffVector) { auto GVFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<Dune::FieldVector<double,dim>>(basis_,coeffVector); auto localfun = localFunction(GVFunction); auto localView = basis_.localView(); Dune::FieldVector<double,3> r = {0.0, 0.0, 0.0}; double area = 0.0; // Compute Area integral & integral of FE-function for(const auto& element : elements(basis_.gridView())) { 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); const auto& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), orderQR); for(const auto& quadPoint : quad) { const auto& quadPos = quadPoint.position(); const double integrationElement = element.geometry().integrationElement(quadPos); area += quadPoint.weight() * integrationElement; r += localfun(quadPos) * quadPoint.weight() * integrationElement; } } // std::cout << "Domain-Area: " << area << std::endl; return (1.0/area) * r ; } auto subtractIntegralMean(VectorCT& coeffVector) { // Subtract correct integral mean from each associated component function auto IM = integralMean(coeffVector); for(size_t k=0; k<dim; k++) { //std::cout << "Integral-Mean: " << IM[k] << std::endl; auto idx = childToIndexMap(k); for ( int i : idx) coeffVector[i] -= IM[k]; } } // ----------------------------------------------------------------- // --- Solving the Corrector-problem: 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; } /////////////////////////////////// // --- Choose Solver --- // 1 : CG-Solver // 2 : GMRES // 3 : QR (default) // 4 : UMFPACK /////////////////////////////////// unsigned int Solvertype = parameterSet_.get<unsigned int>("Solvertype", 3); 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_; std::cout << "start corrector solver..." << std::endl; Dune::Timer SolverTimer; if (Solvertype==1) // CG - SOLVER { 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; std::cout << "solve linear system for x_1.\n"; solver.apply(x_1_, load_alpha1_, statistics); std::cout << "solve linear system for x_2.\n"; solver.apply(x_2_, load_alpha2_, statistics); std::cout << "solve linear system for x_3.\n"; solver.apply(x_3_, load_alpha3_, statistics); log_ << "Solver-type used: " <<" CG-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 { 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; 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 { std::cout << "------------ QR - Solver ------------" << std::endl; log_ << "solveLinearSystems: We use QR solver.\n"; //TODO install suitesparse Dune::SPQR<MatrixCT> sPQR(stiffnessMatrix_); sPQR.setVerbosity(1); Dune::InverseOperatorResult statisticsQR; 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; } //////////////////////////////////////////////////////////////////////////////////// else if (Solvertype==4)// UMFPACK - SOLVER { std::cout << "------------ UMFPACK - Solver ------------" << std::endl; log_ << "solveLinearSystems: We use UMFPACK solver.\n"; 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; } std::cout << "--- Corrector computation finished ---" << std::endl; std::cout << "Time required for solving:" << 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 (auto& matrix : mContainer) matrix = 0; 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]); } 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>("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 << "Integral-Mean phi_1 : " << A[i] << std::endl; } } if(substract_integralMean) { std::cout << " --- subtracting integralMean --- " << std::endl; subtractIntegralMean(phi_1_); subtractIntegralMean(phi_2_); subtractIntegralMean(phi_3_); subtractIntegralMean(x_1_); subtractIntegralMean(x_2_); subtractIntegralMean(x_3_); ////////////////////////////////////////// // 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; } } } ///////////////////////////////////////////////////////// // 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 Correctos to VTK: void writeCorrectorsVTK(const int level) { std::string baseName = parameterSet_.get("baseName", "CellProblem-result"); std::string vtkOutputName = parameterSet_.get("outputPath", "../../outputs") + "/" + baseName; std::cout << "vtkOutputName:" << 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 + "-level"+ std::to_string(level)); 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; } void computeL2Norm() { // IMPLEMENTATION with makeDiscreteGlobalBasisFunction double error_1 = 0.0; double error_2 = 0.0; double error_3 = 0.0; auto localView = basis_.localView(); auto GVFunc_1 = Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_); auto GVFunc_2 = Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_); auto GVFunc_3 = Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_); auto localfun_1 = localFunction(GVFunc_1); auto localfun_2 = localFunction(GVFunc_2); auto localfun_3 = localFunction(GVFunc_3); for(const auto& element : elements(basis_.gridView())) { localView.bind(element); localfun_1.bind(element); localfun_2.bind(element); localfun_3.bind(element); 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 = element.geometry().integrationElement(quadPos); error_1 += localfun_1(quadPos)*localfun_1(quadPos) * quadPoint.weight() * integrationElement; error_2 += localfun_2(quadPos)*localfun_2(quadPos) * quadPoint.weight() * integrationElement; error_3 += localfun_3(quadPos)*localfun_3(quadPos) * quadPoint.weight() * integrationElement; } } std::cout << "L2-Norm(Corrector phi_1): " << sqrt(error_1) << std::endl; std::cout << "L2-Norm(Corrector phi_2): " << sqrt(error_2) << std::endl; std::cout << "L2-Norm(Corrector phi_3): " << sqrt(error_3) << std::endl; return; } void computeL2SymGrad() { double error_1 = 0.0; double error_2 = 0.0; double error_3 = 0.0; auto localView = basis_.localView(); auto GVFunc_1 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_)); auto GVFunc_2 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_)); auto GVFunc_3 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_)); auto localfun_1 = localFunction(GVFunc_1); auto localfun_2 = localFunction(GVFunc_2); auto localfun_3 = localFunction(GVFunc_3); for (const auto& element : elements(basis_.gridView())) { localView.bind(element); localfun_1.bind(element); localfun_2.bind(element); localfun_3.bind(element); 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 auto integrationElement = geometry.integrationElement(quadPos); auto scaledSymGrad1 = sym(crossSectionDirectionScaling(1.0/gamma_, localfun_1(quadPos))); auto scaledSymGrad2 = sym(crossSectionDirectionScaling(1.0/gamma_, localfun_2(quadPos))); auto scaledSymGrad3 = sym(crossSectionDirectionScaling(1.0/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; } } std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_1): " << sqrt(error_1) << std::endl; std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_2): " << sqrt(error_2) << std::endl; std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_3): " << sqrt(error_3) << std::endl; return; } // ----------------------------------------------------------------- // --- Check Orthogonality relation Paper (75) auto check_Orthogonality() { Dune::Timer orthogonalityTimer; std::cout << "Check Orthogonality..." << std::endl; auto localView = basis_.localView(); auto GVFunc_1 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_)); auto GVFunc_2 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_)); auto GVFunc_3 = derivative(Dune::Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_)); auto localfun_1 = localFunction(GVFunc_1); auto localfun_2 = localFunction(GVFunc_2); auto localfun_3 = localFunction(GVFunc_3); const std::array<decltype(localfun_1)*,3> phiDerContainer = {&localfun_1 , &localfun_2 , &localfun_3 }; auto localIndicatorFunction = material_.getLocalIndicatorFunction(); // auto muGridF = makeGridViewFunction(mu_, basis_.gridView()); // auto mu = localFunction(muGridF); // auto lambdaGridF = makeGridViewFunction(lambda_, basis_.gridView()); // auto lambda= localFunction(lambdaGridF); for(int a=0; a<3; a++) 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 matrixFieldBGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView()); // auto matrixFieldB = localFunction(matrixFieldBGVF); // using GridView = typename Basis::GridView; // using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate; // using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>; // std::cout << "Press key.." << std::endl; // std::cin.get(); // TEST // FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0}; // printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--"); for (const auto& e : elements(basis_.gridView())) { localView.bind(e); matrixFieldG.bind(e); DerPhi1.bind(e); DerPhi2.bind(e); // mu.bind(e); // lambda.bind(e); localIndicatorFunction.bind(e); double elementEnergy = 0.0; //double elementEnergy_HP = 0.0; auto geometry = e.geometry(); const auto& localFiniteElement = localView.tree().child(0).finiteElement(); int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1); // int orderQR = 0; // int orderQR = 1; // int orderQR = 2; // int orderQR = 3; 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 Chi = sym(crossSectionDirectionScaling(1.0/gamma_, DerPhi2(quadPos))) + mContainer[b]; const auto strain1 = symVoigt(crossSectionDirectionScaling(1.0/gamma_, DerPhi1(quadPos))); auto G = matrixFieldG(quadPos); // auto G = matrixFieldG(e.geometry().global(quadPos)); //TEST auto tmp = matrixToVoigt(G + mContainer[a]) + strain1; double energyDensity= voigtScalarProduct(material_.applyElasticityTensor(tmp,localIndicatorFunction(quadPos)),symVoigt(Chi)); // double energyDensity= scalarProduct(material_.ElasticityTensor(tmp,localIndicatorFunction(quadPos)),sym(Chi)); // double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), tmp, Chi); elementEnergy += energyDensity * quadPoint.weight() * integrationElement; // elementEnergy += strain1 * quadPoint.weight() * integrationElement; //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement; } energy += elementEnergy; //higherPrecEnergy += elementEnergy_HP; } 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; } std::cout << "Time required for orthogonality check: " << orthogonalityTimer.elapsed() << std::endl; return 0; } // --- Check whether stiffness matrix is symmetric void checkSymmetry() { std::cout << " Check Symmetry of stiffness matrix..." << std::endl; auto localView = basis_.localView(); for (const auto& element : elements(basis_.gridView())) { localView.bind(element); const auto localPhiOffset = localView.size(); for(size_t i=0; i<localPhiOffset; i++) 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; } for(size_t i=0; i<localPhiOffset; i++) 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; } for(size_t m=0; m<3; m++ ) 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 << "--- Symmetry test passed ---" << std::endl; } }; // end class #endif