Skip to content
Snippets Groups Projects
Commit aa0e8b0a authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

new Plugin(Crack) for Gmsh/CIVA

parent 0e944b5f
No related branches found
No related tags found
No related merge requests found
......@@ -31,7 +31,7 @@ set(SRC
Scal2Vec.cpp
CutMesh.cpp
NewView.cpp
SimplePartition.cpp
SimplePartition.cpp Crack.cpp
)
file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
......
// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to the public mailing list <gmsh@geuz.org>.
#include "Crack.h"
#include "GModel.h"
#include "partitionFace.h"
#include "partitionEdge.h"
#include "MElement.h"
#include "MLine.h"
#include "MTriangle.h"
#include "MQuadrangle.h"
#include "MFace.h"
#include "MEdge.h"
#include "mathEvaluator.h"
#if defined(HAVE_MESH)
#include "meshPartition.h"
#endif
StringXNumber CrackOptions_Number[] = {
{GMSH_FULLRC, "Dimension", NULL, 1.},
{GMSH_FULLRC, "PhysicalGroup", NULL, 1.},
};
extern "C"
{
GMSH_Plugin *GMSH_RegisterCrackPlugin()
{
return new GMSH_CrackPlugin();
}
}
std::string GMSH_CrackPlugin::getHelp() const
{
return "Plugin(Crack) creates a crack around the physical group";
}
int GMSH_CrackPlugin::getNbOptions() const
{
return sizeof(CrackOptions_Number) / sizeof(StringXNumber);
}
StringXNumber *GMSH_CrackPlugin::getOption(int iopt)
{
return &CrackOptions_Number[iopt];
}
class EdgeData{
public:
EdgeData(MEdge e) : edge(e) {}
MEdge edge;
std::vector<MVertex*> data;
};
struct Less_EdgeData : public std::binary_function<EdgeData, EdgeData, bool> {
bool operator()(const EdgeData &e1, const EdgeData &e2) const
{
if(e1.edge.getMinVertex() < e2.edge.getMinVertex()) return true;
if(e1.edge.getMinVertex() > e2.edge.getMinVertex()) return false;
if(e1.edge.getMaxVertex() < e2.edge.getMaxVertex()) return true;
return false;
}
};
PView *GMSH_CrackPlugin::execute(PView *view)
{
int dim = (int)CrackOptions_Number[0].def;
int physical = (int)CrackOptions_Number[1].def;
if(dim != 1 && dim != 2){
Msg::Error("Crack dimension should be 1 or 2");
return view;
}
GModel *m = GModel::current();
std::map<int, std::vector<GEntity*> > groups[4];
m->getPhysicalGroups(groups);
std::vector<GEntity*> entities = groups[dim][physical];
if(entities.empty()){
Msg::Error("Physical group %d (dimension %d) is empty", physical, dim);
return view;
}
// get crack elements
std::vector<MElement*> crackElements;
for(unsigned int i = 0; i < entities.size(); i++)
for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++)
crackElements.push_back(entities[i]->getMeshElement(j));
// get internal crack vertices
std::set<MVertex*> crackVertices, bndVertices;
if(dim == 1){
for(unsigned int i = 0; i < crackElements.size(); i++){
for(int j = 0; j < crackElements[i]->getNumVertices(); j++){
MVertex *v = crackElements[i]->getVertex(j);
crackVertices.insert(v);
if(bndVertices.find(v) == bndVertices.end())
bndVertices.insert(v);
else
bndVertices.erase(v);
}
}
}
else{
std::set<EdgeData, Less_EdgeData> bnd;
for(unsigned int i = 0; i < crackElements.size(); i++){
for(int j = 0; j < crackElements[i]->getNumVertices(); j++){
MVertex *v = crackElements[i]->getVertex(j);
crackVertices.insert(v);
}
for(int j = 0; j < crackElements[i]->getNumEdges(); j++){
EdgeData ed(crackElements[i]->getEdge(j));
if(bnd.find(ed) == bnd.end()){
crackElements[i]->getEdgeVertices(j, ed.data);
bnd.insert(ed);
}
else
bnd.erase(ed);
}
}
for(std::set<EdgeData>::iterator it = bnd.begin(); it != bnd.end(); it++)
bndVertices.insert(it->data.begin(), it->data.end());
}
for(std::set<MVertex*>::iterator it = bndVertices.begin();
it != bndVertices.end(); it++)
crackVertices.erase(*it);
// compute smoothed normals on crack vertices
std::map<MVertex*, std::vector<MElement*> > vxe;
for(unsigned int i = 0; i < crackElements.size(); i++){
MElement *e = crackElements[i];
for(int k = 0; k < e->getNumVertices(); k++)
vxe[e->getVertex(k)].push_back(e);
}
std::map<MVertex*, SVector3> vxn;
for(std::map<MVertex*, std::vector<MElement*> >::iterator it = vxe.begin();
it != vxe.end(); it++){
SVector3 n;
for(unsigned int i = 0; i < it->second.size(); i++){
if(dim == 1)
n += it->second[i]->getEdge(0).normal();
else
n += it->second[i]->getFace(0).normal();
}
n.normalize();
vxn[it->first] = n;
}
// compute elements on one side of the crack
vxe.clear();
std::vector<GEntity*> allentities;
m->getEntities(allentities);
for(unsigned int ent = 0; ent < allentities.size(); ent++){
if(allentities[ent]->dim() != dim + 1) continue;
for(int i = 0; i < allentities[ent]->getNumMeshElements(); i++){
MElement *e = allentities[ent]->getMeshElement(i);
for(int j = 0; j < e->getNumVertices(); j++){
MVertex *v = e->getVertex(j);
if(crackVertices.find(v) != crackVertices.end()){
MVertex *vclose = 0;
double d = 1e22;
SVector3 dv;
for(std::set<MVertex*>::iterator it = crackVertices.begin();
it != crackVertices.end(); it++){
MVertex *v = *it;
double d2 = v->point().distance(e->barycenter());
if(d2 < d){
d = d2;
vclose = v;
dv = SVector3(e->barycenter(), vclose->point());
}
}
if(dot(vxn[vclose], dv) < 0)
vxe[v].push_back(e);
}
}
}
}
// create new crack entity
GEdge *crackEdge = 0;
GFace *crackFace = 0;
if(dim == 1){
crackEdge = new discreteEdge(m, m->getMaxElementaryNumber(1) + 1, 0, 0);
m->add(crackEdge);
}
else{
crackFace = new discreteFace(m, m->getMaxElementaryNumber(2) + 1);
m->add(crackFace);
}
GEntity *crackEntity = crackEdge ? (GEntity*)crackEdge : (GEntity*)crackFace;
crackEntity->physicals.push_back(physical);
// duplicate crack vertices
std::map<MVertex *, MVertex*> vxv;
for(std::set<MVertex*>::iterator it = crackVertices.begin();
it != crackVertices.end(); it++){
MVertex *v = *it;
MVertex *newv = new MVertex(v->x(), v->y(), v->z(), crackEntity);
crackEntity->mesh_vertices.push_back(newv);
vxv[v] = newv;
}
// duplicate crack elements
for(unsigned int i = 0; i < crackElements.size(); i++){
MElement *e = crackElements[i];
std::vector<MVertex*> verts;
e->getVertices(verts);
for(unsigned int j = 0; j < verts.size(); j++){
if(vxv.count(verts[j]))
verts[j] = vxv[verts[j]];
}
MElementFactory f;
MElement *newe = f.create(e->getTypeForMSH(), verts, 0, e->getPartition());
if(crackEdge && newe->getType() == TYPE_LIN)
crackEdge->lines.push_back((MLine*)newe);
else if(crackFace && newe->getType() == TYPE_TRI)
crackFace->triangles.push_back((MTriangle*)newe);
else if(crackFace && newe->getType() == TYPE_QUA)
crackFace->quadrangles.push_back((MQuadrangle*)newe);
}
// replace vertices in elements on one side of the crack
std::set<MElement*> eles;
for(std::map<MVertex*, std::vector<MElement*> >::iterator it = vxe.begin();
it != vxe.end(); it++){
for(unsigned int i = 0; i < it->second.size(); i++)
eles.insert(it->second[i]);
}
for(std::set<MElement*>::iterator it = eles.begin(); it != eles.end(); it++){
MElement *e = *it;
for(int i = 0; i < e->getNumVertices(); i++){
if(vxv.count(e->getVertex(i)))
e->setVertex(i, vxv[e->getVertex(i)]);
}
}
CTX::instance()->mesh.changed = ENT_ALL;
return view;
}
// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to the public mailing list <gmsh@geuz.org>.
#ifndef _CRACK_H_
#define _CRACK_H_
#include "Plugin.h"
extern "C"
{
GMSH_Plugin *GMSH_RegisterCrackPlugin();
}
class GMSH_CrackPlugin : public GMSH_PostPlugin
{
public:
GMSH_CrackPlugin(){}
std::string getName() const { return "Crack"; }
std::string getShortHelp() const
{
return "Crack generator";
}
std::string getHelp() const;
int getNbOptions() const;
StringXNumber* getOption(int iopt);
PView *execute(PView *);
};
#endif
......@@ -23,6 +23,7 @@
#include "MathEval.h"
#include "ExtractElements.h"
#include "SimplePartition.h"
#include "Crack.h"
#include "HarmonicToTime.h"
#include "ModulusPhase.h"
#include "Integrate.h"
......@@ -242,6 +243,8 @@ void PluginManager::registerDefaultPlugins()
("NewView", GMSH_RegisterNewViewPlugin()));
allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
("SimplePartition", GMSH_RegisterSimplePartitionPlugin()));
allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
("Crack", GMSH_RegisterCrackPlugin()));
#if defined(HAVE_TETGEN)
allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
("Tetrahedralize", GMSH_RegisterTetrahedralizePlugin()));
......
?: new single-window GUI, with dynamically customizable widget tree; faster
STEP/BRep import; arbitrary size image export; faster 2D Delaunay/Frontal
algorithms; full option viewer/editor; random bug fixes.
2.7.0 (?): new single-window GUI, with dynamically customizable widget tree;
faster STEP/BRep import; arbitrary size image export; faster 2D Delaunay/Frontal
algorithms; full option viewer/editor; many bug fixes.
2.6.1 (July 15, 2012): minor improvements and bug fixes.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment