File: x2.cpp

package info (click to toggle)
gmsh 4.14.0%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 96,556 kB
  • sloc: cpp: 438,695; ansic: 114,912; f90: 15,477; python: 14,025; yacc: 7,333; java: 3,491; lisp: 3,194; lex: 631; perl: 571; makefile: 497; sh: 439; xml: 414; javascript: 113; pascal: 35; modula3: 32
file content (185 lines) | stat: -rw-r--r-- 7,402 bytes parent folder | download | duplicates (3)
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// -----------------------------------------------------------------------------
//
//  Gmsh C++ extended tutorial 2
//
//  Mesh import, discrete entities, hybrid models, terrain meshing
//
// -----------------------------------------------------------------------------

#include <set>
#include <iostream>
#include <gmsh.h>

// The API can be used to import a mesh without reading it from a file, by
// creating nodes and elements on the fly and storing them in model
// entities. These model entities can be existing CAD entities, or can be
// discrete entities, entirely defined by the mesh.
//
// Discrete entities can be reparametrized (see `t13.py') so that they can be
// remeshed later on; and they can also be combined with built-in CAD entities
// to produce hybrid models.
//
// We combine all these features in this tutorial to perform terrain meshing,
// where the terrain is described by a discrete surface (that we then
// reparametrize) combined with a CAD representation of the underground.

