Skip to content
Snippets Groups Projects
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