Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
addConnec.cpp
Go to the documentation of this file.
1 /**
2  * @file addConnec.cpp
3  * @brief Example demonstrating addition of connectivity to point cloud data for visualization
4  *
5  * This example shows how to:
6  * - Load point cloud data from H5M files
7  * - Match vertices between different meshes using global IDs
8  * - Add 2D cell connectivity to point cloud data
9  * - Create new mesh files with enhanced connectivity
10  * - Handle different element types (triangles, quads, polygons)
11  * - Write enhanced meshes for better visualization
12  *
13  * This tool is useful for converting point cloud data into
14  * connected meshes for better visualization in tools like VisIt.
15  *
16  * @author MOAB Development Team
17  * @date 2024
18  *
19 
20  * this tool will take an existing h5m fine point cloud data (phys grid or land pc)
21  * and add 2d cells from a fine atm mesh
22  *
23  * example of usage:
24  * ./addConnec -i wholeFineATM.h5m -s wholeLND_proj01.h5m -o wholeLndM.h5m
25  *
26  * Basically, will output a new h5m file (wholeLndM.h5m), which has also cell connectivity copied from fine atm
27  * matching is based on the global ids
28  * between what we think is the order on the original file (wholeFineATM.h5m)
29  *
30  * file wholeFineATM.h5m is obtained from a coupled run in e3sm, with the ne 11, np 4,
31  *
32  * @param argc Number of command line arguments
33  * @param argv Command line arguments array
34  * @return 0 on success, 1 on failure
35  */
36 #include "moab/ProgOptions.hpp"
37 #include "moab/Core.hpp"
38 
39 #include <cmath>
40 #include <sstream>
41 
42 using namespace moab;
43 
44 int main( int argc, char* argv[] )
45 {
46 
47  ProgOptions opts;
48 
49  std::string inputfile, outfile( "out.h5m" ), sourcefile;
50 
51  opts.addOpt< std::string >( "input,i", "input mesh filename", &inputfile );
52  opts.addOpt< std::string >( "source,s", "h5m file aligned with the mesh input file", &sourcefile );
53  opts.addOpt< std::string >( "output,o", "output mesh filename", &outfile );
54 
55  opts.parseCommandLine( argc, argv );
56 
57  std::cout << "input mesh file: " << inputfile << "\n";
58  std::cout << "source file: " << sourcefile << "\n";
59  std::cout << "output file: " << outfile << "\n";
60 
61  if( inputfile.empty() )
62  {
63  opts.printHelp();
64  return 0;
65  }
66  ErrorCode rval;
67  Core* mb = new Core();
68 
69  MB_CHK_SET_ERR( mb->load_file( inputfile.c_str() ), "can't load input file" );
70 
71  Core* mb2 = new Core();
72  MB_CHK_SET_ERR( mb2->load_file( sourcefile.c_str() ), "can't load source file" );
73 
74  // get vertices on ini mesh; get global id on ini mesh
75  // get global id on source mesh
76  Tag gid;
77  Tag gid2;
78  MB_CHK_SET_ERR( mb->tag_get_handle( "GLOBAL_ID", gid ), "can't get GLOBAL_ID tag on ini mesh " );
79  MB_CHK_SET_ERR( mb2->tag_get_handle( "GLOBAL_ID", gid2 ), "can't get GLOBAL_ID tag on source mesh " );
80 
81  // get vertices on ini mesh; build
82  Range iniVerts;
83  MB_CHK_SET_ERR( mb->get_entities_by_dimension( 0, 0, iniVerts ), "can't get verts on initial mesh " );
84 
85  std::vector< int > gids;
86  gids.resize( iniVerts.size() );
87  MB_CHK_SET_ERR( mb->tag_get_data( gid, iniVerts, &( gids[0] ) ), "can't get gid on initial verts " );
88  // build now the map
89  std::map< int, EntityHandle > fromGidToEh;
90  int i = 0;
91  for( Range::iterator vit = iniVerts.begin(); vit != iniVerts.end(); ++vit, i++ )
92  {
93  fromGidToEh[gids[i]] = *vit;
94  }
95  // now get the source verts, and tags, and set it on new mesh
96 
97  Range sourceVerts;
98  MB_CHK_SET_ERR( mb2->get_entities_by_dimension( 0, 0, sourceVerts ), "can't get verts on source mesh " );
99  std::vector< int > gids2;
100  gids2.resize( sourceVerts.size() );
101  MB_CHK_SET_ERR( mb2->tag_get_data( gid2, sourceVerts, &( gids2[0] ) ), "can't get gid2 on cloud mesh " );
102  std::map< int, EntityHandle > fromGid2ToEh;
103  i = 0;
104  for( Range::iterator vit = sourceVerts.begin(); vit != sourceVerts.end(); ++vit, i++ )
105  {
106  fromGid2ToEh[gids2[i]] = *vit;
107  }
108 
109  Range usedVerts;
110  for( size_t i = 0; i < gids2.size(); i++ )
111  {
112  int globalId = gids2[i];
113  EntityHandle usedVert = fromGidToEh[globalId];
114  usedVerts.insert( usedVert );
115  }
116  Range cells;
117  MB_CHK_SET_ERR( mb->get_adjacencies( usedVerts, 2, false, cells, Interface::UNION ), "can't get adj cells " );
118 
119  // now create a new cell in mb2 for each one in mb
120  for( Range::iterator cit = cells.begin(); cit != cells.end(); ++cit )
121  {
122  EntityHandle cell = *cit;
123  int nnodes = 0;
124  const EntityHandle* conn = NULL;
125  MB_CHK_SET_ERR( mb->get_connectivity( cell, conn, nnodes ), "can't get connectivity " );
126 
127  std::vector< EntityHandle > nconn( nnodes );
128  bool goodCell = true;
129  for( int i = 0; i < nnodes; i++ )
130  {
131  EntityHandle v = conn[i];
132  int index = iniVerts.index( v );
133  if( index < 0 ) goodCell = false;
134  int id = gids[index];
135  if( fromGid2ToEh.find( id ) == fromGid2ToEh.end() )
136  goodCell = false;
137  else
138  nconn[i] = fromGid2ToEh[id];
139  }
140  if( !goodCell ) continue;
141  EntityType type = MBTRI;
142  if( nnodes == 3 )
143  type = MBTRI;
144  else if( nnodes == 4 )
145  type = MBQUAD;
146  else if( nnodes > 4 )
147  type = MBPOLYGON;
148  EntityHandle nel;
149  MB_CHK_SET_ERR( mb2->create_element( type, &nconn[0], nnodes, nel ), "can't create new cell " );
150  }
151  // save file
152  MB_CHK_SET_ERR( mb2->write_file( outfile.c_str() ), "can't write file" );
153 
154  delete mb;
155  delete mb2;
156 
157  return 0;
158 }