int main(int argc, char **argv)
{
  gmsh::initialize();

  gmsh::model::add("x2");

  // We will create the terrain surface mesh from N x N input data points:
  int N = 100;

  // Helper function to return a node tag given two indices i and j:
  auto tag = [N](std::size_t i, std::size_t j) { return (N + 1) * i + j + 1; };

  // The x, y, z coordinates of all the points:
  std::vector<double> coords;

  // The tags of the corresponding nodes:
  std::vector<std::size_t> nodes;

  // The connectivities of the triangle elements (3 node tags per triangle) on
  // the terrain surface:
  std::vector<std::size_t> tris;

  // The connectivities of the line elements on the 4 boundaries (2 node tags
  // for each line element):
  std::vector<std::size_t> lin[4];

  // The connectivities of the point elements on the 4 corners (1 node tag for
  // each point element):
  std::size_t pnt[4] = {tag(0, 0), tag(N, 0), tag(N, N), tag(0, N)};

  for(std::size_t i = 0; i < N + 1; i++) {
    for(std::size_t j = 0; j < N + 1; j++) {
      nodes.push_back(tag(i, j));
      coords.insert(coords.end(), {(double)i / N, (double)j / N,
                                   0.05 * sin(10 * (double)(i + j) / N)});
      if(i > 0 && j > 0) {
        tris.insert(tris.end(),
                    {tag(i - 1, j - 1), tag(i, j - 1), tag(i - 1, j)});
        tris.insert(tris.end(), {tag(i, j - 1), tag(i, j), tag(i - 1, j)});
      }
      if((i == 0 || i == N) && j > 0) {
        std::size_t s = (i == 0) ? 3 : 1;
        lin[s].insert(lin[s].end(), {tag(i, j - 1), tag(i, j)});
      }
      if((j == 0 || j == N) && i > 0) {
        std::size_t s = (j == 0) ? 0 : 2;
        lin[s].insert(lin[s].end(), {tag(i - 1, j), tag(i, j)});
      }
    }
  }

  // Create 4 discrete points for the 4 corners of the terrain surface:
  for(int i = 0; i < 4; i++) gmsh::model::addDiscreteEntity(0, i + 1);
  gmsh::model::setCoordinates(1, 0, 0, coords[3 * tag(0, 0) - 1]);
  gmsh::model::setCoordinates(2, 1, 0, coords[3 * tag(N, 0) - 1]);
  gmsh::model::setCoordinates(3, 1, 1, coords[3 * tag(N, N) - 1]);
  gmsh::model::setCoordinates(4, 0, 1, coords[3 * tag(0, N) - 1]);

  // Create 4 discrete bounding curves, with their boundary points:
  for(int i = 0; i < 4; i++)
    gmsh::model::addDiscreteEntity(1, i + 1, {i + 1, (i < 3) ? (i + 2) : 1});

  // Create one discrete surface, with its bounding curves:
  gmsh::model::addDiscreteEntity(2, 1, {1, 2, -3, -4});

  // Add all the nodes on the surface (for simplicity... see below):
  gmsh::model::mesh::addNodes(2, 1, nodes, coords);

  // Add point elements on the 4 points, line elements on the 4 curves, and
  // triangle elements on the surface:
  for(int i = 0; i < 4; i++) {
    // Type 15 for point elements:
    gmsh::model::mesh::addElementsByType(i + 1, 15, {}, {pnt[i]});
    // Type 1 for 2-node line elements:
    gmsh::model::mesh::addElementsByType(i + 1, 1, {}, lin[i]);
  }
  // Type 2 for 3-node triangle elements:
  gmsh::model::mesh::addElementsByType(1, 2, {}, tris);

  // Reclassify the nodes on the curves and the points (since we put them all on
  // the surface before with `addNodes' for simplicity)
  gmsh::model::mesh::reclassifyNodes();

  // Create a geometry for the discrete curves and surfaces, so that we can
  // remesh them later on:
  gmsh::model::mesh::createGeometry();

  // Note that for more complicated meshes, e.g. for on input unstructured STL
  // mesh, we could use `classifySurfaces()' to automatically create the
  // discrete entities and the topology; but we would then have to extract the
  // boundaries afterwards.

  // Create other CAD entities to form one volume below the terrain surface.
  // Beware that only built-in CAD entities can be hybrid, i.e. have discrete
  // entities on their boundary: OpenCASCADE does not support this feature.
  int p1 = gmsh::model::geo::addPoint(0, 0, -0.5);
  int p2 = gmsh::model::geo::addPoint(1, 0, -0.5);
  int p3 = gmsh::model::geo::addPoint(1, 1, -0.5);
  int p4 = gmsh::model::geo::addPoint(0, 1, -0.5);
  int c1 = gmsh::model::geo::addLine(p1, p2);
  int c2 = gmsh::model::geo::addLine(p2, p3);
  int c3 = gmsh::model::geo::addLine(p3, p4);
  int c4 = gmsh::model::geo::addLine(p4, p1);
  int c10 = gmsh::model::geo::addLine(p1, 1);
  int c11 = gmsh::model::geo::addLine(p2, 2);
  int c12 = gmsh::model::geo::addLine(p3, 3);
  int c13 = gmsh::model::geo::addLine(p4, 4);
  int ll1 = gmsh::model::geo::addCurveLoop({c1, c2, c3, c4});
  int s1 = gmsh::model::geo::addPlaneSurface({ll1});
  int ll3 = gmsh::model::geo::addCurveLoop({c1, c11, -1, -c10});
  int s3 = gmsh::model::geo::addPlaneSurface({ll3});
  int ll4 = gmsh::model::geo::addCurveLoop({c2, c12, -2, -c11});
  int s4 = gmsh::model::geo::addPlaneSurface({ll4});
  int ll5 = gmsh::model::geo::addCurveLoop({c3, c13, 3, -c12});
  int s5 = gmsh::model::geo::addPlaneSurface({ll5});
  int ll6 = gmsh::model::geo::addCurveLoop({c4, c10, 4, -c13});
  int s6 = gmsh::model::geo::addPlaneSurface({ll6});
  int sl1 = gmsh::model::geo::addSurfaceLoop({s1, s3, s4, s5, s6, 1});
  int v1 = gmsh::model::geo::addVolume({sl1});
  gmsh::model::geo::synchronize();

  // Set this to true to build a fully hex mesh:
  bool transfinite = false;
  bool transfiniteAuto = false;

  if(transfinite) {
    int NN = 30;
    std::vector<std::pair<int, int> > tmp;
    gmsh::model::getEntities(tmp, 1);
    for(auto c : tmp) { gmsh::model::mesh::setTransfiniteCurve(c.second, NN); }
    gmsh::model::getEntities(tmp, 2);
    for(auto s : tmp) {
      gmsh::model::mesh::setTransfiniteSurface(s.second);
      gmsh::model::mesh::setRecombine(s.first, s.second);
      gmsh::model::mesh::setSmoothing(s.first, s.second, 100);
    }
    gmsh::model::mesh::setTransfiniteVolume(v1);
  }
  else if(transfiniteAuto) {
    gmsh::option::setNumber("Mesh.MeshSizeMin", 0.5);
    gmsh::option::setNumber("Mesh.MeshSizeMax", 0.5);
    // setTransfiniteAutomatic() uses the sizing constraints to set the number
    // of points
    gmsh::model::mesh::setTransfiniteAutomatic();
  }
  else {
    gmsh::option::setNumber("Mesh.MeshSizeMin", 0.05);
    gmsh::option::setNumber("Mesh.MeshSizeMax", 0.05);
  }

  gmsh::model::mesh::generate(3);
  gmsh::write("x2.msh");

  // Launch the GUI to see the results:
  std::set<std::string> args(argv, argv + argc);
  if(!args.count("-nopopup")) gmsh::fltk::run();

  gmsh::finalize();
  return 0;
}