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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
// -----------------------------------------------------------------------------
//
// Gmsh C tutorial 2
//
// Transformations, extruded geometries, volumes
//
// -----------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gmshc.h>
int main(int argc, char **argv)
{
int ierr;
gmshInitialize(argc, argv, 1, 0, &ierr);
gmshModelAdd("t2", &ierr);
// Copied from `t1.c'...
const double lc = 1e-2;
gmshModelGeoAddPoint(0, 0, 0, lc, 1, &ierr);
gmshModelGeoAddPoint(.1, 0, 0, lc, 2, &ierr);
gmshModelGeoAddPoint(.1, .3, 0, lc, 3, &ierr);
gmshModelGeoAddPoint(0, .3, 0, lc, 4, &ierr);
gmshModelGeoAddLine(1, 2, 1, &ierr);
gmshModelGeoAddLine(3, 2, 2, &ierr);
gmshModelGeoAddLine(3, 4, 3, &ierr);
gmshModelGeoAddLine(4, 1, 4, &ierr);
const int cl1[] = {4, 1, -2, 3};
gmshModelGeoAddCurveLoop(cl1, sizeof(cl1) / sizeof(cl1[0]), 1, 0, &ierr);
const int s1[] = {1};
gmshModelGeoAddPlaneSurface(s1, sizeof(s1) / sizeof(s1[0]), 1, &ierr);
gmshModelGeoSynchronize(&ierr);
const int g5[] = {1, 2, 4}, g6[] = {1};
gmshModelAddPhysicalGroup(1, g5, sizeof(g5) / sizeof(g5[0]), 5, "", &ierr);
gmshModelAddPhysicalGroup(2, g6, sizeof(g6) / sizeof(g6[0]), -1, "My surface", &ierr);
// We can then add new points and curves in the same way as we did in
// `t1.c':
gmshModelGeoAddPoint(0, .4, 0, lc, 5, &ierr);
gmshModelGeoAddLine(4, 5, 5, &ierr);
// But Gmsh also provides tools to transform (translate, rotate, etc.)
// elementary entities or copies of elementary entities. Geometrical
// transformations take a vector of pairs of integers as first argument, which
// contains the list of entities, represented by (dimension, tag) pairs. For
// example, the point 5 (dimension=0, tag=5) can be moved by 0.02 to the left
// (dx=-0.02, dy=0, dz=0) with
const int t2[] = {0, 5};
gmshModelGeoTranslate(t2, 2, -0.02, 0, 0, &ierr);
// And it can be further rotated by -Pi/4 around (0, 0.3, 0) (with the
// rotation along the z axis) with:
gmshModelGeoRotate(t2, 2, 0, 0.3, 0, 0, 0, 1, -M_PI / 4, &ierr);
// Note that there are no units in Gmsh: coordinates are just numbers - it's
// up to the user to associate a meaning to them.
// Point 3 can be duplicated and translated by 0.05 along the y axis by using
// the `copy()' function, which takes a vector of (dim, tag) pairs as input,
// and returns another vector of (dim, tag) pairs:
const int iv[] = {0, 3};
int *ov;
size_t ov_n;
gmshModelGeoCopy(iv, 2, &ov, &ov_n, &ierr);
gmshModelGeoTranslate(ov, ov_n, 0, 0.05, 0, &ierr);
// The new point tag is available in ov[0].second, and can be used to create
// new lines:
gmshModelGeoAddLine(3, ov[1], 7, &ierr);
gmshModelGeoAddLine(ov[1], 5, 8, &ierr);
// Output vectors are allocated with `gmshMalloc()' inside the C API, and
// should be freed with `gmshFree()' when not used anymore:
gmshFree(ov);
// Note that in the C API, undesired output values can be ignored by passing a
// NULL pointer. For example, to ignore the error flag, we can pass NULL as
// the last argument:
const int cl2[] = {5, -8, -7, 3};
gmshModelGeoAddCurveLoop(cl2, sizeof(cl2) / sizeof(cl2[0]), 10, 0, NULL);
const int s2[] = {10};
gmshModelGeoAddPlaneSurface(s2, sizeof(s2) / sizeof(s2[0]), 11, &ierr);
// In the same way, we can translate copies of the two surfaces 1 and 11 to
// the right with the following command:
const int iv2[] = {2, 1, 2, 11};
gmshModelGeoCopy(iv2, 4, &ov, &ov_n, &ierr);
gmshModelGeoTranslate(ov, ov_n, 0.12, 0, 0, &ierr);
printf("New surfaces '%d' and '%d'\n", ov[1], ov[3]);
// Volumes are the fourth type of elementary entities in Gmsh. In the same way
// one defines curve loops to build surfaces, one has to define surface loops
// (i.e. `shells') to build volumes. The following volume does not have holes
// and thus consists of a single surface loop:
gmshModelGeoAddPoint(0., 0.3, 0.12, lc, 100, &ierr);
gmshModelGeoAddPoint(0.1, 0.3, 0.12, lc, 101, &ierr);
gmshModelGeoAddPoint(0.1, 0.35, 0.12, lc, 102, &ierr);
// We would like to retrieve the coordinates of point 5 to create point 103,
// so we synchronize the model, and use `getValue()'
gmshModelGeoSynchronize(&ierr);
const double *param;
const size_t param_n = 0;
double *xyz;
size_t xyz_n;
gmshModelGetValue(0, 5, param, param_n, &xyz, &xyz_n, &ierr);
gmshModelGeoAddPoint(xyz[0], xyz[1], 0.12, lc, 103, &ierr);
gmshFree(xyz);
gmshModelGeoAddLine(4, 100, 110, &ierr);
gmshModelGeoAddLine(3, 101, 111, &ierr);
gmshModelGeoAddLine(6, 102, 112, &ierr);
gmshModelGeoAddLine(5, 103, 113, &ierr);
gmshModelGeoAddLine(103, 100, 114, &ierr);
gmshModelGeoAddLine(100, 101, 115, &ierr);
gmshModelGeoAddLine(101, 102, 116, &ierr);
gmshModelGeoAddLine(102, 103, 117, &ierr);
const int cl3[] = {115, -111, 3, 110};
gmshModelGeoAddCurveLoop(cl3, sizeof(cl3) / sizeof(cl3[0]), 118, 0, &ierr);
const int s3[] = {118};
gmshModelGeoAddPlaneSurface(s3, sizeof(s3) / sizeof(s3[0]), 119, &ierr);
const int cl4[] = {111, 116, -112, -7};
gmshModelGeoAddCurveLoop(cl4, sizeof(cl4) / sizeof(cl4[0]), 120, 0, &ierr);
const int s4[] = {120};
gmshModelGeoAddPlaneSurface(s4, sizeof(s4) / sizeof(s4[0]), 121, &ierr);
const int cl5[] = {112, 117, -113, -8};
gmshModelGeoAddCurveLoop(cl5, sizeof(cl5) / sizeof(cl5[0]), 122, 0, &ierr);
const int s5[] = {122};
gmshModelGeoAddPlaneSurface(s5, sizeof(s5) / sizeof(s5[0]), 123, &ierr);
const int cl6[] = {114, -110, 5, 113};
gmshModelGeoAddCurveLoop(cl6, sizeof(cl6) / sizeof(cl6[0]), 124, 0, &ierr);
const int s6[] = {124};
gmshModelGeoAddPlaneSurface(s6, sizeof(s6) / sizeof(s6[0]), 125, &ierr);
const int cl7[] = {115, 116, 117, 114};
gmshModelGeoAddCurveLoop(cl7, sizeof(cl7) / sizeof(cl7[0]), 126, 0, &ierr);
const int s7[] = {126};
gmshModelGeoAddPlaneSurface(s7, sizeof(s7) / sizeof(s7[0]), 127, &ierr);
const int sl1[] = {127, 119, 121, 123, 125, 11};
gmshModelGeoAddSurfaceLoop(sl1, sizeof(sl1) / sizeof(sl1[0]), 128, &ierr);
const int v1[] = {128};
gmshModelGeoAddVolume(v1, sizeof(v1) / sizeof(v1[0]), 129, &ierr);
// When a volume can be extruded from a surface, it is usually easier to use
// the `extrude()' function directly instead of creating all the points,
// curves and surfaces by hand. For example, the following command extrudes
// the surface 11 along the z axis and automatically creates a new volume (as
// well as all the needed points, curves and surfaces). As expected, the
// function takes a vector of (dim, tag) pairs as input as well as the
// translation vector; since we don't plan to use the output vector of (dim,
// tag) pairs, we pass NULL instead:
const int *numElements;
const size_t numElements_n = 0;
const double *heights;
const size_t heights_n = 0;
const int recombine = 0;
gmshModelGeoExtrude(&(ov[2]), 2, 0.0, 0.0, 0.12, NULL, NULL, numElements,
numElements_n, heights, heights_n, recombine, &ierr);
// Mesh sizes associated to geometrical points can be set by passing a vector
// of (dim, tag) pairs for the corresponding points:
const int ss[] = {0, 103, 0, 105, 0, 109, 0, 102, 0, 28, 0, 24, 0, 6, 0, 5};
gmshModelGeoMeshSetSize(ss, sizeof(ss) / sizeof(ss[0]), lc * 3, &ierr);
// We finish by synchronizing the data from the built-in CAD kernel with the
// Gmsh model:
gmshModelGeoSynchronize(&ierr);
// We group volumes 129 and 130 in a single physical group with tag `1' and
// name "The volume":
const int g7[] = {129, 130};
gmshModelAddPhysicalGroup(3, g7, sizeof(g7) / sizeof(g7[0]), 1, "The volume", &ierr);
// We finally generate and save the mesh:
gmshModelMeshGenerate(3, &ierr);
gmshWrite("t2.msh", &ierr);
// Note that, if the transformation tools are handy to create complex
// geometries, it is also sometimes useful to generate the `flat' geometry,
// with an explicit representation of all the elementary entities.
//
// With the built-in CAD kernel, this can be achieved by saving the model in
// the `Gmsh Unrolled GEO' format:
//
// gmshWrite("t2.geo_unrolled", &ierr);
//
// With the OpenCASCADE CAD kernel, unrolling the geometry can be achieved by
// exporting in the `OpenCASCADE BRep' format:
//
// gmshWrite("t2.brep", &ierr);
//
// (OpenCASCADE geometries can also be exported as STEP files.)
// It is important to note that Gmsh never translates geometry data into a
// common representation: all the operations on a geometrical entity are
// performed natively with the associated CAD kernel. Consequently, one cannot
// export a geometry constructed with the built-in kernel as an OpenCASCADE
// BRep file; or export an OpenCASCADE model as an Unrolled GEO file.
// Launch the GUI to see the results:
int gui = 1;
for(int i = 0; i < argc; i++) {
if(!strcmp(argv[i], "-nopopup")) {
gui = 0;
break;
}
}
if(gui) gmshFltkRun(&ierr);
gmshFinalize(&ierr);
return 0;
}
|