diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt index b936f23343264acdb8672d0fb083da46fea26e89..467bfbb270a2866a0014bf08b96ee3757a098291 100644 --- a/Solver/CMakeLists.txt +++ b/Solver/CMakeLists.txt @@ -19,6 +19,8 @@ set(SRC functionSpace.cpp filters.cpp sparsityPattern.cpp + STensor43.cpp + terms.cpp ) file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h) diff --git a/Solver/STensor43.cpp b/Solver/STensor43.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb46e4ebc1bd4ed8533c438565cd3eb14083a48b --- /dev/null +++ b/Solver/STensor43.cpp @@ -0,0 +1,11 @@ + +#include "STensor43.h" + +void STensor43::print (const char *s) const +{ + printf("STensor43::print to be implemented \n"); +/* printf(" tensor4 %s : \n %12.5E %12.5E %12.5E \n %12.5E %12.5E %12.5E \n %12.5E %12.5E %12.5E \n",s, + (*this)(0,0),(*this)(0,1),(*this)(0,2), + (*this)(1,0),(*this)(1,1),(*this)(1,2), + (*this)(2,0),(*this)(2,1),(*this)(2,2));*/ +} diff --git a/Solver/STensor43.h b/Solver/STensor43.h new file mode 100644 index 0000000000000000000000000000000000000000..dd461ed8b671c0dd35a60d9a2e1bb32abfb3e907 --- /dev/null +++ b/Solver/STensor43.h @@ -0,0 +1,130 @@ +#ifndef _STENSOR43_H_ +#define _STENSOR43_H_ + +#include "STensor3.h" +#include "fullMatrix.h" +#include "Numeric.h" + + +// concrete class for general 3x3 matrix + +class STensor43 { + protected: + // 0000 0001 0002 0010 ... 2211 2212 2220 2221 2222 + double _val[81]; + public: + inline int getIndex(int i, int j, int k, int l) const + { + static int _index[3][3][3][3] = {{{{0,1,2},{3,4,5},{6,7,8}},{{9,10,11},{12,13,14},{15,16,17}},{{18,19,20},{21,22,23},{24,25,26}}}, + {{{27,28,29},{30,31,32},{33,34,35}},{{36,37,38},{39,40,41},{42,43,44}},{{45,46,47},{48,49,50},{51,52,53}}}, + {{{54,55,56},{57,58,59},{60,61,62}},{{63,64,65},{66,67,68},{69,70,71}},{{72,73,74},{75,76,77},{77,79,80}}}}; + return _index[i][j][k][l]; + } + STensor43(const STensor43& other) + { + for (int i = 0; i < 81; i++) _val[i] = other._val[i]; + } + // default constructor, null tensor + STensor43(const double v = 0.0) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + if ((i==k)&&(j==l)) + _val[getIndex(i, j, k, l)]=v; + else + _val[getIndex(i, j, k, l)]=0.0; + } + inline double &operator()(int i, int j,int k, int l) + { + return _val[getIndex(i, j, k, l)]; + } + inline double operator()(int i, int j, int k, int l) const + { + return _val[getIndex(i, j, k ,l)]; + } + STensor43 operator + (const STensor43 &other) const + { + STensor43 res(*this); + for (int i = 0; i < 81; i++) res._val[i] += other._val[i]; + return res; + } + STensor43& operator += (const STensor43 &other) + { + for (int i = 0; i < 81; i++) _val[i] += other._val[i]; + return *this; + } + STensor43& operator *= (const double &other) + { + for (int i = 0; i < 81; i++) _val[i] *= other; + return *this; + } +/* STensor43& operator *= (const STensor43 &other) + { +// to be implemented + return *this; + }*/ + void print(const char *) const; +}; + +// tensor product +inline void tensprod(const STensor3 &a, const STensor3 &b, STensor43 &c) +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + c(i,j,k,l)=a(i,j)*b(k,l); +} + +inline double dot(const STensor43 &a, const STensor43 &b) +{ + double prod=0; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + prod+=a(i,j,k,l)*b(i,j,k,l); + return prod; +} + +inline STensor43 operator*(const STensor43 &t, double m) +{ + STensor43 val(t); + val *= m; + return val; +} + +inline STensor43 operator*(double m,const STensor43 &t) +{ + STensor43 val(t); + val *= m; + return val; +} + +inline STensor3 operator*(const STensor43 &t, const STensor3 &m) +{ + STensor3 val(0.); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + val(i,j)+=t(i,j,k,l)*m(k,l); + return val; +} + +inline STensor3 operator*( const STensor3 &m , const STensor43 &t) +{ + STensor3 val(0.); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + val(k,l)+=t(i,j,k,l)*m(i,j); + return val; +} + + + +#endif diff --git a/Solver/elasticitySolver.cpp b/Solver/elasticitySolver.cpp index 31cbea5fe5956271037b87a6fa97f74a408afc24..1fdd6715bd3d0bdb4e7673acecac62737a246e80 100644 --- a/Solver/elasticitySolver.cpp +++ b/Solver/elasticitySolver.cpp @@ -92,7 +92,7 @@ void elasticitySolver::solve() { SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); + BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); Assemble(Elastic_Energy_Term,elasticFields[i].g->begin(),elasticFields[i].g->end(),Integ_Bulk,energ); } printf("elastic energy=%f\n",energ); @@ -107,7 +107,7 @@ void elasticitySolver::postSolve() { SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); + BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); Assemble(Elastic_Energy_Term,elasticFields[i].g->begin(),elasticFields[i].g->end(),Integ_Bulk,energ); } printf("elastic energy=%f\n",energ); @@ -551,7 +551,7 @@ PView* elasticitySolver::buildStressesView (const std::string postFileName) double nu = elasticFields[i]._nu; SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); + BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) { MElement *e=*it; @@ -644,8 +644,8 @@ PView *elasticitySolver::buildElasticEnergyView(const std::string postFileName) if(elasticFields[i]._E == 0.) continue; SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); - ScalarTermConstant One(1.0); + BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); + ScalarTermConstant<double> One(1.0); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) { MElement *e = *it; @@ -673,7 +673,7 @@ PView *elasticitySolver::buildVonMisesView(const std::string postFileName) { SolverField<SVector3> Field(pAssembler, LagSpace); IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu); - BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm); + BilinearTermToScalarTerm Elastic_Energy_Term(Eterm); for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it) { MElement *e=*it; diff --git a/Solver/functionSpace.h b/Solver/functionSpace.h index ec0da235b6a2e8d73a8dde19cb4859ed06dc51d0..68c30abedfc9b98895e79734d27dcd176b485641 100644 --- a/Solver/functionSpace.h +++ b/Solver/functionSpace.h @@ -3,6 +3,7 @@ #include "SVector3.h" #include "STensor3.h" +#include "STensor43.h" #include <vector> #include <iterator> #include <iostream> @@ -16,8 +17,8 @@ template<class T> struct TensorialTraits { typedef T ValType; typedef T GradType[3]; -/* typedef T HessType[3][3]; - typedef SVoid DivType; + typedef T HessType[3][3]; +/* typedef SVoid DivType; typedef SVoid CurlType;*/ }; @@ -26,6 +27,7 @@ template<> struct TensorialTraits<double> typedef double ValType; typedef SVector3 GradType; typedef STensor3 HessType; + typedef double TensProdType; /* typedef SVoid DivType; typedef SVoid CurlType;*/ }; @@ -35,10 +37,23 @@ template<> struct TensorialTraits<SVector3> typedef SVector3 ValType; typedef STensor3 GradType; typedef STensor3 HessType; - typedef double DivType; - typedef SVector3 CurlType; + typedef STensor3 TensProdType; +// typedef double DivType; +// typedef SVector3 CurlType; }; +template<> struct TensorialTraits<STensor3> +{ + typedef STensor3 ValType; +// typedef STensor3 GradType; +// typedef STensor3 HessType; +// typedef STensor3 TensProdType; + typedef STensor43 TensProdType; +// typedef double DivType; +// typedef SVector3 CurlType; +}; + + class FunctionSpaceBase { public: diff --git a/Solver/solverAlgorithms.h b/Solver/solverAlgorithms.h index 3b3f7bbfac21dc4eebd1968addfd32fd441df2a2..2126746254711822d93536f31cc7ce80e22edaac 100644 --- a/Solver/solverAlgorithms.h +++ b/Solver/solverAlgorithms.h @@ -97,7 +97,7 @@ template<class Iterator, class Assembler> void Assemble(BilinearTermBase &term, -template<class Iterator, class Assembler> void Assemble(LinearTermBase &term, FunctionSpaceBase &space, +template<class Iterator, class Assembler> void Assemble(LinearTermBase<double> &term, FunctionSpaceBase &space, Iterator itbegin, Iterator itend, QuadratureBase &integrator, Assembler &assembler) { @@ -114,7 +114,7 @@ template<class Iterator, class Assembler> void Assemble(LinearTermBase &term, Fu } } -template<class Assembler> void Assemble(LinearTermBase &term, FunctionSpaceBase &space, MElement *e, +template<class Assembler> void Assemble(LinearTermBase<double> &term, FunctionSpaceBase &space, MElement *e, QuadratureBase &integrator, Assembler &assembler) { fullVector<typename Assembler::dataMat> localVector; @@ -126,7 +126,7 @@ template<class Assembler> void Assemble(LinearTermBase &term, FunctionSpaceBase assembler.assemble(R, localVector); } -template<class Iterator, class dataMat> void Assemble(ScalarTermBase &term, +template<class Iterator, class dataMat> void Assemble(ScalarTermBase<double> &term, Iterator itbegin, Iterator itend, QuadratureBase &integrator, dataMat & val) { @@ -140,7 +140,7 @@ template<class Iterator, class dataMat> void Assemble(ScalarTermBase &term, } } -template<class Iterator, class dataMat> void Assemble(ScalarTermBase &term, MElement *e, +template<class Iterator, class dataMat> void Assemble(ScalarTermBase<double> &term, MElement *e, QuadratureBase &integrator, dataMat & val) { dataMat localval; diff --git a/Solver/terms.cpp b/Solver/terms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08622668b3dcae207854fbb68607b07358c31ce3 --- /dev/null +++ b/Solver/terms.cpp @@ -0,0 +1,198 @@ +// +// C++ Implementation: terms +// +// Description: +// +// +// Author: <Eric Bechet>, (C) 2011 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "terms.h" + + +void BilinearTermToScalarTerm::get(MElement *ele, int npts, IntPt *GP, double &val) const +{ + fullMatrix<double> localMatrix; + bilterm.get(ele, npts, GP, localMatrix); + val = localMatrix(0, 0); +} + +void BilinearTermBase::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + std::vector<fullMatrix<double> > mv(npts); + get(ele,npts,GP,mv); + m.resize(mv[0].size1(), mv[0].size2()); + m.setAll(0.); + double jac[3][3]; + for (int k=0;k<npts;k++) + { + const double u = GP[k].pt[0]; const double v = GP[k].pt[1]; const double w = GP[k].pt[2]; + const double weight = GP[k].weight; const double detJ = ele->getJacobian(u, v, w, jac); + const double coeff=weight*detJ; + for (int i=0;i<mv[k].size1();++i) + for (int j=0;j<mv[k].size2();++j) + m(i,j)+=mv[k](i,j)*coeff; + } +} + +IsotropicElasticTerm::IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<SVector3>& space2_, double E_, double nu_) : + BilinearTerm<SVector3, SVector3>(space1_, space2_), E(E_), nu(nu_), H(6, 6) +{ + double FACT = E / (1 + nu); + double C11 = FACT * (1 - nu) / (1 - 2 * nu); + double C12 = FACT * nu / (1 - 2 * nu); + double C44 = (C11 - C12) / 2; + H.scale(0.); + for(int i = 0; i < 3; ++i) { H(i, i) = C11; H(i + 3, i + 3) = C44; } + H(1, 0) = H(0, 1) = H(2, 0) = H(0, 2) = H(1, 2) = H(2, 1) = C12; + sym = (&space1_ == &space2_); +} +IsotropicElasticTerm::IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, double E_, double nu_) : + BilinearTerm<SVector3, SVector3>(space1_, space1_), E(E_), nu(nu_), H(6, 6) +{ + double FACT = E / (1 + nu); + double C11 = FACT * (1 - nu) / (1 - 2 * nu); + double C12 = FACT * nu / (1 - 2 * nu); + double C44 = (C11 - C12) / 2; +/* FACT = E / (1 - nu * nu); // plane stress (plates) + C11 = FACT; + C12 = nu * FACT; + C44 = (1. - nu) * .5 * FACT;*/ + H.scale(0.); + for(int i = 0; i < 3; ++i) { H(i, i) = C11; H(i + 3, i + 3) = C44; } + H(1, 0) = H(0, 1) = H(2, 0) = H(0, 2) = H(1, 2) = H(2, 1) = C12; + sym = true; +} + +void IsotropicElasticTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + if(ele->getParent()) ele = ele->getParent(); + if(sym) + { + int nbFF = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); + double jac[3][3]; + fullMatrix<double> B(6, nbFF); + fullMatrix<double> BTH(nbFF, 6); + fullMatrix<double> BT(nbFF, 6); + m.resize(nbFF, nbFF); + m.setAll(0.); + //std::cout << m.size1() << " " << m.size2() << std::endl; + for(int i = 0; i < npts; i++) + { + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<TensorialTraits<SVector3>::GradType> Grads; + BilinearTerm<SVector3, SVector3>::space1.gradf(ele, u, v, w, Grads); // a optimiser ?? + for(int j = 0; j < nbFF; j++) + { + BT(j, 0) = B(0, j) = Grads[j](0, 0); + BT(j, 1) = B(1, j) = Grads[j](1, 1); + BT(j, 2) = B(2, j) = Grads[j](2, 2); + BT(j, 3) = B(3, j) = Grads[j](0, 1) + Grads[j](1, 0); + BT(j, 4) = B(4, j) = Grads[j](1, 2) + Grads[j](2, 1); + BT(j, 5) = B(5, j) = Grads[j](0, 2) + Grads[j](2, 0); + } + BTH.setAll(0.); + BTH.gemm(BT, H); + m.gemm(BTH, B, weight * detJ, 1.); + } + } + else + { + int nbFF1 = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); + int nbFF2 = BilinearTerm<SVector3, SVector3>::space2.getNumKeys(ele); + double jac[3][3]; + fullMatrix<double> B(6, nbFF2); + fullMatrix<double> BTH(nbFF2, 6); + fullMatrix<double> BT(nbFF1, 6); + m.resize(nbFF1, nbFF2); + m.setAll(0.); + // Sum on Gauss Points i + for(int i = 0; i < npts; i++) + { + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<TensorialTraits<SVector3>::GradType> Grads;// tableau de matrices... + std::vector<TensorialTraits<SVector3>::GradType> GradsT;// tableau de matrices... + BilinearTerm<SVector3, SVector3>::space1.gradf(ele, u, v, w, Grads); + BilinearTerm<SVector3, SVector3>::space2.gradf(ele, u, v, w, GradsT); + for(int j = 0; j < nbFF1; j++) + { + BT(j, 0) = Grads[j](0, 0); + BT(j, 1) = Grads[j](1, 1); + BT(j, 2) = Grads[j](2, 2); + BT(j, 3) = Grads[j](0, 1) + Grads[j](1, 0); + BT(j, 4) = Grads[j](1, 2) + Grads[j](2, 1); + BT(j, 5) = Grads[j](0, 2) + Grads[j](2, 0); + } + for(int j = 0; j < nbFF2; j++) + { + B(0, j) = GradsT[j](0, 0); + B(1, j) = GradsT[j](1, 1); + B(2, j) = GradsT[j](2, 2); + B(3, j) = GradsT[j](0, 1) + GradsT[j](1, 0); + B(4, j) = GradsT[j](1, 2) + GradsT[j](2, 1); + B(5, j) = GradsT[j](0, 2) + GradsT[j](2, 0); + } + BTH.setAll(0.); + BTH.gemm(BT, H); + // gemm add the product to m so there is a sum on gauss' points here + m.gemm(BTH, B, weight * detJ, 1.); + } + } +} + +void LagrangeMultiplierTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + int nbFF1 = BilinearTerm<SVector3, double>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent + int nbFF2 = BilinearTerm<SVector3, double>::space2.getNumKeys(ele); //nbVertices of boundary + double jac[3][3]; + m.resize(nbFF1, nbFF2); + m.setAll(0.); + for(int i = 0; i < npts; i++) + { + double u = GP[i].pt[0]; double v = GP[i].pt[1]; double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<TensorialTraits<SVector3>::ValType> Vals; + std::vector<TensorialTraits<double>::ValType> ValsT; + BilinearTerm<SVector3,double>::space1.f(ele, u, v, w, Vals); + BilinearTerm<SVector3,double>::space2.f(ele, u, v, w, ValsT); + for(int j = 0; j < nbFF1; j++) + { + for(int k = 0; k < nbFF2; k++) + { + m(j, k) += dot(Vals[j], _d) * ValsT[k] * weight * detJ; + } + } + } +} + +void LagMultTerm::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + int nbFF1 = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent + int nbFF2 = BilinearTerm<SVector3, SVector3>::space2.getNumKeys(ele); //nbVertices of boundary + double jac[3][3]; + m.resize(nbFF1, nbFF2); + m.setAll(0.); + for(int i = 0; i < npts; i++) + { + double u = GP[i].pt[0]; double v = GP[i].pt[1]; double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<TensorialTraits<SVector3>::ValType> Vals; + std::vector<TensorialTraits<SVector3>::ValType> ValsT; + BilinearTerm<SVector3,SVector3>::space1.f(ele, u, v, w, Vals); + BilinearTerm<SVector3,SVector3>::space2.f(ele, u, v, w, ValsT); + for(int j = 0; j < nbFF1; j++) + { + for(int k = 0; k < nbFF2; k++) + { + m(j, k) += _eqfac * dot(Vals[j], ValsT[k]) * weight * detJ; + } + } + } +} + + diff --git a/Solver/terms.h b/Solver/terms.h index a336c2490a9af709e9d24ae7e36d1eafee2c6178..e3540ec8ee36df169806b3c2895e32e2bb8d5390 100644 --- a/Solver/terms.h +++ b/Solver/terms.h @@ -4,7 +4,7 @@ // Description: // // -// Author: <Eric Bechet>, (C) 2009 +// Author: <Eric Bechet>, (C) 2011 // // Copyright: See COPYING file that comes with this distribution // @@ -15,102 +15,181 @@ #define _TERMS_H_ #include "SVector3.h" -#include <vector> -#include <iterator> +#include "STensor3.h" +#include "STensor43.h" #include "Numeric.h" #include "functionSpace.h" #include "groupOfElements.h" #include "materialLaw.h" +#include <vector> +#include <iterator> + +template<class T2> class ScalarTermBase; + +template<class T2> class LinearTermBase; +template<class T2> class PlusTerm; + +class BilinearTermBase; + +inline double dot(const double &a, const double &b) +{ + return a * b; +} + +inline int delta(int i,int j) {if (i==j) return 1; else return 0;} + + + + +template<class T2=double> class ScalarTermBase +{ +public : + virtual ~ScalarTermBase() {} + virtual void get(MElement *ele, int npts, IntPt *GP, T2 &val) const = 0 ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<T2> &vval) const = 0 ; + virtual ScalarTermBase<T2>* clone () const =0; +}; + +template<class T2=double> class ScalarTerm : public ScalarTermBase<T2> +{ +public : + virtual ~ScalarTerm() {} +}; + + +template<class T2=double> class ScalarTermConstant : public ScalarTerm<T2> +{ +protected: + T2 cst; +public : + ScalarTermConstant(T2 val_ = T2()) : cst(val_) {} + virtual ~ScalarTermConstant() {} + virtual void get(MElement *ele, int npts, IntPt *GP, T2 &val) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<T2> &vval) const; + virtual void get(MVertex *ver, T2 &val) const; + virtual ScalarTermBase<T2>* clone () const {return new ScalarTermConstant<T2>(cst);} +}; + +class BilinearTermToScalarTerm : public ScalarTerm<double> +{ +protected: + BilinearTermBase &bilterm; +public : + BilinearTermToScalarTerm(BilinearTermBase &bilterm_): bilterm(bilterm_){} + virtual ~BilinearTermToScalarTerm() {} + virtual void get(MElement *ele, int npts, IntPt *GP, double &val) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<double> &vval) const {}; + virtual ScalarTermBase<double>* clone () const {return new BilinearTermToScalarTerm(bilterm);} +}; + + class BilinearTermBase { - public : +public : virtual ~BilinearTermBase() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) = 0 ; + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullMatrix<double> > &mv) const = 0 ; + virtual BilinearTermBase* clone () const =0; +}; + + +template<class T2> class BilinearTermContract : public BilinearTermBase +{ +protected: + const LinearTermBase<T2> *a; + const LinearTermBase<T2> *b; +public: + BilinearTermContract(const LinearTermBase<T2> &a_,const LinearTermBase<T2> &b_) : a(a_.clone()),b(b_.clone()) {} + virtual ~BilinearTermContract() {delete a;delete b;} + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullMatrix<double> > &mv) const {}; + virtual BilinearTermBase* clone () const {return new BilinearTermContract<T2>(*a,*b);} }; +template<class T2> class BilinearTermContractWithLaw : public BilinearTermContract<T2> +{ +public: +protected: + const ScalarTermBase< typename TensorialTraits<T2>::TensProdType > *c; +public: + BilinearTermContractWithLaw(const LinearTermBase<T2> &a_,const ScalarTermBase<typename TensorialTraits<T2>::TensProdType> &c_, const LinearTermBase<T2> &b_) : BilinearTermContract<T2>(a_,b_), c(c_.clone()) {} + virtual ~BilinearTermContractWithLaw() {delete c;} + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullMatrix<double> > &mv) const ; + virtual BilinearTermBase* clone () const {return new BilinearTermContractWithLaw<T2>(*BilinearTermContract<T2>::a,*c,*BilinearTermContract<T2>::b);} +}; + +template<class T2> BilinearTermContract<T2> operator |(const LinearTermBase<T2>& L1,const LinearTermBase<T2>& L2); + + template<class T1,class T2> class BilinearTerm : public BilinearTermBase { - protected : +protected : FunctionSpace<T1>& space1; FunctionSpace<T2>& space2; - public : +public : BilinearTerm(FunctionSpace<T1>& space1_, FunctionSpace<T2>& space2_) : space1(space1_), space2(space2_) {} virtual ~BilinearTerm() {} }; -class LinearTermBase +template<class T2=double> class LinearTermBase { - public: +public: virtual ~LinearTermBase() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<double> &v) = 0; + virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<T2> &v) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<T2> > &vv) const =0; + virtual LinearTermBase<T2>* clone () const = 0; + PlusTerm<T2> operator +(const LinearTermBase<T2>& other); +}; + + +template<class T2> class PlusTerm:public LinearTermBase<T2> +{ + const LinearTermBase<T2> *a; + const LinearTermBase<T2> *b; +public: + PlusTerm(const LinearTermBase<T2> &a_,const LinearTermBase<T2> &b_) : a(a_.clone()),b(b_.clone()) {} + virtual ~PlusTerm() {delete a;delete b;} + virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<T2> &v) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<T2> > &vv) const {}; + virtual LinearTermBase<T2>* clone () const { return new PlusTerm<T2>(*a,*b);} }; -template<class T1> class LinearTerm : public LinearTermBase + +template<class T1, class T2=double> class LinearTerm : public LinearTermBase<T2> { - protected : +protected : FunctionSpace<T1>& space1; - public : +public : LinearTerm(FunctionSpace<T1>& space1_) : space1(space1_) {} virtual ~LinearTerm() {} }; -class ScalarTermBase -{ - public : - virtual ~ScalarTermBase() {} - virtual void get(MElement *ele, int npts, IntPt *GP, double &val) = 0; -}; -class ScalarTerm : public ScalarTermBase -{ - public : - virtual ~ScalarTerm() {} -}; -template<class T1, class T2> class BilinearTermToScalarTerm : public ScalarTerm +template<class T1> class GradTerm : public LinearTerm<T1, typename TensorialTraits<T1>::GradType > { - BilinearTerm<T1, T2> &bilterm; - public : - BilinearTermToScalarTerm(BilinearTerm<T1, T2> &bilterm_): bilterm(bilterm_){} - virtual ~BilinearTermToScalarTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, double &val) - { - fullMatrix<double> localMatrix; - bilterm.get(ele, npts, GP, localMatrix); - val = localMatrix(0, 0); - } +public : + GradTerm(FunctionSpace<T1>& space1_) : LinearTerm<T1,typename TensorialTraits<T1>::GradType >(space1_) {} + virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<typename TensorialTraits<T1>::GradType > &vec) const {LinearTermBase<typename TensorialTraits<T1>::GradType>::get(ele,npts,GP,vec);} + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<typename TensorialTraits<T1>::GradType > > &vvec) const; + virtual LinearTermBase<typename TensorialTraits<T1>::GradType>* clone () const { return new GradTerm<T1>(LinearTerm<T1,typename TensorialTraits<T1>::GradType>::space1);} + virtual ~GradTerm() {} }; -class ScalarTermConstant : public ScalarTerm -{ - double val; - public : - ScalarTermConstant(double val_ = 1.0) : val(val_) {} - virtual ~ScalarTermConstant() {} - virtual void get(MElement *ele, int npts, IntPt *GP, double &val) - { - double jac[3][3]; - val = 0; - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - val += weight * detJ; - } - } - virtual void get(MVertex *ver, double &val) - { - val = 1; - } -}; template<class T1, class T2> class LaplaceTerm : public BilinearTerm<T1, T2> { - public : +public : LaplaceTerm(FunctionSpace<T1>& space1_, FunctionSpace<T2>& space2_) : BilinearTerm<T1, T2>(space1_, space2_) {} virtual ~LaplaceTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const + { + Msg::Error("LaplaceTerm<S1, S2> w/ S1 != S2 not implemented"); + } + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const { Msg::Error("LaplaceTerm<S1, S2> w/ S1 != S2 not implemented"); } @@ -118,40 +197,25 @@ template<class T1, class T2> class LaplaceTerm : public BilinearTerm<T1, T2> { Msg::Error("LaplaceTerm<S1, S2> w/ S1 != S2 not implemented"); } + virtual BilinearTermBase* clone () const {return new LaplaceTerm< T1, T2 >(BilinearTerm<T1, T2>::space1,BilinearTerm<T1, T2>::space2);} }; // class template<class T1> class LaplaceTerm<T1, T1> : public BilinearTerm<T1, T1> // symmetric { +protected: double diffusivity; - public : +public : LaplaceTerm(FunctionSpace<T1>& space1_, double diff = 1) : BilinearTerm<T1, T1>(space1_, space1_), diffusivity(diff) {} virtual ~LaplaceTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) - { - int nbFF = BilinearTerm<T1, T1>::space1.getNumKeys(ele); - double jac[3][3]; - m.resize(nbFF, nbFF); - m.setAll(0.); - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<typename TensorialTraits<T1>::GradType> Grads; - BilinearTerm<T1, T1>::space1.gradf(ele, u, v, w, Grads); - for(int j = 0; j < nbFF; j++){ - for(int k = j; k < nbFF; k++){ - double contrib = weight * detJ * dot(Grads[j], Grads[k]) * diffusivity; - m(j, k) += contrib; - if(j != k) m(k, j) += contrib; - } - } - } - } + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const{}; + virtual BilinearTermBase* clone () const {return new LaplaceTerm< T1, T1 >(BilinearTerm<T1, T1>::space1,diffusivity);} }; // class class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> { - protected : +protected : double E, nu; bool sym; fullMatrix<double> H;/* = @@ -161,237 +225,71 @@ class IsotropicElasticTerm : public BilinearTerm<SVector3,SVector3> { 0, 0, 0, C44, 0, 0}, { 0, 0, 0, 0, C44, 0}, { 0, 0, 0, 0, 0, C44} };*/ - public : - IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<SVector3>& space2_, double E_, double nu_) : - BilinearTerm<SVector3, SVector3>(space1_, space2_), E(E_), nu(nu_), H(6, 6) - { - double FACT = E / (1 + nu); - double C11 = FACT * (1 - nu) / (1 - 2 * nu); - double C12 = FACT * nu / (1 - 2 * nu); - double C44 = (C11 - C12) / 2; - H.scale(0.); - for(int i = 0; i < 3; ++i) { H(i, i) = C11; H(i + 3, i + 3) = C44; } - H(1, 0) = H(0, 1) = H(2, 0) = H(0, 2) = H(1, 2) = H(2, 1) = C12; - sym = (&space1_ == &space2_); - } - IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, double E_, double nu_) : - BilinearTerm<SVector3, SVector3>(space1_, space1_), E(E_), nu(nu_), H(6, 6) - { - double FACT = E / (1 + nu); - double C11 = FACT * (1 - nu) / (1 - 2 * nu); - double C12 = FACT * nu / (1 - 2 * nu); - double C44 = (C11 - C12) / 2; - FACT = E / (1 - nu * nu); - C11 = FACT; - C12 = nu * FACT; - C44 = (1. - nu) * .5 * FACT; - H.scale(0.); - for(int i = 0; i < 3; ++i) { H(i, i) = C11; H(i + 3, i + 3) = C44; } - H(1, 0) = H(0, 1) = H(2, 0) = H(0, 2) = H(1, 2) = H(2, 1) = C12; - sym = true; - } +public : + IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<SVector3>& space2_, double E_, double nu_); + IsotropicElasticTerm(FunctionSpace<SVector3>& space1_, double E_, double nu_); virtual ~IsotropicElasticTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) - { - if(ele->getParent()) ele = ele->getParent(); - if(sym){ - int nbFF = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); - double jac[3][3]; - fullMatrix<double> B(6, nbFF); - fullMatrix<double> BTH(nbFF, 6); - fullMatrix<double> BT(nbFF, 6); - m.resize(nbFF, nbFF); - m.setAll(0.); - //std::cout << m.size1() << " " << m.size2() << std::endl; - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<TensorialTraits<SVector3>::GradType> Grads; - BilinearTerm<SVector3, SVector3>::space1.gradf(ele, u, v, w, Grads); // a optimiser ?? - for(int j = 0; j < nbFF; j++){ - BT(j, 0) = B(0, j) = Grads[j](0, 0); - BT(j, 1) = B(1, j) = Grads[j](1, 1); - BT(j, 2) = B(2, j) = Grads[j](2, 2); - BT(j, 3) = B(3, j) = Grads[j](0, 1) + Grads[j](1, 0); - BT(j, 4) = B(4, j) = Grads[j](1, 2) + Grads[j](2, 1); - BT(j, 5) = B(5, j) = Grads[j](0, 2) + Grads[j](2, 0); - } - BTH.setAll(0.); - BTH.gemm(BT, H); - m.gemm(BTH, B, weight * detJ, 1.); - } - } - else{ - int nbFF1 = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); - int nbFF2 = BilinearTerm<SVector3, SVector3>::space2.getNumKeys(ele); - double jac[3][3]; - fullMatrix<double> B(6, nbFF2); - fullMatrix<double> BTH(nbFF2, 6); - fullMatrix<double> BT(nbFF1, 6); - m.resize(nbFF1, nbFF2); - m.setAll(0.); - // Sum on Gauss Points i - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<TensorialTraits<SVector3>::GradType> Grads;// tableau de matrices... - std::vector<TensorialTraits<SVector3>::GradType> GradsT;// tableau de matrices... - BilinearTerm<SVector3, SVector3>::space1.gradf(ele, u, v, w, Grads); - BilinearTerm<SVector3, SVector3>::space2.gradf(ele, u, v, w, GradsT); - for(int j = 0; j < nbFF1; j++){ - BT(j, 0) = Grads[j](0, 0); - BT(j, 1) = Grads[j](1, 1); - BT(j, 2) = Grads[j](2, 2); - BT(j, 3) = Grads[j](0, 1) + Grads[j](1, 0); - BT(j, 4) = Grads[j](1, 2) + Grads[j](2, 1); - BT(j, 5) = Grads[j](0, 2) + Grads[j](2, 0); - } - for(int j = 0; j < nbFF2; j++){ - B(0, j) = GradsT[j](0, 0); - B(1, j) = GradsT[j](1, 1); - B(2, j) = GradsT[j](2, 2); - B(3, j) = GradsT[j](0, 1) + GradsT[j](1, 0); - B(4, j) = GradsT[j](1, 2) + GradsT[j](2, 1); - B(5, j) = GradsT[j](0, 2) + GradsT[j](2, 0); - } - BTH.setAll(0.); - BTH.gemm(BT, H); - // gemm add the product to m so there is a sum on gauss' points here - m.gemm(BTH, B, weight * detJ, 1.); - } - } - } + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const{}; + virtual BilinearTermBase* clone () const {return new IsotropicElasticTerm(BilinearTerm<SVector3, SVector3>::space1,BilinearTerm<SVector3, SVector3>::space2,E,nu);} }; // class -inline double dot(const double &a, const double &b) -{ - return a * b; -} template<class T1> class LoadTerm : public LinearTerm<T1> { +protected: simpleFunction<typename TensorialTraits<T1>::ValType> &Load; - public : +public : LoadTerm(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> &Load_) : - LinearTerm<T1>(space1_), Load(Load_) {} + LinearTerm<T1>(space1_), Load(Load_) {} virtual ~LoadTerm() {} - - virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) - { - if(ele->getParent()) ele = ele->getParent(); - int nbFF = LinearTerm<T1>::space1.getNumKeys(ele); - double jac[3][3]; - m.resize(nbFF); - m.scale(0.); - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<typename TensorialTraits<T1>::ValType> Vals; - LinearTerm<T1>::space1.f(ele, u, v, w, Vals); - SPoint3 p; - ele->pnt(u, v, w, p); - typename TensorialTraits<T1>::ValType load = Load(p.x(), p.y(), p.z()); - for(int j = 0; j < nbFF ; ++j){ - m(j) += dot(Vals[j], load) * weight * detJ; - } - } - } + virtual LinearTermBase<double>* clone () const { return new LoadTerm<T1>(LinearTerm<T1>::space1,Load);} + virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<double> > &vv) const {}; }; class LagrangeMultiplierTerm : public BilinearTerm<SVector3, double> { SVector3 _d; - public : +public : LagrangeMultiplierTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<double>& space2_, const SVector3 &d) : - BilinearTerm<SVector3, double>(space1_, space2_) + BilinearTerm<SVector3, double>(space1_, space2_) { - for(int i = 0; i < 3; i++) _d(i) = d(i); + for (int i = 0; i < 3; i++) _d(i) = d(i); } virtual ~LagrangeMultiplierTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) - { - int nbFF1 = BilinearTerm<SVector3, double>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent - int nbFF2 = BilinearTerm<SVector3, double>::space2.getNumKeys(ele); //nbVertices of boundary - double jac[3][3]; - m.resize(nbFF1, nbFF2); - m.setAll(0.); - for(int i = 0; i < npts; i++){ - double u = GP[i].pt[0]; double v = GP[i].pt[1]; double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<TensorialTraits<SVector3>::ValType> Vals; - std::vector<TensorialTraits<double>::ValType> ValsT; - BilinearTerm<SVector3,double>::space1.f(ele, u, v, w, Vals); - BilinearTerm<SVector3,double>::space2.f(ele, u, v, w, ValsT); - for(int j = 0; j < nbFF1; j++){ - for(int k = 0; k < nbFF2; k++){ - m(j, k) += dot(Vals[j], _d) * ValsT[k] * weight * detJ; - } - } - } - } + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const{}; + virtual BilinearTermBase* clone () const {return new LagrangeMultiplierTerm(BilinearTerm<SVector3, double>::space1,BilinearTerm<SVector3, double>::space2,_d);} }; class LagMultTerm : public BilinearTerm<SVector3, SVector3> { - private : +private : double _eqfac; - public : +public : LagMultTerm(FunctionSpace<SVector3>& space1_, FunctionSpace<SVector3>& space2_, double eqfac = 1.0) : - BilinearTerm<SVector3, SVector3>(space1_, space2_), _eqfac(eqfac) {} + BilinearTerm<SVector3, SVector3>(space1_, space2_), _eqfac(eqfac) {} virtual ~LagMultTerm() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) - { - int nbFF1 = BilinearTerm<SVector3, SVector3>::space1.getNumKeys(ele); //nbVertices*nbcomp of parent - int nbFF2 = BilinearTerm<SVector3, SVector3>::space2.getNumKeys(ele); //nbVertices of boundary - double jac[3][3]; - m.resize(nbFF1, nbFF2); - m.setAll(0.); - for(int i = 0; i < npts; i++) { - double u = GP[i].pt[0]; double v = GP[i].pt[1]; double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<TensorialTraits<SVector3>::ValType> Vals; - std::vector<TensorialTraits<SVector3>::ValType> ValsT; - BilinearTerm<SVector3,SVector3>::space1.f(ele, u, v, w, Vals); - BilinearTerm<SVector3,SVector3>::space2.f(ele, u, v, w, ValsT); - for(int j = 0; j < nbFF1; j++){ - for(int k = 0; k < nbFF2; k++){ - m(j, k) += _eqfac * dot(Vals[j], ValsT[k]) * weight * detJ; - } - } - } - } + virtual void get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector< fullMatrix<double> > &vm) const{}; + virtual BilinearTermBase* clone () const {return new LagMultTerm(BilinearTerm<SVector3, SVector3>::space1,BilinearTerm<SVector3, SVector3>::space2,_eqfac);} }; template<class T1> class LoadTermOnBorder : public LinearTerm<T1> { - private : +private : double _eqfac; simpleFunction<typename TensorialTraits<T1>::ValType> &Load; - public : +public : LoadTermOnBorder(FunctionSpace<T1>& space1_, simpleFunction<typename TensorialTraits<T1>::ValType> &Load_, double eqfac = 1.0) : - LinearTerm<T1>(space1_), _eqfac(eqfac), Load(Load_) {} + LinearTerm<T1>(space1_), _eqfac(eqfac), Load(Load_) {} virtual ~LoadTermOnBorder() {} - virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) - { - MElement *elep; - if (ele->getParent()) elep = ele->getParent(); - int nbFF = LinearTerm<T1>::space1.getNumKeys(ele); - double jac[3][3]; - m.resize(nbFF); - m.scale(0.); - for(int i = 0; i < npts; i++){ - const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; - const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); - std::vector<typename TensorialTraits<T1>::ValType> Vals; - LinearTerm<T1>::space1.f(ele, u, v, w, Vals); - SPoint3 p; - ele->pnt(u, v, w, p); - typename TensorialTraits<T1>::ValType load = Load(p.x(), p.y(), p.z()); - for(int j = 0; j < nbFF ; ++j){ - m(j) += _eqfac * dot(Vals[j], load) * weight * detJ; - } - } - } + virtual LinearTermBase<double>* clone () const { return new LoadTermOnBorder<T1>(LinearTerm<T1>::space1,Load,_eqfac);} + virtual void get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) const ; + virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<double> > &vv) const {}; }; +#include "terms.hpp" + #endif// _TERMS_H_ diff --git a/Solver/terms.hpp b/Solver/terms.hpp new file mode 100644 index 0000000000000000000000000000000000000000..844efa9d84761e7b32d35a13606498454ac1898e --- /dev/null +++ b/Solver/terms.hpp @@ -0,0 +1,220 @@ +// +// C++ Template Implementations: terms +// +// Description: +// +// +// Author: <Eric Bechet>, (C) 2011 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "terms.h" + +template<class T2> void LinearTermBase<T2>::get(MElement *ele, int npts, IntPt *GP, fullVector<T2> &vec) const +{ + std::vector<fullVector<T2> > vv; + vv.resize(npts); + get(ele,npts,GP,vv); + int nbFF=vv[0].size(); + vec.resize(nbFF); + vec.setAll(T2()); + double jac[3][3]; + for(int i = 0; i < npts; i++) + { + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + for(int j = 0; j < nbFF; j++) + { + double contrib = weight * detJ; + vec(j) += contrib*vv[i](j); + } + } +} + +template<class T2> void PlusTerm<T2>::get(MElement *ele, int npts, IntPt *GP, fullVector<T2> &v) const +{ + fullVector<T2> v2; + a->get(ele,npts,GP,v); + b->get(ele,npts,GP,v2); + for (int i=0;i<v2.size();++i) v(i)+=v2(i); +} + +template<class T2> void ScalarTermConstant<T2>::get(MElement *ele, int npts, IntPt *GP, T2 &val) const +{ + double jac[3][3]; + double eval = 0; + for(int i = 0; i < npts; i++) + { + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + eval += weight * detJ; + } + val=cst * eval; +} + +template<class T2> void ScalarTermConstant<T2>::get(MElement *ele, int npts, IntPt *GP, std::vector<T2> &vval) const +{ + for(int i = 0; i < npts; i++) + { + vval[i] = cst; + } +} + +template<class T2> void ScalarTermConstant<T2>::get(MVertex *ver, T2 &val) const +{ + val = cst; +} + +template<class T1> void LaplaceTerm<T1, T1>::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + int nbFF = BilinearTerm<T1, T1>::space1.getNumKeys(ele); + double jac[3][3]; + m.resize(nbFF, nbFF); + m.setAll(0.); + for(int i = 0; i < npts; i++){ + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<typename TensorialTraits<T1>::GradType> Grads; + BilinearTerm<T1, T1>::space1.gradf(ele, u, v, w, Grads); + for(int j = 0; j < nbFF; j++) + { + for(int k = j; k < nbFF; k++) + { + double contrib = weight * detJ * dot(Grads[j], Grads[k]) * diffusivity; + m(j, k) += contrib; + if(j != k) m(k, j) += contrib; + } + } + } +} + +template<class T1> void LoadTerm<T1>::get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) const +{ + if(ele->getParent()) ele = ele->getParent(); + int nbFF = LinearTerm<T1>::space1.getNumKeys(ele); + double jac[3][3]; + m.resize(nbFF); + m.scale(0.); + for(int i = 0; i < npts; i++){ + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<typename TensorialTraits<T1>::ValType> Vals; + LinearTerm<T1>::space1.f(ele, u, v, w, Vals); + SPoint3 p; + ele->pnt(u, v, w, p); + typename TensorialTraits<T1>::ValType load = Load(p.x(), p.y(), p.z()); + for(int j = 0; j < nbFF ; ++j) + { + m(j) += dot(Vals[j], load) * weight * detJ; + } + } +} + +template<class T2> BilinearTermContract<T2> operator |(const LinearTermBase<T2>& L1,const LinearTermBase<T2>& L2) +{ + return BilinearTermContract<T2>(L1,L2); +} + +template<class T2> void BilinearTermContract<T2>::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + fullVector<T2> va; + fullVector<T2> vb; + a->get(ele,npts,GP,va); + b->get(ele,npts,GP,vb); + m.resize(va.size(), vb.size()); + m.setAll(0.); + for (int i=0;i<va.size();++i) + for (int j=0;j<vb.size();++j) + m(i,j)=dot(va(i),vb(j)); +} + + +template<class T2> void BilinearTermContractWithLaw<T2>::get(MElement *ele, int npts, IntPt *GP, fullMatrix<double> &m) const +{ + BilinearTermBase::get(ele,npts,GP,m); +} + +template<class T2> void BilinearTermContractWithLaw<T2>::get(MElement *ele, int npts, IntPt *GP, std::vector<fullMatrix<double> > &mv) const +{ + std::vector<fullVector<T2> > va(npts); + std::vector<fullVector<T2> > vb(npts); + std::vector<typename TensorialTraits<T2>::TensProdType> tens(npts); + BilinearTermContract<T2>::a->get(ele,npts,GP,va); + BilinearTermContract<T2>::b->get(ele,npts,GP,vb); + c->get(ele,npts,GP,tens); + for (int k=0;k<npts;k++) + { + mv[k].resize(va[k].size(), vb[k].size()); + for (int i=0;i<va[k].size();++i) + for (int j=0;j<vb[k].size();++j) + mv[k](i,j)=dot(va[k](i),tens[k]*vb[k](j)); + } +} + +template<class T2> PlusTerm<T2> LinearTermBase<T2>::operator +(const LinearTermBase<T2>& other) +{ + return PlusTerm<T2>(*this,other); +} +/* +template<class T1> void GradTerm<T1>::get(MElement *ele, int npts, IntPt *GP, fullVector<typename TensorialTraits<T1>::GradType > &vec) const +{ + int nbFF = LinearTerm<T1,typename TensorialTraits<T1>::GradType>::space1.getNumKeys(ele); + double jac[3][3]; + vec.resize(nbFF); + vec.setAll(typename TensorialTraits<T1>::GradType()); + for(int i = 0; i < npts; i++) + { + std::vector<typename TensorialTraits<T1>::GradType> Grads; + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + LinearTerm<T1,typename TensorialTraits<T1>::GradType>::space1.gradf(ele, u, v, w, Grads); + for(int j = 0; j < nbFF; j++) + { + double contrib = weight * detJ; + vec(j) += contrib*Grads[j]; + } + } +} +*/ +template<class T1> void GradTerm<T1>::get(MElement *ele, int npts, IntPt *GP, std::vector<fullVector<typename TensorialTraits<T1>::GradType > > &vvec) const +{ + int nbFF = LinearTerm<T1,typename TensorialTraits<T1>::GradType>::space1.getNumKeys(ele); + for(int i = 0; i < npts; i++) + { + vvec[i].resize(nbFF); + std::vector<typename TensorialTraits<T1>::GradType> Grads; + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + LinearTerm<T1,typename TensorialTraits<T1>::GradType>::space1.gradf(ele, u, v, w, Grads); + for(int j = 0; j < nbFF; j++) + { + vvec[i](j) = Grads[j]; + } + } +} + + + +template<class T1> void LoadTermOnBorder<T1>::get(MElement *ele, int npts, IntPt *GP, fullVector<double> &m) const +{ + MElement *elep; + if (ele->getParent()) elep = ele->getParent(); + int nbFF = LinearTerm<T1>::space1.getNumKeys(ele); + double jac[3][3]; + m.resize(nbFF); + m.scale(0.); + for(int i = 0; i < npts; i++) + { + const double u = GP[i].pt[0]; const double v = GP[i].pt[1]; const double w = GP[i].pt[2]; + const double weight = GP[i].weight; const double detJ = ele->getJacobian(u, v, w, jac); + std::vector<typename TensorialTraits<T1>::ValType> Vals; + LinearTerm<T1>::space1.f(ele, u, v, w, Vals); + SPoint3 p; + ele->pnt(u, v, w, p); + typename TensorialTraits<T1>::ValType load = Load(p.x(), p.y(), p.z()); + for(int j = 0; j < nbFF ; ++j){ + m(j) += _eqfac * dot(Vals[j], load) * weight * detJ; + } + } +}