A Structured Quadrilateral Mesh Example -- Surface Submapper

The CAMAL surface submapper generates a structured quadrilateral mesh for surfaces that can be broken up into regions with 4 logical sides. These surfaces can have one or more interior loops. The input is the loops of nodes on the boundary of the surface. The outer loop is ordered counter-clockwise and any interior loops are ordered clockwise when viewed from above.. In other words, the surface will be on your left as you walk the loops. CMLSurfSubMapper is used as the meshing object for generating a submapped surface mesh.

Figure 12 shows an example surface that is submappable. The nodes on the boundary of the surface are used as input to the surface submapper. As shown in Figure 12, the outer loop is ordered counter-clockwise when viewed from a position down the positive normal of the surface and the inner loop(s) are ordered clockwise when viewed from the same position.

surfsubmapinput.png

Figure 12: Submapper input

The following code snippets show how the CMLSurfSubMapper object is used to generate a submapped mesh on a surface.

    // read input file
  int     num_points = 0;
  int     num_loops  = 0;
  int    *loop_sizes = NULL; // array allocated in read_loop_file
  double *points     = NULL; // array allocated in read_loop_file
  if (!read_loop_file(num_points, points, num_loops, loop_sizes)) {
    exit(EXIT_FAILURE);
  }

First the input is generated. In this example the input is read from a file. For the surface in Figure 12, the total number of points, num_points, is 24 and the number of loops, num_loops, is 2. The points array holds all of the coordinates of the input points. The size of points is 3 * num_points. The array should be ordered as follows. The first 3 entries in the array will be the x, y, and z coordinates of the first point, the next 3 entries will be the x, y, and z coordinates of the second point, and so on. The loop_sizes array is a num_loops long. It holds the number of points in each loop. For the surface in Figure 12, the first entry in loop_sizes would be 18, and the second entry would be 6.

In this example, the submapper will compute the node types from the loops. Node types are used to find corners and break the surface loops into mappable regions. A node type can be either an end (interior angle of about 90 degrees), a side (interior angle of about 180 degrees), a corner (interior angle of about 270 degrees), or a reversal (interior angle of about 360 degrees). For the surface in Figure 12 nodes 1, 4, 8, 13, and 15 are of type end and nodes 17, 19, 21, 22, and 24 are of type corner. Again, these values will be computed internally.

    // mesh the surface
  int *quads = NULL;
  int new_points = 0;
  int num_quads  = 0;
  if (ret_value) {
    MySurfEval geom_eval;
    CMLSurfSubMapper surf_submapper(&geom_eval);
    ret_value = surf_submapper.set_boundary_mesh(num_points, points, 
                                                 num_loops, loop_sizes);
    if (!ret_value) {
      printf("Failed setting boundary mesh\n");
    }

      // delete memory allocated in read_loop_file
    delete [] points;
    delete [] loop_sizes;
    points = NULL;
    
      // generate the mesh
    if (ret_value) {
      ret_value = surf_submapper.generate_mesh(new_points, num_quads);
      if (!ret_value) {
        printf("Failed generating mesh\n");
      }
    }

The input is sent to CMLSurfSubMapper using the CMLSurfSubMapper::set_boundary_mesh() function. Then the mesh is generated by calling the CMLSurfSubMapper::generate_mesh() function.

      // allocate memory to accept quad mesh and retrieve it
    if (ret_value) {
      quads  = new int [num_quads * 4];
      points = new double [new_points * 3];
      if (quads == NULL || points == NULL) {
        printf("Failed allocating memory to receive mesh\n");
        ret_value = false;
      }
    }
    if (ret_value) {
      ret_value = surf_submapper.get_mesh(new_points, points, 
                                          num_quads, quads);
      if (!ret_value) {
        printf("Failed reading quad mesh\n");
      }

This next part shows how the mesh is retrieved from CMLSurfSubMapper. Memory is allocated for the generated nodes and quads. For the example in Figure 12, new_points is 26 and num_quads is 14. Both of these values are returned during the call to CMLSurfSubMapper::generate_mesh(). The points array will hold the nodal coordinates of the resulting nodes and quads will hold the connectivity of the resulting quads. The format for points will be the same as for the input nodes.

The format for quads will be as follows. The first four entries in quads will be the indices of the nodes making up quad number 1, the second four entries in quads will be the indices of the nodes making up quad number 2, and so on. The node numbering for each quad will be counter-clockwise around the quad when looking from a positive position the surface normal. The nodes and quads are retrieved using the funciton CMLSurfSubMapper::get_mesh().

    // write output file
  if (ret_value) {
    ret_value = write_quad_file(new_points, points, num_quads, quads);
    if (!ret_value) {
      printf("Failed writing quad mesh file\n");
    }
  }

Finally, a call to write_quad_file() writes the quadrilateral mesh to an output file, deletes the allocated memory and exits. Figure 13 shows the resulting mesh for the example in Figure 12.

surfsubmapmesh.png

Figure 13: Submapper output

Other Examples

  1. A Simple Tetrahedral Mesh Example
  2. A Triangle Mesh Example
  3. An Unstructured Quadrilateral Mesh Example
  4. Curve Meshing Examples
  5. A Swept Hexahedral Mesh Example
  6. Another Triangle Mesh Example
  7. A Structured Quadrilateral Mesh Example -- Surface Mapper
  8. A Structured Hexahedral Mesh Example -- Volume Mapper

CAMAL 5.2-0 documentation created on 1 Jun 2010
Comments to csimsoft.com