Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
19051 commits behind the upstream repository.
3D_Mesh_Netgen.cpp 6.10 KiB
// $Id: 3D_Mesh_Netgen.cpp,v 1.6 2004-06-28 20:36:14 geuzaine Exp $
//
// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
// 
// Please report all bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
//   Nicolas Tardieu
//

#include "Gmsh.h"
#include "Mesh.h"
#include "Numeric.h"
#include "Context.h"

extern Context_T CTX;
extern Mesh *THEM;

#if !defined(HAVE_NETGEN)

int Mesh_Netgen(Volume * v)
{
  if(CTX.mesh.algo3d == FRONTAL_NETGEN)
    Msg(GERROR, "Netgen is not compiled in this version of Gmsh");
  return 0;
}

void Optimize_Netgen(Volume * v)
{
  Msg(GERROR, "Netgen is not compiled in this version of Gmsh");
}

#else

#include "nglib.h"
#include "nglib_addon.h"

class Netgen{
 private:
  List_T *_vertices;
  Volume *_vol;
  Ng_Mesh *_ngmesh;
 public:
  Netgen(Volume *vol, int importVolumeMesh = 0);
  Netgen(Surface *s, int importSurfaceMesh = 0);
  ~Netgen();
  void MeshVolume();
  void OptimizeVolume();
};

Netgen::Netgen(Volume *vol, int importVolumeMesh)
  : _vol(vol)
{
  // creates Netgen mesh structure
  Ng_Init();
  _ngmesh = Ng_NewMesh();

  if(importVolumeMesh){
    _vertices = Tree2List(_vol->Vertices);
  }
  else{
    // Transfer all surface vertices we must *not* add 2 times the
    // same vertex (the same vertex can belong to several surfaces)
    Tree_T *tree = Tree_Create(sizeof(Vertex*), compareVertex);
    for(int i = 0; i < List_Nbr(_vol->Surfaces); i++) {
      Surface *s;
      List_Read(_vol->Surfaces, i, &s);
      Tree_Unit(tree, s->Vertices);
    }
    _vertices = Tree2List(tree);
  }
  List_Sort(_vertices, compareVertex);

  // Transfer the vertices
  for(int i = 0; i < List_Nbr(_vertices); i++){
    Vertex *v;
    List_Read(_vertices, i, &v);
    double tmp[3];
    tmp[0] = v->Pos.X;
    tmp[1] = v->Pos.Y;
    tmp[2] = v->Pos.Z;
    Ng_AddPoint(_ngmesh, tmp);
  }

  // Transfert all surface simplices
  for(int i = 0; i < List_Nbr(_vol->Surfaces); i++) {
    Surface *s;
    List_Read(_vol->Surfaces, i, &s);
    int sign;
    List_Read(_vol->SurfacesOrientations, i, &sign);
    List_T *simplist = Tree2List(s->Simplexes);
    for(int j = 0; j < List_Nbr(simplist); j++) {
      Simplex *simp;
      List_Read(simplist, j, &simp);
      int tmp[3], index[3];
      if(sign > 0){
	index[0] = 0;
	index[1] = 1;
	index[2] = 2;
      }
      else{
	index[0] = 0;
	index[1] = 2;
	index[2] = 1;
      }
      tmp[0] = 1 + List_ISearch(_vertices, &simp->V[index[0]], compareVertex);
      tmp[1] = 1 + List_ISearch(_vertices, &simp->V[index[1]], compareVertex);
      tmp[2] = 1 + List_ISearch(_vertices, &simp->V[index[2]], compareVertex);
      Ng_AddSurfaceElement(_ngmesh, NG_TRIG, tmp);
    }
    List_Delete(simplist);
  }
  
  // Transfer the volume elements
  if(importVolumeMesh){
    List_T *simplist = Tree2List(_vol->Simplexes);
    for(int i = 0; i < List_Nbr(simplist); i++) {
      Simplex *simp;
      List_Read(simplist, i, &simp);
      int tmp[4];
      tmp[0] = 1 + List_ISearch(_vertices, &simp->V[0], compareVertex);
      tmp[1] = 1 + List_ISearch(_vertices, &simp->V[1], compareVertex);
      tmp[2] = 1 + List_ISearch(_vertices, &simp->V[2], compareVertex);
      tmp[3] = 1 + List_ISearch(_vertices, &simp->V[3], compareVertex);
      Ng_AddVolumeElement(_ngmesh, NG_TET, tmp);
    }
    List_Delete(simplist);    
  }
}

Netgen::Netgen(Surface *sur, int importSurfaceMesh)
{
  // todo
}

Netgen::~Netgen()
{
  List_Delete(_vertices);
  Ng_DeleteMesh(_ngmesh);
  Ng_Exit();
}

void Netgen::MeshVolume()
{
  Ng_Meshing_Parameters mp;
  mp.maxh = 1;
  mp.fineness = 1;
  mp.secondorder = 0;
  Ng_GenerateVolumeMesh(_ngmesh, &mp);

  // Gets total number of vertices of Netgen's mesh
  int nbv = Ng_GetNP(_ngmesh);
  Vertex **vtable = (Vertex **)Malloc(nbv * sizeof(Vertex*));
  
  // Get existing vertices
  for(int i = 0; i < List_Nbr(_vertices); i++){
    List_Read(_vertices, i, &vtable[i]);
    Tree_Insert(_vol->Vertices, &vtable[i]);
    Tree_Insert(THEM->Vertices, &vtable[i]);
  }

  // Create new volume vertices
  for(int i = List_Nbr(_vertices); i < nbv; i++) {
    double tmp[3];
    Ng_GetPoint(_ngmesh, i+1, tmp);
    vtable[i] = Create_Vertex(++(THEM->MaxPointNum), tmp[0], tmp[1], tmp[2], 1., 0);
    Tree_Add(_vol->Vertices, &vtable[i]);
    Tree_Add(THEM->Vertices, &vtable[i]);
  }

  // Get total number of simplices of Netgen's mesh
  int nbe = Ng_GetNE(_ngmesh);

  // Create new volume simplices
  for(int i = 0; i < nbe; i++) {
    int tmp[4];
    Ng_GetVolumeElement(_ngmesh, i+1, tmp);
    Simplex *simp = Create_Simplex(vtable[tmp[0]-1], vtable[tmp[1]-1],
				   vtable[tmp[2]-1], vtable[tmp[3]-1]);
    simp->iEnt = _vol->Num;
    Tree_Add(_vol->Simplexes, &simp);
  }
  
  Free(vtable);
}

void Netgen::OptimizeVolume()
{
  Ng_Meshing_Parameters mp;
  mp.maxh = 1;
  mp.fineness = 1;
  mp.secondorder = 0;
  // remove the pure volume vertices from THEM->Vertices and v->Vertices
  // remove the tets from THEM->Simplexes
  // reset v->Simplexes
  NgAddOn_OptimizeVolumeMesh(_ngmesh, &mp);
  // transfer vertices and tets back into v and THEM
}

int Mesh_Netgen(Volume * v)
{
  if(CTX.mesh.algo3d != FRONTAL_NETGEN)
    return 0;

  if(THEM->BGM.Typ == ONFILE){
    Msg(GERROR, "Netgen is not ready to be used with a background mesh");
    return 0;
  }

  Msg(STATUS3, "Meshing volume %d", v->Num);
  Netgen ng(v);
  ng.MeshVolume();
  
  return 1;
}

void Optimize_Netgen(Volume * v)
{
  Msg(STATUS3, "Optimizing volume %d", v->Num);
  Netgen ng(v, 1);
  ng.OptimizeVolume();
}

#endif // !HAVE_NETGEN