Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
mbex4.cpp
Go to the documentation of this file.
1 /** @example mbex4.cpp
2  * \brief beginner tutorial, example 4: Demonstrates creating a structured mesh
3  *
4  * In this example, we create a 2x2x2 mesh that is identical to the
5  * previous example. However, in this case we will use the structured
6  * mesh interface since the mesh we created is logically
7  * structured. There are many advantages to using the structured mesh
8  * interface...such as memory savings, speed, ease-of-use...
9  *
10  * \author Milad Fatenejad
11  */
12 
13 // The moab/Core.hpp header file is needed for all MOAB work...
14 #include "moab/Core.hpp"
15 
16 // The moab/ScdInterface.hpp contains code which defines the moab
17 // structured mesh interface
18 #include "moab/ScdInterface.hpp"
19 
20 #include <iostream>
21 #include <cmath>
22 
23 // ****************
24 // * *
25 // * main *
26 // * *
27 // ****************
28 int main()
29 {
30  moab::ErrorCode rval;
31  moab::Core mbint;
32 
33  // ***********************
34  // * Create the Mesh *
35  // ***********************
36 
37  // First, lets make the mesh. It will be a 100 by 100 uniform grid
38  // (there will be 100x100 quads, 101x101 vertexes) with dx = dy =
39  // 0.1. Unlike the previous example, we will first make the mesh,
40  // then set the coordinates one at a time.
41 
42  const unsigned NI = 100;
43  const unsigned NJ = 100;
44 
45  // moab::ScdInterface is the structured mesh interface class for
46  // MOAB.
47  moab::ScdInterface* scdint;
48 
49  // Tell MOAB that our mesh is structured:
50  MB_CHK_SET_ERR( mbint.query_interface( scdint ), "mbint.query_interface failed" );
51 
52  // Create the mesh:
53  moab::ScdBox* scdbox = NULL;
54  MB_CHK_SET_ERR( scdint->construct_box( moab::HomCoord( 0, 0, 0 ), moab::HomCoord( NI, NJ, 0 ), NULL, 0, scdbox ),
55  "scdint->construct_box failed" );
56 
57  // MOAB knows to make quads instead of hexes because the last start
58  // and end indexes are the same (0). Note that it is still a "3D"
59  // mesh because each vertex coordinate is still defined using three
60  // numbers although every element in the mesh is a quadrilateral.
61 
62  // ******************************
63  // * Set Vertex Coordinates *
64  // ******************************
65 
66  // The "NULL" and "0" arguments in the call to construct_box are
67  // where we could specify the vertex coordinates. Since we didn't
68  // give any coordinates, every vertex is given a position of 0,0,0
69  // by default. Now we will set the vertex coordinates...
70 
71  const double DX = 0.1;
72  const double DY = 0.1;
73 
74  for( unsigned i = 0; i < NI + 1; i++ )
75  for( unsigned j = 0; j < NJ + 1; j++ )
76  {
77  // First, get the entity handle:
78  moab::EntityHandle handle = scdbox->get_vertex( i, j );
79 
80  // Compute the coordinate:
81  double coord[3] = { DX * i, DY * j, 0.0 };
82 
83  // Change the coordinate of the vertex:
84  mbint.set_coords( &handle, 1, coord );
85  }
86 
87  // *******************
88  // * Attach Tags *
89  // *******************
90 
91  // The vertex coordinates have been defined, now let's attach some
92  // data to the mesh. In MOAB this is done using "tags". Tags are
93  // little bits of information that can be attached to any mesh
94  // entity. In our example, we want to create two tags. The
95  // "temperature" tag will be attached to each quad and will be 1
96  // double. The "velocity" tag will be attached to each vertex and
97  // will be an array of two doubles.
98 
99  // zero and twozeros represent the initial tag
100 
101  // Create the tags:
102  moab::Tag temp_tag;
103  double temp_default_value = 0.0;
104  rval = mbint.tag_get_handle( "temperature", 1, moab::MB_TYPE_DOUBLE, temp_tag,
105  moab::MB_TAG_DENSE | moab::MB_TAG_CREAT, &temp_default_value );MB_CHK_SET_ERR( rval, "mbint.tag_get_handle(temperature) failed" );
106 
107  moab::Tag vel_tag;
108  double vel_default_value[2] = { 0.0, 0.0 };
109  rval = mbint.tag_get_handle( "velocity", 2, moab::MB_TYPE_DOUBLE, vel_tag, moab::MB_TAG_DENSE | moab::MB_TAG_CREAT,
110  vel_default_value );MB_CHK_SET_ERR( rval, "mbint.tag_get_handle(velocity) failed" );
111 
112  // Note that when we created each tag, we specified two flags:
113  //
114  // The moab::MB_TAG_DENSE flag tells MOAB that this is a dense
115  // tag. Dense tags will get automatically assigned to entities which
116  // have continuous handles. For this example, this means that once
117  // we set a tag on one vertex, memory will be allocated for
118  // assigning the tag to all vertexes. The same is true of
119  // quads. Dense tags are much more efficient when assigning tags to
120  // lots of entities. If you only want to assign a tag to a few
121  // entities, it is more efficient to use sparse tags
122  // (moab::MB_TAG_SPARSE).
123  //
124  // The moab::MB_TAG_CREAT flag tells MOAB to create the tag if it
125  // doesn't already exist.
126 
127  // The tags have now been created, now we have to attach them to
128  // entities and set their values. NOTE: I am going to do this in a
129  // manner which emphasizes clarity - this is not the most efficient
130  // approach - that will be saved for later tutorial examples.
131 
132  // Loop through each quad and set the temperature:
133  for( unsigned i = 0; i < NI; i++ )
134  for( unsigned j = 0; j < NJ; j++ )
135  {
136  // Get the handle for this quad:
137  moab::EntityHandle handle = scdbox->get_element( i, j );
138 
139  // Compute the temperature...
140  double xc = DX * ( i + 0.5 );
141  double yc = DY * ( j + 0.5 );
142  double r = std::sqrt( xc * xc + yc * yc );
143  double temperature = std::exp( -0.5 * r );
144 
145  // Set the temperature on a single quad:
146  MB_CHK_SET_ERR( mbint.tag_set_data( temp_tag, &handle, 1, &temperature ),
147  "mbint.tag_set_data(temp_tag) failed" );
148  }
149 
150  // Loop through each vertex and set the velocity:
151  for( unsigned i = 0; i < NI + 1; i++ )
152  for( unsigned j = 0; j < NJ + 1; j++ )
153  {
154  // Get the handle for this vertex:
155  moab::EntityHandle handle = scdbox->get_vertex( i, j );
156  double velocity[2] = { i, j };
157 
158  // Set the velocity on a vertex:
159  MB_CHK_SET_ERR( mbint.tag_set_data( vel_tag, &handle, 1, velocity ), "mbint.tag_set_data(vel_tag) failed" );
160  }
161 
162  // ***************************
163  // * Write Mesh to Files *
164  // ***************************
165 
166  // NOTE: Some visualization software (such as VisIt) may not
167  // interpret the velocity tag as a vector and you may not be able to
168  // plot it. But you should be able to plot the temperature on top of
169  // the mesh.
170 
171  MB_CHK_SET_ERR( mbint.write_file( "mbex4.vtk" ), "write_file(mbex4.vtk) failed" );
172 
173  return 0;
174 }