Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
mbIntxCheck.cpp
Go to the documentation of this file.
1 /*
2  * Usage: MOAB intersection check tool, for intersection on a sphere or in plane
3  *
4  * mpiexec -np n ./mbintx_check -s <source mesh> -t <target mesh> -i <intx mesh> -o <source verif>
5  * -q <target verif>
6  *
7  * after a run with mbtempest in parallel, that computes intersection, we can use this tool to
8  * verify areas of intersection polygons, compared to areas of source, target elements
9  *
10  */
11 
12 #include <iostream>
13 #include <cstdlib>
14 #include <vector>
15 #include <string>
16 #include <sstream>
17 #include <cassert>
18 
19 #include "moab/Core.hpp"
21 #include "moab/ProgOptions.hpp"
22 #include "moab/CpuTimer.hpp"
23 #include "DebugOutput.hpp"
24 
25 #ifdef MOAB_HAVE_MPI
26 // MPI includes
27 #include "moab_mpi.h"
28 #include "moab/ParallelComm.hpp"
29 #include "MBParallelConventions.h"
30 #endif
31 
32 using namespace moab;
33 
34 int main( int argc, char* argv[] )
35 {
36  std::stringstream sstr;
37  // Default area_method = lHuiller; Options: Girard, GaussQuadrature (if TR is available)
39 
40  int rank = 0, size = 1;
41 #ifdef MOAB_HAVE_MPI
42  MPI_Init( &argc, &argv );
43  MPI_Comm_rank( MPI_COMM_WORLD, &rank );
44  MPI_Comm_size( MPI_COMM_WORLD, &size );
45 #endif
46 
47  std::string sourceFile, targetFile, intxFile;
48  std::string source_verif( "outS.h5m" ), target_verif( "outt.h5m" );
49  int sphere = 1;
50  int oldNamesParents = 0;
51  double areaErrSource = -1;
52  double areaErrTarget = -1;
53  ProgOptions opts;
54 
55  opts.addOpt< std::string >( "source,s", "source file ", &sourceFile );
56  opts.addOpt< std::string >( "target,t", "target file ", &targetFile );
57  opts.addOpt< std::string >( "intersection,i", "intersection file ", &intxFile );
58  opts.addOpt< std::string >( "verif_source,v", "output source verification ", &source_verif );
59  opts.addOpt< std::string >( "verif_target,w", "output target verification ", &target_verif );
60  opts.addOpt< double >( "threshold_source,m", "error source threshold ", &areaErrSource );
61  opts.addOpt< double >( "threshold_target,q", "error target threshold ", &areaErrTarget );
62 
63  opts.addOpt< int >( "sphere,p", "mesh on a sphere", &sphere );
64  opts.addOpt< int >( "old_convention,n", "old names for parent tags", &oldNamesParents );
65 
66  opts.parseCommandLine( argc, argv );
67  // load meshes in parallel if needed
68  std::string opts_read = ( size == 1 ? ""
69  : std::string( "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION" ) +
70  std::string( ";PARALLEL_RESOLVE_SHARED_ENTS" ) );
71 
72  // read meshes in 3 file sets
73  ErrorCode rval;
74  Core moab;
75  Interface* mb = &moab; // global
76  EntityHandle sset, tset, ixset;
77 
78  // create meshsets and load files
82  if( 0 == rank ) std::cout << "Loading source file " << sourceFile << "\n";
83  MB_CHK_SET_ERR( mb->load_file( sourceFile.c_str(), &sset, opts_read.c_str() ), "failed reading source file" );
84  if( 0 == rank ) std::cout << "Loading target file " << targetFile << "\n";
85  MB_CHK_SET_ERR( mb->load_file( targetFile.c_str(), &tset, opts_read.c_str() ), "failed reading target file" );
86 
87  if( 0 == rank ) std::cout << "Loading intersection file " << intxFile << "\n";
88  MB_CHK_SET_ERR( mb->load_file( intxFile.c_str(), &ixset, opts_read.c_str() ), "failed reading intersection file" );
89  double R = 1.;
90  if( sphere )
91  {
92  // fix radius of both meshes, to be consistent with radius 1
95  }
96  Range intxCells;
97  MB_CHK_ERR( mb->get_entities_by_dimension( ixset, 2, intxCells ) );
98 
99  Range sourceCells;
100  MB_CHK_ERR( mb->get_entities_by_dimension( sset, 2, sourceCells ) );
101 
102  Range targetCells;
103  MB_CHK_ERR( mb->get_entities_by_dimension( tset, 2, targetCells ) );
104 
105  Tag sourceParentTag;
106  Tag targetParentTag;
107  if( oldNamesParents )
108  {
109  MB_CHK_SET_ERR( mb->tag_get_handle( "RedParent", targetParentTag ), "can't find target parent tag" );
110  MB_CHK_SET_ERR( mb->tag_get_handle( "BlueParent", sourceParentTag ), "can't find source parent tag" );
111  }
112  else
113  {
114  MB_CHK_SET_ERR( mb->tag_get_handle( "TargetParent", targetParentTag ), "can't find target parent tag" );
115  MB_CHK_SET_ERR( mb->tag_get_handle( "SourceParent", sourceParentTag ), "can't find source parent tag" );
116  }
117 
118  // error sets, for better visualization
119  EntityHandle errorSourceSet;
120  MB_CHK_ERR( mb->create_meshset( MESHSET_SET, errorSourceSet ) );
121  EntityHandle errorTargetSet;
122  MB_CHK_ERR( mb->create_meshset( MESHSET_SET, errorTargetSet ) );
123 
124  std::map< int, double > sourceAreas;
125  std::map< int, double > targetAreas;
126 
127  std::map< int, double > sourceAreasIntx;
128  std::map< int, double > targetAreasIntx;
129 
130  std::map< int, int > sourceNbIntx;
131  std::map< int, int > targetNbIntx;
132 
133  std::map< int, EntityHandle > sourceMap;
134  std::map< int, EntityHandle > targetMap;
135 
136  Tag gidTag = mb->globalId_tag();
137 
138  Tag areaTag;
139  MB_CHK_ERR( mb->tag_get_handle( "OrigArea", 1, MB_TYPE_DOUBLE, areaTag, MB_TAG_DENSE | MB_TAG_CREAT ) );
140 
141  moab::IntxAreaUtils areaAdaptor( areaMethod );
142  Range non_convex_intx_cells;
143  for( Range::iterator eit = sourceCells.begin(); eit != sourceCells.end(); ++eit )
144  {
145  EntityHandle cell = *eit;
146  const EntityHandle* verts;
147  int num_nodes;
148  MB_CHK_ERR( mb->get_connectivity( cell, verts, num_nodes ) );
149  if( MB_SUCCESS != rval ) return -1;
150  std::vector< double > coords( 3 * num_nodes );
151  // get coordinates
152  rval = mb->get_coords( verts, num_nodes, &coords[0] );
153  if( MB_SUCCESS != rval ) return -1;
154  double area = areaAdaptor.area_spherical_polygon( &coords[0], num_nodes, R );
155  int sourceID;
156  MB_CHK_ERR( mb->tag_get_data( gidTag, &cell, 1, &sourceID ) );
157  sourceAreas[sourceID] = area;
158  MB_CHK_ERR( mb->tag_set_data( areaTag, &cell, 1, &area ) );
159  sourceMap[sourceID] = cell;
160  }
161  for( Range::iterator eit = targetCells.begin(); eit != targetCells.end(); ++eit )
162  {
163  EntityHandle cell = *eit;
164  const EntityHandle* verts;
165  int num_nodes;
166  MB_CHK_ERR( mb->get_connectivity( cell, verts, num_nodes ) );
167  if( MB_SUCCESS != rval ) return -1;
168  std::vector< double > coords( 3 * num_nodes );
169  // get coordinates
170  rval = mb->get_coords( verts, num_nodes, &coords[0] );
171  if( MB_SUCCESS != rval ) return -1;
172  double area = areaAdaptor.area_spherical_polygon( &coords[0], num_nodes, R );
173  int targetID;
174  MB_CHK_ERR( mb->tag_get_data( gidTag, &cell, 1, &targetID ) );
175  targetAreas[targetID] = area;
176  MB_CHK_ERR( mb->tag_set_data( areaTag, &cell, 1, &area ) );
177  targetMap[targetID] = cell;
178  }
179 
180  for( Range::iterator eit = intxCells.begin(); eit != intxCells.end(); ++eit )
181  {
182  EntityHandle cell = *eit;
183  const EntityHandle* verts;
184  int num_nodes;
185  MB_CHK_ERR( mb->get_connectivity( cell, verts, num_nodes ) );
186  if( MB_SUCCESS != rval ) return -1;
187  std::vector< double > coords( 3 * num_nodes );
188  // get coordinates
189  rval = mb->get_coords( verts, num_nodes, &coords[0] );
190  if( MB_SUCCESS != rval ) return -1;
191  int check_sign = 1;
192  double intx_area = areaAdaptor.area_spherical_polygon( &coords[0], num_nodes, R, &check_sign );
193 
194  MB_CHK_ERR( mb->tag_set_data( areaTag, &cell, 1, &intx_area ) );
195  int sourceID, targetID;
196  MB_CHK_ERR( mb->tag_get_data( sourceParentTag, &cell, 1, &sourceID ) );
197  MB_CHK_ERR( mb->tag_get_data( targetParentTag, &cell, 1, &targetID ) );
198 
199  std::map< int, double >::iterator sit = sourceAreasIntx.find( sourceID );
200  if( sit == sourceAreasIntx.end() )
201  {
202  sourceAreasIntx[sourceID] = intx_area;
203  sourceNbIntx[sourceID] = 1;
204  }
205  else
206  {
207  sourceAreasIntx[sourceID] += intx_area;
208  sourceNbIntx[sourceID]++;
209  }
210 
211  std::map< int, double >::iterator tit = targetAreasIntx.find( targetID );
212  if( tit == targetAreasIntx.end() )
213  {
214  targetAreasIntx[targetID] = intx_area;
215  targetNbIntx[targetID] = 1;
216  }
217  else
218  {
219  targetAreasIntx[targetID] += intx_area;
220  targetNbIntx[targetID]++;
221  }
222  if( intx_area < 0 )
223  {
224  std::cout << "negative intx area: " << intx_area << " n:" << num_nodes << " parents: " << sourceID << " "
225  << targetID << "\n";
226  }
227  if( check_sign < 0 )
228  {
229  non_convex_intx_cells.insert( cell );
230  std::cout << " non-convex polygon: " << intx_area << " n:" << num_nodes << " parents: " << sourceID << " "
231  << targetID << "\n";
232  }
233  }
234  Tag diffTag;
235  MB_CHK_ERR( mb->tag_get_handle( "AreaDiff", 1, MB_TYPE_DOUBLE, diffTag, MB_TAG_DENSE | MB_TAG_CREAT ) );
236 
237  Tag countIntxCellsTag;
238  MB_CHK_ERR( mb->tag_get_handle( "CountIntx", 1, MB_TYPE_INTEGER, countIntxCellsTag, MB_TAG_DENSE | MB_TAG_CREAT ) );
239 
240  for( Range::iterator eit = sourceCells.begin(); eit != sourceCells.end(); ++eit )
241  {
242  EntityHandle cell = *eit;
243 
244  int sourceID;
245  MB_CHK_ERR( mb->tag_get_data( gidTag, &cell, 1, &sourceID ) );
246  double areaDiff = sourceAreas[sourceID];
247  std::map< int, double >::iterator sit = sourceAreasIntx.find( sourceID );
248  int countIntxCells = 0;
249  if( sit != sourceAreasIntx.end() )
250  {
251  areaDiff -= sourceAreasIntx[sourceID];
252  countIntxCells = sourceNbIntx[sourceID];
253  }
254  rval = mb->tag_set_data( diffTag, &cell, 1, &areaDiff );
255  rval = mb->tag_set_data( countIntxCellsTag, &cell, 1, &countIntxCells );
256  // add to errorSourceSet set if needed
257  if( ( areaErrSource > 0 ) && ( fabs( areaDiff ) > areaErrSource ) )
258  {
259  MB_CHK_ERR( mb->add_entities( errorSourceSet, &cell, 1 ) );
260  }
261  }
262  if( 0 == rank ) std::cout << "write source verification file " << source_verif << "\n";
263  MB_CHK_ERR( mb->write_file( source_verif.c_str(), 0, 0, &sset, 1 ) );
264  if( areaErrSource > 0 )
265  {
266  Range sourceErrorCells;
267  MB_CHK_ERR( mb->get_entities_by_handle( errorSourceSet, sourceErrorCells ) );
268  EntityHandle errorSourceIntxSet;
269  MB_CHK_ERR( mb->create_meshset( MESHSET_SET, errorSourceIntxSet ) );
270  if( !sourceErrorCells.empty() )
271  {
272  // add the intx cells that have these as source parent
273  std::vector< int > sourceIDs;
274  sourceIDs.resize( sourceErrorCells.size() );
275  MB_CHK_SET_ERR( mb->tag_get_data( gidTag, sourceErrorCells, &sourceIDs[0] ), "can't get source IDs" );
276  std::sort( sourceIDs.begin(), sourceIDs.end() );
277  for( Range::iterator eit = intxCells.begin(); eit != intxCells.end(); ++eit )
278  {
279  EntityHandle cell = *eit;
280  int sourceID;
281  MB_CHK_ERR( mb->tag_get_data( sourceParentTag, &cell, 1, &sourceID ) );
282  std::vector< int >::iterator j = std::lower_bound( sourceIDs.begin(), sourceIDs.end(), sourceID );
283  if( ( j != sourceIDs.end() ) && ( *j == sourceID ) )
284  {
285  MB_CHK_ERR( mb->add_entities( errorSourceIntxSet, &cell, 1 ) );
286  }
287  }
288  std::string filtersource = std::string( "filt_" ) + source_verif;
289  rval = mb->write_file( filtersource.c_str(), 0, 0, &errorSourceSet, 1 );
290  std::string filterIntxsource = std::string( "filtIntx_" ) + source_verif;
291  rval = mb->write_file( filterIntxsource.c_str(), 0, 0, &errorSourceIntxSet, 1 );
292  }
293  }
294 
295  for( Range::iterator eit = targetCells.begin(); eit != targetCells.end(); ++eit )
296  {
297  EntityHandle cell = *eit;
298 
299  int targetID;
300  MB_CHK_ERR( mb->tag_get_data( gidTag, &cell, 1, &targetID ) );
301  double areaDiff = targetAreas[targetID];
302  int countIntxCells = 0;
303  std::map< int, double >::iterator sit = targetAreasIntx.find( targetID );
304  if( sit != targetAreasIntx.end() )
305  {
306  areaDiff -= targetAreasIntx[targetID];
307  countIntxCells = targetNbIntx[targetID];
308  }
309 
310  rval = mb->tag_set_data( diffTag, &cell, 1, &areaDiff );
311  rval = mb->tag_set_data( countIntxCellsTag, &cell, 1, &countIntxCells );
312  // add to errorTargetSet set if needed
313  if( ( areaErrTarget > 0 ) && ( fabs( areaDiff ) > areaErrTarget ) )
314  {
315  MB_CHK_ERR( mb->add_entities( errorTargetSet, &cell, 1 ) );
316  }
317  }
318  if( 0 == rank ) std::cout << "write target verification file " << target_verif << "\n";
319  MB_CHK_ERR( mb->write_file( target_verif.c_str(), 0, 0, &tset, 1 ) );
320  if( areaErrTarget > 0 )
321  {
322  Range targetErrorCells;
323  MB_CHK_ERR( mb->get_entities_by_handle( errorTargetSet, targetErrorCells ) );
324  if( !targetErrorCells.empty() )
325  {
326  EntityHandle errorTargetIntxSet;
327  MB_CHK_ERR( mb->create_meshset( MESHSET_SET, errorTargetIntxSet ) );
328  // add the intx cells that have these as target parent
329  std::vector< int > targetIDs;
330  targetIDs.resize( targetErrorCells.size() );
331  MB_CHK_SET_ERR( mb->tag_get_data( gidTag, targetErrorCells, &targetIDs[0] ), "can't get target IDs" );
332  std::sort( targetIDs.begin(), targetIDs.end() );
333  for( Range::iterator eit = intxCells.begin(); eit != intxCells.end(); ++eit )
334  {
335  EntityHandle cell = *eit;
336  int targetID;
337  MB_CHK_ERR( mb->tag_get_data( targetParentTag, &cell, 1, &targetID ) );
338  std::vector< int >::iterator j = std::lower_bound( targetIDs.begin(), targetIDs.end(), targetID );
339  if( ( j != targetIDs.end() ) && ( *j == targetID ) )
340  {
341  MB_CHK_ERR( mb->add_entities( errorTargetIntxSet, &cell, 1 ) );
342  }
343  }
344  std::string filterTarget = std::string( "filt_" ) + target_verif;
345  rval = mb->write_file( filterTarget.c_str(), 0, 0, &errorTargetSet, 1 );
346  std::string filterIntxtarget = std::string( "filtIntx_" ) + target_verif;
347  rval = mb->write_file( filterIntxtarget.c_str(), 0, 0, &errorTargetIntxSet, 1 );
348  }
349  }
350 
351  if( !non_convex_intx_cells.empty() )
352  {
353 
354  sourceCells.clear();
355  targetCells.clear();
356  for( Range::iterator it = non_convex_intx_cells.begin(); it != non_convex_intx_cells.end(); it++ )
357  {
358  EntityHandle cellIntx = *it;
359  int sourceID, targetID;
360  MB_CHK_ERR( mb->tag_get_data( sourceParentTag, &cellIntx, 1, &sourceID ) );
361  MB_CHK_ERR( mb->tag_get_data( targetParentTag, &cellIntx, 1, &targetID ) );
362  sourceCells.insert( sourceMap[sourceID] );
363  targetCells.insert( targetMap[targetID] );
364  }
365  EntityHandle nonConvexSet;
366  MB_CHK_ERR( mb->create_meshset( MESHSET_SET, nonConvexSet ) );
367  rval = mb->add_entities( nonConvexSet, non_convex_intx_cells );
368  MB_CHK_ERR( mb->write_file( "nonConvex.h5m", 0, 0, &nonConvexSet, 1 ) );
369 
370  EntityHandle sSet;
372  rval = mb->add_entities( sSet, sourceCells );
373  MB_CHK_ERR( mb->write_file( "nonConvexSource.h5m", 0, 0, &sSet, 1 ) );
374  EntityHandle tSet;
376  rval = mb->add_entities( tSet, targetCells );
377  MB_CHK_ERR( mb->write_file( "nonConvexTarget.h5m", 0, 0, &tSet, 1 ) );
378  rval = mb->add_entities( nonConvexSet, sourceCells );
379  rval = mb->add_entities( nonConvexSet, targetCells );
380  MB_CHK_ERR( mb->write_file( "nonConvexAll.h5m", 0, 0, &nonConvexSet, 1 ) );
381  }
382  return 0;
383 }