Forked from
Klaus Böhnlein / dune-microstructure
474 commits behind, 248 commits ahead of the upstream repository.
-
Klaus Böhnlein authoredKlaus Böhnlein authored
EffectiveQuantitiesComputer.hh 19.29 KiB
#ifndef DUNE_MICROSTRUCTURE_EFFECTIVEQUANTITIESCOMPUTER_HH
#define DUNE_MICROSTRUCTURE_EFFECTIVEQUANTITIESCOMPUTER_HH
#include <filesystem>
#include <dune/microstructure/matrix_operations.hh>
#include <dune/microstructure/CorrectorComputer.hh>
#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number
#include <dune/istl/io.hh>
#include <dune/istl/matrix.hh>
#include <dune/common/parametertree.hh>
using namespace Dune;
using namespace MatrixOperations;
using std::shared_ptr;
using std::make_shared;
using std::string;
using std::cout;
using std::endl;
// template <class Basis>
// class EffectiveQuantitiesComputer : public CorrectorComputer<Basis,Material> {
template <class Basis, class Material>
class EffectiveQuantitiesComputer {
public:
static const int dimworld = 3;
// static const int nCells = 4;
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 HierarchicVectorView = typename CorrectorComputer<Basis,Material>::HierarchicVectorView;
protected:
CorrectorComputer<Basis,Material>& correctorComputer_;
Func2Tensor prestrain_;
const Material& material_;
public:
VectorCT B_load_TorusCV_; //<B, Chi>_L2
// FieldMatrix<double, dim, dim> Q_; //effective moduli <LF_i, F_j>_L2
// FieldVector<double, dim> Bhat_; //effective loads induced by prestrain <LF_i, B>_L2
// FieldVector<double, dim> Beff_; //effective strains Mb = ak
MatrixRT Q_; //effective moduli <LF_i, F_j>_L2
VectorRT Bhat_; //effective loads induced by prestrain <LF_i, B>_L2
VectorRT Beff_; //effective strains Mb = ak
// corrector parts
VectorCT phi_E_TorusCV_; //phi_i * (a,K)_i
VectorCT phi_perp_TorusCV_;
VectorCT phi_TorusCV_;
VectorCT phi_1_; //phi_i * (a,K)_i
VectorCT phi_2_;
VectorCT phi_3_;
// is this really interesting???
// double phi_E_L2norm_;
// double phi_E_H1seminorm_;
// double phi_perp_L2norm_;
// double phi_perp_H1seminorm_;
// double phi_L2norm_;
// double phi_H1seminorm_;
// double Chi_E_L2norm_;
// double Chi_perp_L2norm_;
// double Chi_L2norm_;
double B_energy_; // < B, B >_L B = F + Chi_perp + B_perp
double F_energy_; // < F, F >_L
double Chi_perp_energy_; // < Chi_perp, Chi_perp >_L
double B_perp_energy_; // < B_perp, B_perp >_L
//Chi(phi) is only implicit computed, can we store this?
///////////////////////////////
// constructor
///////////////////////////////
// EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer, Func2Tensor prestrain)
// : correctorComputer_(correctorComputer), prestrain_(prestrain)
EffectiveQuantitiesComputer(CorrectorComputer<Basis,Material>& correctorComputer,
Func2Tensor prestrain,
const Material& material)
: correctorComputer_(correctorComputer),
prestrain_(prestrain),
material_(material)
{
// computePrestressLoadCV();
// computeEffectiveStrains();
// Q_ = 0;
// Q_ = {{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}};
// compute_phi_E_TorusCV();
// compute_phi_perp_TorusCV();
// compute_phi_TorusCV();
// computeCorrectorNorms();
// computeChiNorms();
// computeEnergiesPrestainParts();
// writeInLogfile();
}
///////////////////////////////
// getter
///////////////////////////////
CorrectorComputer<Basis,Material> getCorrectorComputer(){return correctorComputer_;}
const shared_ptr<Basis> getBasis()
{
return correctorComputer_.getBasis();
}
auto getQeff(){return Q_;}
auto getBeff(){return Beff_;}
// -----------------------------------------------------------------
// --- Compute Effective Quantities
void computeEffectiveQuantities()
{
// Get everything.. better TODO: with Inheritance?
// auto test = correctorComputer_.getLoad_alpha1();
// auto phiContainer = correctorComputer_.getPhicontainer();
auto MContainer = correctorComputer_.getMcontainer();
auto MatrixBasisContainer = correctorComputer_.getMatrixBasiscontainer();
auto x3MatrixBasisContainer = correctorComputer_.getx3MatrixBasiscontainer();
auto mu_ = *correctorComputer_.getMu();
auto lambda_ = *correctorComputer_.getLambda();
auto gamma = correctorComputer_.getGamma();
auto basis = *correctorComputer_.getBasis();
ParameterTree parameterSet = correctorComputer_.getParameterSet();
shared_ptr<VectorCT> phiBasis[3] = {correctorComputer_.getCorr_phi1(),
correctorComputer_.getCorr_phi2(),
correctorComputer_.getCorr_phi3()
};
auto prestrainGVF = Dune::Functions::makeGridViewFunction(prestrain_, basis.gridView());
auto prestrainFunctional = localFunction(prestrainGVF);
Q_ = 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();
// auto GVFunc_a = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiContainer[a]));
auto GVFunc_a = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiBasis[a]));
// auto GVFunc_b = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,phiContainer[b]));
auto localfun_a = localFunction(GVFunc_a);
// auto localfun_b = localFunction(GVFunc_b);
///////////////////////////////////////////////////////////////////////////////
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);
auto muGridF = Dune::Functions::makeGridViewFunction(mu_, basis.gridView());
auto mu = localFunction(muGridF);
auto lambdaGridF = Dune::Functions::makeGridViewFunction(lambda_, basis.gridView());
auto lambda= localFunction(lambdaGridF);
// using GridView = typename Basis::GridView;
for (const auto& e : elements(basis.gridView()))
{
localView.bind(e);
matrixFieldG1.bind(e);
matrixFieldG2.bind(e);
localfun_a.bind(e);
// DerPhi2.bind(e);
mu.bind(e);
lambda.bind(e);
prestrainFunctional.bind(e);
double elementEnergy = 0.0;
double elementPrestrain = 0.0;
auto geometry = e.geometry();
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);
// int orderQR = 0;
// int orderQR = 1;
// int orderQR = 2;
// int orderQR = 3;
const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.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 G1 = matrixFieldG1(e.geometry().global(quadPos)); //TEST
// auto G2 = matrixFieldG2(e.geometry().global(quadPos)); //TEST
auto X1 = G1 + Chi1;
// auto X2 = G2 + Chi2;
double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), X1, G2);
elementEnergy += energyDensity * quadPoint.weight() * integrationElement; // quad[quadPoint].weight() ???
if (b==0)
{
elementPrestrain += linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), X1, prestrainFunctional(quadPos)) * quadPoint.weight() * integrationElement;
}
}
energy += elementEnergy;
prestrain += elementPrestrain;
}
Q_[a][b] = energy;
if (b==0)
Bhat_[a] = prestrain;
}
if(parameterSet.get<bool>("print_debug", false))
{
printmatrix(std::cout, Q_, "Matrix Q_", "--");
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(Q_,true,2,1);
// std::cout << "----------------------------------------" << std::endl;
Q_.solve(Beff_,Bhat_);
if(parameterSet.get<bool>("print_debug", false))
printvector(std::cout, Beff_, "Beff_", "--");
//LOG-Output
auto& log = *(correctorComputer_.getLog());
log << "--- Prestrain Output --- " << std::endl;
log << "Bhat_: " << Bhat_ << std::endl;
log << "Beff_: " << Beff_ << " (Effective Prestrain)" << std::endl;
log << "------------------------ " << std::endl;
// TEST
// std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
return ;
}
// -----------------------------------------------------------------
// --- write Data to Matlab / Optimization-Code
void writeToMatlab(std::string outputPath)
{
std::cout << "write effective quantities to Matlab folder..." << std::endl;
//writeMatrixToMatlab(Q, "../../Matlab-Programs/QMatrix.txt");
writeMatrixToMatlab(Q_, outputPath + "/QMatrix.txt");
// write effective Prestrain in Matrix for Output
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 matrixFieldAGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView());
auto matrixFieldA = localFunction(matrixFieldAGVF);
auto matrixFieldBGVF = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
auto matrixFieldB = localFunction(matrixFieldBGVF);
auto muGridF = Dune::Functions::makeGridViewFunction(mu_, basis.gridView());
auto mu = localFunction(muGridF);
auto lambdaGridF = Dune::Functions::makeGridViewFunction(lambda_, basis.gridView());
auto lambda= localFunction(lambdaGridF);
for (const auto& e : elements(basis.gridView()))
{
localView.bind(e);
matrixFieldA.bind(e);
matrixFieldB.bind(e);
mu.bind(e);
lambda.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 QuadratureRule<double, dim>& quad = 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 = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), matrixFieldA(quadPos), matrixFieldB(quadPos));
elementEnergy += energyDensity * quadPoint.weight() * integrationElement;
}
energy += elementEnergy;
}
return energy;
}
// --- Alternative that does not use orthogonality relation (75) in the paper
// void computeFullQ()
// {
// auto MContainer = correctorComputer_.getMcontainer();
// auto MatrixBasisContainer = correctorComputer_.getMatrixBasiscontainer();
// auto x3MatrixBasisContainer = correctorComputer_.getx3MatrixBasiscontainer();
// auto mu_ = *correctorComputer_.getMu();
// auto lambda_ = *correctorComputer_.getLambda();
// auto gamma = correctorComputer_.getGamma();
// auto basis = *correctorComputer_.getBasis();
// shared_ptr<VectorCT> phiBasis[3] = {correctorComputer_.getCorr_phi1(),
// correctorComputer_.getCorr_phi2(),
// correctorComputer_.getCorr_phi3()
// };
// auto prestrainGVF = Dune::Functions::makeGridViewFunction(prestrain_, basis.gridView());
// auto prestrainFunctional = localFunction(prestrainGVF);
// Q_ = 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();
// // auto GVFunc_a = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiContainer[a]));
// auto GVFunc_a = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiBasis[a]));
// auto GVFunc_b = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis,*phiBasis[b]));
// auto localfun_a = localFunction(GVFunc_a);
// auto localfun_b = localFunction(GVFunc_b);
// ///////////////////////////////////////////////////////////////////////////////
// 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);
// auto muGridF = Dune::Functions::makeGridViewFunction(mu_, basis.gridView());
// auto mu = localFunction(muGridF);
// auto lambdaGridF = Dune::Functions::makeGridViewFunction(lambda_, basis.gridView());
// auto lambda= localFunction(lambdaGridF);
// // using GridView = typename Basis::GridView;
// for (const auto& e : elements(basis.gridView()))
// {
// localView.bind(e);
// matrixFieldG1.bind(e);
// matrixFieldG2.bind(e);
// localfun_a.bind(e);
// localfun_b.bind(e);
// mu.bind(e);
// lambda.bind(e);
// prestrainFunctional.bind(e);
// double elementEnergy = 0.0;
// double elementPrestrain = 0.0;
// auto geometry = e.geometry();
// 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);
// // int orderQR = 0;
// // int orderQR = 1;
// // int orderQR = 2;
// // int orderQR = 3;
// const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.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] + matrixFieldG1(quadPos);
// auto Chi2 = sym(crossSectionDirectionScaling(1.0/gamma, localfun_b(quadPos))) + *MContainer[b] + matrixFieldG2(quadPos);
// // auto G1 = matrixFieldG1(quadPos);
// // auto G2 = matrixFieldG2(quadPos);
// // auto G1 = matrixFieldG1(e.geometry().global(quadPos)); //TEST
// // auto G2 = matrixFieldG2(e.geometry().global(quadPos)); //TEST
// // auto X1 = G1 + Chi1;
// // auto X2 = G2 + Chi2;
// double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), Chi1, Chi2);
// elementEnergy += energyDensity * quadPoint.weight() * integrationElement; // quad[quadPoint].weight() ???
// }
// energy += elementEnergy;
// prestrain += elementPrestrain;
// }
// Q_[a][b] = energy;
// if (b==0)
// Bhat_[a] = prestrain;
// }
// printmatrix(std::cout, Q_, "Matrix Q_", "--");
// 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(Q_,true,2,1);
// // std::cout << "----------------------------------------" << std::endl;
// Q_.solve(Beff_,Bhat_);
// printvector(std::cout, Beff_, "Beff_", "--");
// //LOG-Output
// auto& log = *(correctorComputer_.getLog());
// log << "--- Prestrain Output --- " << std::endl;
// log << "Bhat_: " << Bhat_ << std::endl;
// log << "Beff_: " << Beff_ << " (Effective Prestrain)" << std::endl;
// log << "------------------------ " << std::endl;
// return ;
// }
}; // end class
#endif