Forked from
Klaus Böhnlein / dune-microstructure
474 commits behind, 88 commits ahead of the upstream repository.
-
Klaus Böhnlein authoredKlaus Böhnlein authored
matrix_operations.hh 7.32 KiB
#ifndef DUNE_MICROSTRUCTURE_MATRIXOPERATIONS_HH
#define DUNE_MICROSTRUCTURE_MATRIXOPERATIONS_HH
namespace MatrixOperations {
using namespace Dune;
using MatrixRT = FieldMatrix< double, 3, 3>;
using VectorRT = FieldVector< double, 3>;
using std::sin;
using std::cos;
static MatrixRT Id (){
MatrixRT Id(0);
for (int i=0;i<3;i++)
Id[i][i]=1.0;
return Id;
}
static double norm(VectorRT v){
return sqrt(pow(v[0],2) + pow(v[1],2) + pow(v[2],2));
}
static double norm(MatrixRT M){
return sqrt(
pow(M[0][0],2) + pow(M[0][1],2) + pow(M[0][2],2)
+ pow(M[1][0],2) + pow(M[1][1],2) + pow(M[1][2],2)
+ pow(M[2][0],2) + pow(M[2][1],2) + pow(M[2][2],2));
}
static MatrixRT sym (MatrixRT M) { // 1/2 (M^T + M)
MatrixRT ret(0);
for (int i = 0; i< 3; i++)
for (int j = 0; j< 3; j++)
ret[i][j] = 0.5 * (M[i][j] + M[j][i]);
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], w*M[1], w*M[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;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
sum += M1[i][j] * M2[i][j];
return sum;
}
// static double linearizedStVenantKirchhoffDensity(double mu, double lambda, MatrixRT E1, MatrixRT E2){ // ?? Check with Robert
// E1= sym(E1);
// E2 = sym(E2);
// double t1 = scalarProduct(E1,E2);
// t1 *= 2* mu;
// double t2 = trace(E1)*trace(E2);
// t2 *= lambda;
// return t1 + t2;
// }
static double linearizedStVenantKirchhoffDensity(double mu, double lambda, MatrixRT E1, MatrixRT E2) // CHANGED
{
auto t1 = 2.0 * mu * sym(E1) + lambda * trace(sym(E1)) * Id();
return scalarProduct(t1,E2);
}
// --- Generalization: Define Quadratic QuadraticForm
static double QuadraticForm(const double mu, const double lambda, const MatrixRT M){
auto tmp1 = sym(M);
double tmp2 = norm(tmp1);
return lambda*std::pow(trace(M),2) + 2*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;
}
/*
template<double phi>
static bool isInRotatedPlane(double x1, double x2){
return cos(phi)*x1 + sin(phi)*x2 > 0;
}*/
}
// OPTIONAL H1-Seminorm ...
/*
template<class VectorCT>
double semi_H1_vectorScalarProduct(VectorCT& coeffVector1, VectorCT& coeffVector2)
{
double ret(0);
auto localView = basis_.localView();
for (const auto& e : elements(basis_.gridView()))
{
localView.bind(e);
auto geometry = e.geometry();
const auto& localFiniteElement = localView.tree().child(0).finiteElement();
const auto nSf = localFiniteElement.localBasis().size();
int order = 2*(dim*localFiniteElement.localBasis().order()-1);
const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), order);
for (const auto& quadPoint : quad)
{
double elementScp(0);
auto pos = quadPoint.position();
const auto jacobian = geometry.jacobianInverseTransposed(pos);
const double integrationElement = geometry.integrationElement(pos);
std::vector<FieldMatrix<double,1,dim> > referenceGradients;
localFiniteElement.localBasis().evaluateJacobian(pos, referenceGradients);
std::vector< VectorRT > gradients(referenceGradients.size());
for (size_t i=0; i< gradients.size(); i++)
jacobian.mv(referenceGradients[i][0], gradients[i]);
for (size_t i=0; i < nSf; i++)
for (size_t j=0; j < nSf; j++)
for (size_t k=0; k < dimworld; k++)
for (size_t l=0; l < dimworld; l++)
{
MatrixRT defGradient1(0);
defGradient1[k] = gradients[i];
MatrixRT defGradient2(0);
defGradient2[l] = gradients[j];
size_t localIdx1 = localView.tree().child(k).localIndex(i);
size_t globalIdx1 = localView.index(localIdx1);
size_t localIdx2 = localView.tree().child(l).localIndex(j);
size_t globalIdx2 = localView.index(localIdx2);
double scp(0);
for (int ii=0; ii<dimworld; ii++)
for (int jj=0; jj<dimworld; jj++)
scp += coeffVector1[globalIdx1] * defGradient1[ii][jj] * coeffVector2[globalIdx2] * defGradient2[ii][jj];
elementScp += scp;
}
ret += elementScp * quadPoint.weight() * integrationElement;
} //qp
} //e
return ret;
}*/
/*
class BiotStrainApprox
{
// E_h = h^{-1} (R^T F_h - Id)
//
//E_h = (U + K e_cs, 0, 0)
//
Func2Tensor E_a = [] (const Domain& z) //extra Klasse
{
return biotStrainApprox({1, 0, 0}, {0, 0, 0}, {0, z[1], z[2]}); //MatrixRT{{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
};
// twist in x2-x3 plane E_K1 = sym (e1 x (0,x2,x3)^T ot e1)
Func2Tensor E_K1 = [] (const Domain& z)
{
return biotStrainApprox({0, 0, 0}, {1, 0, 0}, {0, z[1], z[2]}); //MatrixRT{{0.0,-0.5*z[2], 0.5*z[1]}, {-0.5*z[2], 0.0 , 0.0 }, {0.5*z[1],0.0,0.0}};
};
// bend strain in x1-x2 plane E_K2 = sym (e2 x (0,x2,x3)^T ot e1)
Func2Tensor E_K2 = [] (const Domain& z)
{
return biotStrainApprox({0, 0, 0}, {0, 1, 0}, {0, z[1], z[2]}); //MatrixRT{{z[2], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0}};
};
// bend strain in x1-x3 plane E_K3 = sym (e3 x (0,x2,x3)^T ot e1)
Func2Tensor E_K3 = [] (const Domain& z)
{
return biotStrainApprox({0, 0, 0}, {0, 0, 1}, {0, z[1], z[2]}); //MatrixRT{{-z[1], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
};
};
*/
#endif