Forked from
gmsh / gmsh
14554 commits behind the upstream repository.
-
Gauthier Becker authoredGauthier Becker authored
elasticitySolver.cpp 11.41 KiB
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#include <string.h>
#include "GmshConfig.h"
#include "elasticitySolver.h"
#include "linearSystemCSR.h"
#include "linearSystemPETSc.h"
#include "linearSystemGMM.h"
#include "Numeric.h"
#include "GModel.h"
#include "functionSpace.h"
#include "terms.h"
#include "solverAlgorithms.h"
#include "quadratureRules.h"
#include "solverField.h"
#include "MPoint.h"
#if defined(HAVE_POST)
#include "PView.h"
#include "PViewData.h"
#endif
void elasticitySolver::setMesh(const std::string &meshFileName)
{
pModel = new GModel();
pModel->readMSH(meshFileName.c_str());
_dim = pModel->getNumRegions() ? 3 : 2;
if (LagSpace) delete LagSpace;
if (_dim==3) LagSpace=new VectorLagrangeFunctionSpace(_tag);
if (_dim==2) LagSpace=new VectorLagrangeFunctionSpace(_tag,VectorLagrangeFunctionSpace::VECTOR_X,VectorLagrangeFunctionSpace::VECTOR_Y);
}
void elasticitySolver::readInputFile(const std::string &fn)
{
FILE *f = fopen(fn.c_str(), "r");
char what[256];
while(!feof(f)){
if(fscanf(f, "%s", what) != 1) return;
if (!strcmp(what, "ElasticDomain")){
elasticField field;
int physical;
if(fscanf(f, "%d %lf %lf", &physical, &field._E, &field._nu) != 3) return;
field._tag = _tag;
field.g = new groupOfElements (_dim, physical);
elasticFields.push_back(field);
}
else if (!strcmp(what, "Void")){
// elasticField field;
// create enrichment ...
// create the group ...
// assign a tag
// elasticFields.push_back(field);
}
else if (!strcmp(what, "NodeDisplacement")){
double val;
int node, comp;
if(fscanf(f, "%d %d %lf", &node, &comp, &val) != 3) return;
dirichletBC diri;
diri.g = new groupOfElements (0, node);
diri._f= simpleFunction<double>(val);
diri._comp=comp;
diri._tag=node;
diri.onWhat=BoundaryCondition::ON_VERTEX;
allDirichlet.push_back(diri);
}
else if (!strcmp(what, "EdgeDisplacement")){
double val;
int edge, comp;
if(fscanf(f, "%d %d %lf", &edge, &comp, &val) != 3) return;
dirichletBC diri;
diri.g = new groupOfElements (1, edge);
diri._f= simpleFunction<double>(val);
diri._comp=comp;
diri._tag=edge;
diri.onWhat=BoundaryCondition::ON_EDGE;
allDirichlet.push_back(diri);
}
else if (!strcmp(what, "FaceDisplacement")){
double val;
int face, comp;
if(fscanf(f, "%d %d %lf", &face, &comp, &val) != 3) return;
dirichletBC diri;
diri.g = new groupOfElements (2, face);
diri._f= simpleFunction<double>(val);
diri._comp=comp;
diri._tag=face;
diri.onWhat=BoundaryCondition::ON_FACE;
allDirichlet.push_back(diri);
}
else if (!strcmp(what, "NodeForce")){
double val1, val2, val3;
int node;
if(fscanf(f, "%d %lf %lf %lf", &node, &val1, &val2, &val3) != 4) return;
neumannBC neu;
neu.g = new groupOfElements (0, node);
neu._f= simpleFunction<SVector3>(SVector3(val1, val2, val3));
neu._tag=node;
neu.onWhat=BoundaryCondition::ON_VERTEX;
allNeumann.push_back(neu);
}
else if (!strcmp(what, "EdgeForce")){
double val1, val2, val3;
int edge;
if(fscanf(f, "%d %lf %lf %lf", &edge, &val1, &val2, &val3) != 4) return;
neumannBC neu;
neu.g = new groupOfElements (1, edge);
neu._f= simpleFunction<SVector3>(SVector3(val1, val2, val3));
neu._tag=edge;
neu.onWhat=BoundaryCondition::ON_EDGE;
allNeumann.push_back(neu);
}
else if (!strcmp(what, "FaceForce")){
double val1, val2, val3;
int face;
if(fscanf(f, "%d %lf %lf %lf", &face, &val1, &val2, &val3) != 4) return;
neumannBC neu;
neu.g = new groupOfElements (2, face);
neu._f= simpleFunction<SVector3>(SVector3(val1, val2, val3));
neu._tag=face;
neu.onWhat=BoundaryCondition::ON_FACE;
allNeumann.push_back(neu);
}
else if (!strcmp(what, "VolumeForce")){
double val1, val2, val3;
int volume;
if(fscanf(f, "%d %lf %lf %lf", &volume, &val1, &val2, &val3) != 4) return;
neumannBC neu;
neu.g = new groupOfElements (3, volume);
neu._f= simpleFunction<SVector3>(SVector3(val1, val2, val3));
neu._tag=volume;
neu.onWhat=BoundaryCondition::ON_VOLUME;
allNeumann.push_back(neu);
}
else if (!strcmp(what, "MeshFile")){
char name[245];
if(fscanf(f, "%s", name) != 1) return;
setMesh(name);
}
else {
Msg::Error("Invalid input : %s", what);
// return;
}
}
fclose(f);
}
void elasticitySolver::solve()
{
#if defined(HAVE_TAUCS)
linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>;
#elif defined(HAVE_PETSC)
linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>;
#else
linearSystemGmm<double> *lsys = new linearSystemGmm<double>;
lsys->setNoisy(2);
#endif
if (pAssembler) delete pAssembler;
pAssembler = new dofManager<double>(lsys);
// we first do all fixations. the behavior of the dofManager is to
// give priority to fixations : when a dof is fixed, it cannot be
// numbered afterwards
std::cout << "Dirichlet BC"<< std::endl;
for (unsigned int i = 0; i < allDirichlet.size(); i++)
{
FilterDofComponent filter(allDirichlet[i]._comp);
FixNodalDofs(*LagSpace,allDirichlet[i].g->begin(),allDirichlet[i].g->end(),*pAssembler,allDirichlet[i]._f,filter);
}
// we number the dofs : when a dof is numbered, it cannot be numbered
// again with another number.
for (unsigned int i = 0; i < elasticFields.size(); ++i)
{
NumberDofs(*LagSpace, elasticFields[i].g->begin(), elasticFields[i].g->end(),*pAssembler);
}
// Now we start the assembly process
// First build the force vector
GaussQuadrature Integ_Boundary(GaussQuadrature::Val);
std::cout << "Neumann BC"<< std::endl;
for (unsigned int i = 0; i < allNeumann.size(); i++)
{
LoadTerm<SVector3> Lterm(*LagSpace,allNeumann[i]._f);
Assemble(Lterm,*LagSpace,allNeumann[i].g->begin(),allNeumann[i].g->end(),Integ_Boundary,*pAssembler);
}
// bulk material law
GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad);
for (unsigned int i = 0; i < elasticFields.size(); i++)
{
IsotropicElasticTerm Eterm(*LagSpace,elasticFields[i]._E,elasticFields[i]._nu);
// LaplaceTerm<SVector3,SVector3> Eterm(*LagSpace);
Assemble(Eterm,*LagSpace,elasticFields[i].g->begin(),elasticFields[i].g->end(),Integ_Bulk,*pAssembler);
}
printf("-- done assembling!\n");
lsys->systemSolve();
printf("-- done solving!\n");
double energ=0;
for (unsigned int i = 0; i < elasticFields.size(); i++)
{
SolverField<SVector3> Field(pAssembler, LagSpace);
IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu);
BilinearTermToScalarTerm<SVector3,SVector3> 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);
}
#if defined(HAVE_POST)
static double vonMises(dofManager<double> *a, MElement *e,
double u, double v, double w,
double E, double nu, int _tag)
{
double valx[256];
double valy[256];
double valz[256];
for (int k = 0; k < e->getNumVertices(); k++){
valx[k] = a->getDofValue(e->getVertex(k), 0, _tag);
valy[k] = a->getDofValue(e->getVertex(k), 1, _tag);
valz[k] = a->getDofValue(e->getVertex(k), 2, _tag);
}
double gradux[3];
double graduy[3];
double graduz[3];
e->interpolateGrad(valx, u, v, w, gradux);
e->interpolateGrad(valy, u, v, w, graduy);
e->interpolateGrad(valz, u, v, w, graduz);
double eps[6] = {gradux[0], graduy[1], graduz[2],
0.5 * (gradux[1] + graduy[0]),
0.5 * (gradux[2] + graduz[0]),
0.5 * (graduy[2] + graduz[1])};
double A = E / (1. + nu);
double B = A * (nu / (1. - 2 * nu));
double trace = eps[0] + eps[1] + eps[2] ;
double sxx = A * eps[0] + B * trace;
double syy = A * eps[1] + B * trace;
double szz = A * eps[2] + B * trace;
double sxy = A * eps[3];
double sxz = A * eps[4];
double syz = A * eps[5];
double s[9] = {sxx, sxy, sxz,
sxy, syy, syz,
sxz, syz, szz};
return ComputeVonMises(s);
}
PView* elasticitySolver::buildDisplacementView (const std::string &postFileName)
{
std::set<MVertex*> v;
for (unsigned int i = 0; i < elasticFields.size(); ++i)
{
for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it)
{
MElement *e=*it;
for (int j = 0; j < e->getNumVertices(); ++j) v.insert(e->getVertex(j));
}
}
std::map<int, std::vector<double> > data;
SolverField<SVector3> Field(pAssembler, LagSpace);
for ( std::set<MVertex*>::iterator it = v.begin(); it != v.end(); ++it)
{
SVector3 val;
MPoint p(*it);
Field.f(&p,0,0,0,val);
std::vector<double> vec(3);vec[0]=val(0);vec[1]=val(1);vec[2]=val(2);
data[(*it)->getNum()]=vec;
}
PView *pv = new PView (postFileName, "NodeData", pModel, data, 0.0);
return pv;
}
PView *elasticitySolver::buildElasticEnergyView(const std::string &postFileName)
{
std::map<int, std::vector<double> > data;
GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad);
for (unsigned int i = 0; i < elasticFields.size(); ++i)
{
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);
for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it)
{
MElement *e=*it;
double energ;
double vol;
IntPt *GP;
int npts=Integ_Bulk.getIntPoints(e,&GP);
Elastic_Energy_Term.get(e,npts,GP,energ);
One.get(e,npts,GP,vol);
std::vector<double> vec;
vec.push_back(energ/vol);
data[(*it)->getNum()]=vec;
}
}
PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0);
return pv;
}
PView *elasticitySolver::buildVonMisesView(const std::string &postFileName)
{
std::map<int, std::vector<double> > data;
GaussQuadrature Integ_Bulk(GaussQuadrature::GradGrad);
for (unsigned int i = 0; i < elasticFields.size(); ++i)
{
SolverField<SVector3> Field(pAssembler, LagSpace);
IsotropicElasticTerm Eterm(Field,elasticFields[i]._E,elasticFields[i]._nu);
BilinearTermToScalarTerm<SVector3,SVector3> Elastic_Energy_Term(Eterm);
for (groupOfElements::elementContainer::const_iterator it = elasticFields[i].g->begin(); it != elasticFields[i].g->end(); ++it)
{
MElement *e=*it;
double energ;
double vol;
IntPt *GP;
int npts=Integ_Bulk.getIntPoints(e,&GP);
Elastic_Energy_Term.get(e,npts,GP,energ);
std::vector<double> vec;
vec.push_back(energ);
data[(*it)->getNum()]=vec;
}
}
PView *pv = new PView (postFileName, "ElementData", pModel, data, 0.0);
return pv;
}
#else
PView* elasticitySolver::buildDisplacementView (const std::string &postFileName)
{
Msg::Error("Post-pro module not available");
return 0;
}
PView* elasticitySolver::buildElasticEnergyView(const std::string &postFileName)
{
Msg::Error("Post-pro module not available");
return 0;
}
#endif