Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
ssn_test.cpp
Go to the documentation of this file.
1 // A test file for Subset Normalization
2 #include "moab/ParallelComm.hpp"
4 #include "moab/Core.hpp"
5 #include "moab/FileOptions.hpp"
6 #include "ReadParallel.hpp"
7 #include "Coupler.hpp"
8 #include "DebugOutput.hpp"
9 #include "ElemUtil.hpp"
10 #include <iostream>
11 #include <iomanip>
12 #include <sstream>
13 #include <cstring>
14 #include <cstdlib>
15 extern "C" {
16 #include "moab/FindPtFuncs.h"
17 }
18 #include "moab/TupleList.hpp"
19 #include "moab/gs.hpp"
20 #include "moab/Types.hpp"
21 #ifndef IS_BUILDING_MB
22 #define IS_BUILDING_MB
23 #include "Internals.hpp"
24 #undef IS_BUILDING_MB
25 #else
26 #include "Internals.hpp"
27 #endif
28 
29 using namespace moab;
30 
31 bool debug = true;
32 
33 // Forward declarations
34 void get_file_options( int argc,
35  char** argv,
36  std::vector< const char* >& filenames,
37  std::string& norm_tag,
38  std::vector< const char* >& tag_names,
39  std::vector< const char* >& tag_values,
40  std::string& file_opts,
41  int* err );
42 
43 void print_tuples( TupleList* tlp );
44 
46  std::vector< std::vector< EntityHandle > >& groups,
47  Tag& norm_hdl,
48  Coupler::IntegType integ_type );
49 
50 double const_field( double x, double y, double z );
51 double field_1( double x, double y, double z );
52 double field_2( double x, double y, double z );
53 double field_3( double x, double y, double z );
54 double physField( double x, double y, double z );
55 
57 int pack_tuples( TupleList* tl, void** ptr );
58 void unpack_tuples( void* ptr, TupleList** tlp );
59 
60 //
61 // Start of main test program
62 //
63 int main( int argc, char** argv )
64 {
65  // need to init MPI first, to tell how many procs and rank
66  // Used since Coupler is a parallel code. The Coupler may be run
67  // in parallel or serial mode but will need MPI either way.
68  int err = MPI_Init( &argc, &argv );
69 
70  // Print usage if not enough arguments
71  if( argc < 3 )
72  {
73  std::cerr << "Usage: ";
74  std::cerr << argv[0] << " <nfiles> <fname1> ... <fnamen> <norm_tag> <tag_select_opts> <file_opts>" << std::endl;
75  std::cerr << "nfiles : number of mesh files" << std::endl;
76  std::cerr << "fname1...fnamen : mesh files" << std::endl;
77  std::cerr << "norm_tag : name of tag to normalize across meshes" << std::endl;
78  std::cerr << "tag_select_opts : quoted string of tags and values for subset selection, "
79  "e.g. \"TAG1=VAL1;TAG2=VAL2;TAG3;TAG4\""
80  << std::endl;
81  std::cerr << "file_opts : quoted string of parallel file read options, e.g. "
82  "\"OPTION1=VALUE1;OPTION2;OPTION3=VALUE3\""
83  << std::endl;
84 
86  MB_CHK_SET_ERR( (ErrorCode)err, "Integrate scalar field test failed" );
87 
88  err = MPI_Finalize();
89 
90  return err;
91  }
92 
93  int nprocs, rank;
94  err = MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
95  assert( MPI_SUCCESS == err );
96  err = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
97  assert( MPI_SUCCESS == err );
98 
99  // Create an ofstream to write output. One file each for each proc.
100  std::stringstream fname;
101  fname << argv[0] << rank << ".out";
102  if( !std::freopen( fname.str().c_str(), "a", stdout ) ) return -1;
103  if( !std::freopen( fname.str().c_str(), "a", stderr ) ) return -1;
104 
105  // Create the moab instance
106  Interface* mbi = new Core();
107  if( NULL == mbi )
108  {
109  std::cerr << "MOAB constructor failed" << std::endl;
110  return 1;
111  }
112 
113  // Get the input options
114  std::cout << "Getting options..." << std::endl;
115  std::vector< const char* > filenames;
116  std::vector< const char* > tagNames;
117  std::vector< const char* > tagValues;
118  std::string normTag, fileOpts;
119  get_file_options( argc, argv, filenames, normTag, tagNames, tagValues, fileOpts, &err );
120  MB_CHK_SET_ERR( (ErrorCode)err, "get_file_options failed" );
121 
122  // Print out the input parameters
123  std::cout << " Input Parameters - " << std::endl;
124  std::cout << " Filenames: ";
125  for( std::vector< const char* >::iterator it = filenames.begin(); it != filenames.end(); ++it )
126  std::cout << *it << " ";
127  std::cout << std::endl;
128  std::cout << " Norm Tag: " << normTag << std::endl;
129  std::cout << " Selection Data: NumNames=" << tagNames.size() << " NumValues=" << tagValues.size() << std::endl;
130  std::cout << " TagNames TagValues " << std::endl;
131  std::cout << " -------------------- --------------------" << std::endl;
132  std::vector< const char* >::iterator nameIt = tagNames.begin();
133  std::vector< const char* >::iterator valIt = tagValues.begin();
134  std::cout << std::setiosflags( std::ios::left );
135  for( ; nameIt != tagNames.end(); ++nameIt )
136  {
137  std::cout << " " << std::setw( 20 ) << *nameIt;
138  if( *valIt != 0 )
139  {
140  std::cout << " " << std::setw( 20 ) << *( (int*)( *valIt ) ) << std::endl;
141  ++valIt;
142  }
143  else
144  std::cout << " NULL " << std::endl;
145  }
146  std::cout << std::resetiosflags( std::ios::left );
147  std::cout << " File Options: " << fileOpts << std::endl;
148 
149  // Read in mesh(es)
150  std::cout << "Reading mesh file(s)..." << std::endl;
151  std::vector< ParallelComm* > pcs( filenames.size() );
152  std::vector< ReadParallel* > rps( filenames.size() );
153 
154  // allocate root sets for each mesh for moab
155  std::vector< EntityHandle > roots( filenames.size() );
156 
157  ErrorCode result;
158  for( unsigned int i = 0; i < filenames.size(); i++ )
159  {
160  pcs[i] = new ParallelComm( mbi, MPI_COMM_WORLD );
161  rps[i] = new ReadParallel( mbi, pcs[i] );
162 
163  result = mbi->create_meshset( MESHSET_SET, roots[i] );
164 
165  MB_CHK_SET_ERR( result, "Creating root set failed" );
166  result = rps[i]->load_file( filenames[i], &roots[i], FileOptions( fileOpts.c_str() ) );
167  MB_CHK_SET_ERR( result, "load_file failed" );
168  }
169 
170  // Initialize the debug object for Range printing
171  DebugOutput debugOut( "ssn_test-", std::cerr );
172  debugOut.set_rank( rank );
173  debugOut.set_verbosity( 10 );
174 
175  // Output what is in root sets
176  for( unsigned int k = 0; k < filenames.size(); k++ )
177  {
178 
179  Range rootRg;
180  result = mbi->get_entities_by_handle( roots[k], rootRg );
181  MB_CHK_SET_ERR( result, "can't get entities" );
182  debugOut.print( 2, "Root set entities: ", rootRg );
183  rootRg.clear();
184 
185  Range partRg;
186  pcs[k]->get_part_entities( partRg );
187  debugOut.print( 2, "Partition entities: ", partRg );
188  partRg.clear();
189  }
190 
191  // source is 1st mesh, target is 2nd mesh
192  Range src_elems, targ_elems;
193 
194  // ******************************
195  std::cout << "********** Create Coupler **********" << std::endl;
196  // Create a coupler
197  std::cout << "Creating Coupler..." << std::endl;
198  Coupler mbc( mbi, pcs[0], src_elems, 0 );
199 
200  // Get tag handles for passed in tags
201  std::cout << "Getting tag handles..." << std::endl;
202  int numTagNames = tagNames.size();
203 
204  std::vector< Tag > tagHandles( numTagNames );
205  int iTags = 0;
206  while( iTags < numTagNames )
207  {
208  std::cout << "Getting handle for " << tagNames[iTags] << std::endl;
209  result = mbi->tag_get_handle( tagNames[iTags], tagHandles[iTags] );
210  MB_CHK_SET_ERR( result, "Retrieving tag handles failed" );
211  iTags++;
212  }
213 
214  // ******************************
215  std::cout << "********** Test create_tuples **********" << std::endl;
216  // First get some EntitySets for Mesh 1 and Mesh 2
217  {
218 
219  Range entsets1, entsets2;
220  result = mbi->get_entities_by_type_and_tag( roots[0], MBENTITYSET, &tagHandles[0],
221  (const void* const*)&tagValues[0], tagHandles.size(), entsets1,
222  Interface::INTERSECT ); // recursive is false
223  MB_CHK_SET_ERR( result, "sets: get_entities_by_type_and_tag failed on Mesh 1." );
224 
225  // Create tuple_list for each mesh's
226  std::cout << "Creating tuples for mesh 1..." << std::endl;
227  TupleList* m1TagTuples = NULL;
228  err = mbc.create_tuples( entsets1, &tagHandles[0], tagHandles.size(), &m1TagTuples );
229  MB_CHK_SET_ERR( (ErrorCode)err, "create_tuples failed" );
230 
231  std::cout << " create_tuples returned" << std::endl;
232  print_tuples( m1TagTuples );
233 
234  result = mbi->get_entities_by_type_and_tag( roots[1], MBENTITYSET, &tagHandles[0],
235  (const void* const*)&tagValues[0], tagHandles.size(), entsets2,
236  Interface::INTERSECT ); // recursive is false
237  MB_CHK_SET_ERR( result, "sets: get_entities_by_type_and_tag failed on Mesh 2." );
238 
239  std::cout << "Creating tuples for mesh 2..." << std::endl;
240  TupleList* m2TagTuples = NULL;
241  err = mbc.create_tuples( entsets2, (Tag*)( &tagHandles[0] ), tagHandles.size(), &m2TagTuples );
242  MB_CHK_SET_ERR( (ErrorCode)err, "create_tuples failed" );
243 
244  std::cout << " create_tuples returned" << std::endl;
245  print_tuples( m2TagTuples );
246 
247  // ******************************
248  std::cout << "********** Test consolidate_tuples **********" << std::endl;
249  // In this serial version we only have the tuples from Mesh 1 and Mesh 2.
250  // Just consolidate those for the test.
251  std::cout << "Consolidating tuple_lists for Mesh 1 and Mesh 2..." << std::endl;
252  TupleList** tplp_arr = (TupleList**)malloc( 2 * sizeof( TupleList* ) );
253  TupleList* unique_tpl = NULL;
254  tplp_arr[0] = m1TagTuples;
255  tplp_arr[1] = m2TagTuples;
256 
257  err = mbc.consolidate_tuples( tplp_arr, 2, &unique_tpl );
258  MB_CHK_SET_ERR( (ErrorCode)err, "consolidate_tuples failed" );
259  std::cout << " consolidate_tuples returned" << std::endl;
260  print_tuples( unique_tpl );
261  }
262 
263  // ******************************
264  std::cout << "********** Test get_matching_entities **********" << std::endl;
265  std::vector< std::vector< EntityHandle > > m1EntitySets;
266  std::vector< std::vector< EntityHandle > > m1EntityGroups;
267  std::vector< std::vector< EntityHandle > > m2EntitySets;
268  std::vector< std::vector< EntityHandle > > m2EntityGroups;
269 
270  // Get matching entities for Mesh 1
271  std::cout << "Get matching entities for mesh 1..." << std::endl;
272  err = mbc.get_matching_entities( roots[0], &tagHandles[0], &tagValues[0], tagHandles.size(), &m1EntitySets,
273  &m1EntityGroups );
274  MB_CHK_SET_ERR( (ErrorCode)err, "get_matching_entities failed" );
275 
276  std::cout << " get_matching_entities returned " << m1EntityGroups.size() << " entity groups" << std::endl;
277 
278  // Print out the data in the vector of vectors
279  std::vector< std::vector< EntityHandle > >::iterator iter_esi;
280  std::vector< std::vector< EntityHandle > >::iterator iter_egi;
281  std::vector< EntityHandle >::iterator iter_esj;
282  std::vector< EntityHandle >::iterator iter_egj;
283  Range entSetRg;
284  int icnt;
285  for( iter_egi = m1EntityGroups.begin(), iter_esi = m1EntitySets.begin(), icnt = 1;
286  ( iter_egi != m1EntityGroups.end() ) && ( iter_esi != m1EntitySets.end() ); ++iter_egi, ++iter_esi, icnt++ )
287  {
288  std::cout << " EntityGroup(" << icnt << ") = ";
289  std::cout.flush();
290  entSetRg.clear();
291  for( iter_egj = ( *iter_egi ).begin(); iter_egj != ( *iter_egi ).end(); ++iter_egj )
292  entSetRg.insert( (EntityHandle)*iter_egj );
293  debugOut.print( 2, "Mesh1 matching Entities: ", entSetRg );
294  std::cout.flush();
295 
296  std::cout << " EntitySet(" << icnt << ") = ";
297  std::cout.flush();
298  entSetRg.clear();
299  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
300  entSetRg.insert( (EntityHandle)*iter_esj );
301  debugOut.print( 2, "Mesh1 matching EntitySets: ", entSetRg );
302  std::cout.flush();
303  }
304 
305  // Get matching entities for Mesh 2
306  std::cout << "Get matching entities for mesh 2..." << std::endl;
307  err = mbc.get_matching_entities( roots[1], &tagHandles[0], &tagValues[0], tagHandles.size(), &m2EntitySets,
308  &m2EntityGroups );
309  MB_CHK_SET_ERR( (ErrorCode)err, "get_matching_entities failed" );
310 
311  std::cout << " get_matching_entities returned " << m2EntityGroups.size() << " entity groups" << std::endl;
312  for( iter_egi = m2EntityGroups.begin(), iter_esi = m2EntitySets.begin(), icnt = 1;
313  ( iter_egi != m2EntityGroups.end() ) && ( iter_esi != m2EntitySets.end() ); ++iter_egi, ++iter_esi, icnt++ )
314  {
315  std::cout << " EntityGroup(" << icnt << ") = ";
316  std::cout.flush();
317  entSetRg.clear();
318  for( iter_egj = ( *iter_egi ).begin(); iter_egj != ( *iter_egi ).end(); ++iter_egj )
319  entSetRg.insert( (EntityHandle)*iter_egj );
320  debugOut.print( 2, "Mesh2 matching Entities: ", entSetRg );
321  std::cout.flush();
322 
323  std::cout << " EntitySet(" << icnt << ") = ";
324  std::cout.flush();
325  entSetRg.clear();
326  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
327  entSetRg.insert( (EntityHandle)*iter_esj );
328  debugOut.print( 2, "Mesh2 matching EntitySets: ", entSetRg );
329  std::cout.flush();
330  }
331 
332  if( debug )
333  {
334  // ******************************
335  std::cout << "********** Test print_tuples **********" << std::endl;
336  // temporary test function
337  std::cout << "Testing print_tuples..." << std::endl;
338 
339  TupleList test_tuple;
340  int num_ints = 3, num_longs = 2, num_ulongs = 4, num_reals = 6, num_rows = 10;
341 
342  std::cout << " print of test_tuples zero init..." << std::endl;
343  test_tuple.initialize( 0, 0, 0, 0, 0 );
344 
345  test_tuple.enableWriteAccess();
346 
347  print_tuples( &test_tuple );
348 
349  std::cout << " print of test_tuples after setting n to 10..." << std::endl;
350  test_tuple.set_n( 10 );
351  print_tuples( &test_tuple );
352 
353  test_tuple.initialize( num_ints, num_longs, num_ulongs, num_reals, num_rows );
354  std::cout << " print of test_tuples after init..." << std::endl;
355  print_tuples( &test_tuple );
356 
357  std::cout << " print of test_tuples after setting n to 10..." << std::endl;
358  test_tuple.set_n( 10 );
359  print_tuples( &test_tuple );
360 
361  for( int i = 0; i < num_rows; i++ )
362  {
363  int j;
364  for( j = 0; j < num_ints; j++ )
365  test_tuple.vi_wr[i * num_ints + j] = (int)( ( j + 1 ) * ( i + 1 ) );
366 
367  for( j = 0; j < num_longs; j++ )
368  test_tuple.vl_wr[i * num_longs + j] = (int)( ( j + 1 ) * ( i + 1 ) );
369 
370  for( j = 0; j < num_ulongs; j++ )
371  test_tuple.vul_wr[i * num_ulongs + j] = (int)( ( j + 1 ) * ( i + 1 ) );
372 
373  for( j = 0; j < num_reals; j++ )
374  test_tuple.vr_wr[i * num_reals + j] = (int)( ( j + 1 ) * ( i + 1 ) + ( j * 0.01 ) );
375  }
376  std::cout << " print of test_tuples after filling with data..." << std::endl;
377  print_tuples( &test_tuple );
378 
379  // ******************************
380  std::cout << "********** Test pack_tuples and unpack_tuples **********" << std::endl;
381  void* mp_buf;
382  int buf_sz;
383  if( rank == 0 )
384  {
385  buf_sz = pack_tuples( &test_tuple, &mp_buf );
386  }
387 
388  // Send buffer size
389  err = MPI_Bcast( &buf_sz, 1, MPI_INT, 0, MPI_COMM_WORLD );
390 
391  if( err != MPI_SUCCESS )
392  {
393  std::cerr << "MPI_Bcast of buffer size failed" << std::endl;
394  return -1;
395  }
396 
397  // Allocate a buffer in the other procs
398  if( rank != 0 )
399  {
400  mp_buf = malloc( buf_sz * sizeof( uint ) );
401  }
402 
403  err = MPI_Bcast( mp_buf, buf_sz * sizeof( uint ), MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD );
404  if( err != MPI_SUCCESS )
405  {
406  std::cerr << "MPI_Bcast of buffer failed" << std::endl;
407  return -1;
408  }
409 
410  TupleList* rcv_tuples;
411  unpack_tuples( mp_buf, &rcv_tuples );
412 
413  std::cout << " print of rcv_tuples after unpacking from MPI_Bcast..." << std::endl;
414  print_tuples( rcv_tuples );
415  }
416 
418  MB_CHK_SET_ERR( (ErrorCode)err, "Failure in integrating a scalar_field" );
419 
420  // ******************************
421  std::cout << "********** Test get_group_integ_vals **********" << std::endl;
422  std::cout << "Get group integrated field values..." << std::endl;
423 
424  // print the field values at the vertices before change.
425  std::cout << " print vertex field values first:" << std::endl;
426  Tag norm_hdl;
427  result = mbi->tag_get_handle( normTag.c_str(), norm_hdl );
428  MB_CHK_SET_ERR( (ErrorCode)err, "Failed to get tag handle." );
429 
430  Coupler::IntegType integ_type = Coupler::VOLUME;
431  // Mesh 1 field values
432  std::cout << " Original entity vertex field values (mesh 1): " << std::endl;
433  print_vertex_fields( mbi, m1EntityGroups, norm_hdl, integ_type );
434 
435  // Mesh 2 field values
436  std::cout << " Original entity vertex field values (mesh 2): " << std::endl;
437  print_vertex_fields( mbi, m2EntityGroups, norm_hdl, integ_type );
438 
439  // Get the field values
440  std::vector< double >::iterator iter_ivals;
441 
442  std::cout << "Get group integrated field values for mesh 1..." << std::endl;
443  std::vector< double > m1IntegVals( m1EntityGroups.size() );
444  err = mbc.get_group_integ_vals( m1EntityGroups, m1IntegVals, normTag.c_str(), 4, integ_type );
445  MB_CHK_SET_ERR( (ErrorCode)err, "Failed to get the Mesh 1 group integration values." );
446  std::cout << "Mesh 1 integrated field values(" << m1IntegVals.size() << "): ";
447  for( iter_ivals = m1IntegVals.begin(); iter_ivals != m1IntegVals.end(); ++iter_ivals )
448  {
449  std::cout << ( *iter_ivals ) << " ";
450  }
451  std::cout << std::endl;
452 
453  std::cout << "Get group integrated field values for mesh 2..." << std::endl;
454  std::vector< double > m2IntegVals( m2EntityGroups.size() );
455  err = mbc.get_group_integ_vals( m2EntityGroups, m2IntegVals, normTag.c_str(), 4, integ_type );
456  MB_CHK_SET_ERR( (ErrorCode)err, "Failed to get the Mesh 2 group integration values." );
457  std::cout << "Mesh 2 integrated field values(" << m2IntegVals.size() << "): ";
458  for( iter_ivals = m2IntegVals.begin(); iter_ivals != m2IntegVals.end(); ++iter_ivals )
459  {
460  std::cout << ( *iter_ivals ) << " ";
461  }
462  std::cout << std::endl;
463 
464  // ******************************
465  std::cout << "********** Test apply_group_norm_factors **********" << std::endl;
466  // Make the norm factors by inverting the integration values.
467  double val;
468  for( unsigned int i = 0; i < m1IntegVals.size(); i++ )
469  {
470  val = m1IntegVals[i];
471  m1IntegVals[i] = 1 / val;
472  }
473 
474  for( unsigned int i = 0; i < m2IntegVals.size(); i++ )
475  {
476  val = m2IntegVals[i];
477  m2IntegVals[i] = 1 / val;
478  }
479 
480  std::cout << "Mesh 1 norm factors(" << m1IntegVals.size() << "): ";
481  for( iter_ivals = m1IntegVals.begin(); iter_ivals != m1IntegVals.end(); ++iter_ivals )
482  {
483  std::cout << ( *iter_ivals ) << " ";
484  }
485  std::cout << std::endl;
486 
487  std::cout << "Mesh 2 norm factors(" << m2IntegVals.size() << "): ";
488  for( iter_ivals = m2IntegVals.begin(); iter_ivals != m2IntegVals.end(); ++iter_ivals )
489  {
490  std::cout << ( *iter_ivals ) << " ";
491  }
492  std::cout << std::endl;
493 
494  // Apply the factors and reprint the vertices
495  err = mbc.apply_group_norm_factor( m1EntitySets, m1IntegVals, normTag.c_str(), integ_type );
496  MB_CHK_SET_ERR( (ErrorCode)err, "Failed to apply norm factors to Mesh 1." );
497 
498  err = mbc.apply_group_norm_factor( m2EntitySets, m2IntegVals, normTag.c_str(), integ_type );
499  MB_CHK_SET_ERR( (ErrorCode)err, "Failed to apply norm factors to Mesh 2." );
500 
501  // Get the norm_tag_factor on the EntitySets
502  // Get the handle for the norm factor tag
503  Tag norm_factor_hdl;
504  std::string normFactor = normTag + "_normf";
505  result = mbi->tag_get_handle( normFactor.c_str(), norm_factor_hdl );
506  MB_CHK_SET_ERR( result, "Failed to get norm factor tag handle." );
507 
508  // Mesh 1 values
509  std::cout << "Mesh 1 norm factors per EntitySet...";
510  for( iter_esi = m1EntitySets.begin(); iter_esi != m1EntitySets.end(); ++iter_esi )
511  {
512  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
513  {
514  double data = 0;
515  EntityHandle eh = *iter_esj;
516  result = mbi->tag_get_data( norm_factor_hdl, &eh, 1, &data );
517  MB_CHK_SET_ERR( result, "Failed to get tag data." );
518  std::cout << data << ", ";
519  }
520  }
521  std::cout << std::endl;
522 
523  // Mesh 2 values
524  std::cout << "Mesh 2 norm factors per EntitySet...";
525  for( iter_esi = m2EntitySets.begin(); iter_esi != m2EntitySets.end(); ++iter_esi )
526  {
527  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
528  {
529  double data = 0;
530  EntityHandle eh = *iter_esj;
531  result = mbi->tag_get_data( norm_factor_hdl, &eh, 1, &data );
532  MB_CHK_SET_ERR( result, "Failed to get tag data." );
533  std::cout << data << ", ";
534  }
535  }
536  std::cout << std::endl;
537 
538  // ******************************
539  std::cout << "********** Test normalize_subset **********" << std::endl;
540  // Now call the Coupler::normalize_subset routine and see if we get an error.
541  std::cout << "Running Coupler::normalize_subset() on mesh 1" << std::endl;
542  err = mbc.normalize_subset( (EntityHandle)roots[0], normTag.c_str(), &tagNames[0], numTagNames, &tagValues[0],
543  Coupler::VOLUME, 4 );
544  MB_CHK_SET_ERR( (ErrorCode)err, "Failure in call to Coupler::normalize_subset() on mesh 1" );
545 
546  // Print the normFactor on each EntitySet after the above call.
547  // Mesh 1 values
548  std::cout << "Mesh 1 norm factors per EntitySet...";
549  for( iter_esi = m1EntitySets.begin(); iter_esi != m1EntitySets.end(); ++iter_esi )
550  {
551  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
552  {
553  double data = 0;
554  EntityHandle eh = *iter_esj;
555  result = mbi->tag_get_data( norm_factor_hdl, &eh, 1, &data );
556  MB_CHK_SET_ERR( result, "Failed to get tag data." );
557  std::cout << data << ", ";
558  }
559  }
560  std::cout << std::endl;
561 
562  std::cout << "Running Coupler::normalize_subset() on mesh 2" << std::endl;
563  err = mbc.normalize_subset( (EntityHandle)roots[1], normTag.c_str(), &tagNames[0], numTagNames, &tagValues[0],
564  Coupler::VOLUME, 4 );
565  MB_CHK_SET_ERR( (ErrorCode)err, "Failure in call to Coupler::normalize_subset() on mesh 2" );
566 
567  // Mesh 2 values
568  std::cout << "Mesh 2 norm factors per EntitySet...";
569  for( iter_esi = m2EntitySets.begin(); iter_esi != m2EntitySets.end(); ++iter_esi )
570  {
571  for( iter_esj = ( *iter_esi ).begin(); iter_esj != ( *iter_esi ).end(); ++iter_esj )
572  {
573  double data = 0;
574  EntityHandle eh = *iter_esj;
575  result = mbi->tag_get_data( norm_factor_hdl, &eh, 1, &data );
576  MB_CHK_SET_ERR( result, "Failed to get tag data." );
577 
578  std::cout << data << ", ";
579  }
580  }
581  std::cout << std::endl;
582 
583  // Done, cleanup
584  std::cout << "********** ssn_test DONE! **********" << std::endl;
585  MPI_Finalize();
586  return 0;
587 }
588 
590 {
591  // ******************************
592  std::cout << "********** Test moab::Element::Map::integrate_scalar_field **********" << std::endl;
593  // Create a simple hex centered at 0,0,0 with sides of length 2.
594  std::vector< CartVect > biunit_cube( 8 );
595  biunit_cube[0] = CartVect( -1, -1, -1 );
596  biunit_cube[1] = CartVect( 1, -1, -1 );
597  biunit_cube[2] = CartVect( 1, 1, -1 );
598  biunit_cube[3] = CartVect( -1, 1, -1 );
599  biunit_cube[4] = CartVect( -1, -1, 1 );
600  biunit_cube[5] = CartVect( 1, -1, 1 );
601  biunit_cube[6] = CartVect( 1, 1, 1 );
602  biunit_cube[7] = CartVect( -1, 1, 1 );
603 
604  std::vector< CartVect > zerobase_cube( 8 );
605  zerobase_cube[0] = CartVect( 0, 0, 0 );
606  zerobase_cube[1] = CartVect( 2, 0, 0 );
607  zerobase_cube[2] = CartVect( 2, 2, 0 );
608  zerobase_cube[3] = CartVect( 0, 2, 0 );
609  zerobase_cube[4] = CartVect( 0, 0, 2 );
610  zerobase_cube[5] = CartVect( 2, 0, 2 );
611  zerobase_cube[6] = CartVect( 2, 2, 2 );
612  zerobase_cube[7] = CartVect( 0, 2, 2 );
613 
614  // Calculate field values at the corners of both cubes
615  double bcf[8], bf1[8], bf2[8], bf3[8], zcf[8], zf1[8], zf2[8], zf3[8];
616  for( int i = 0; i < 8; i++ )
617  {
618  bcf[i] = const_field( biunit_cube[i][0], biunit_cube[i][1], biunit_cube[i][2] );
619  bf1[i] = field_1( biunit_cube[i][0], biunit_cube[i][1], biunit_cube[i][2] );
620  bf2[i] = field_2( biunit_cube[i][0], biunit_cube[i][1], biunit_cube[i][2] );
621  bf3[i] = field_3( biunit_cube[i][0], biunit_cube[i][1], biunit_cube[i][2] );
622 
623  zcf[i] = const_field( zerobase_cube[i][0], zerobase_cube[i][1], zerobase_cube[i][2] );
624  zf1[i] = field_1( zerobase_cube[i][0], zerobase_cube[i][1], zerobase_cube[i][2] );
625  zf2[i] = field_2( zerobase_cube[i][0], zerobase_cube[i][1], zerobase_cube[i][2] );
626  zf3[i] = field_3( zerobase_cube[i][0], zerobase_cube[i][1], zerobase_cube[i][2] );
627  }
628 
629  std::cout << "Integrated values:" << std::endl;
630 
631  try
632  {
633  double field_const1, field_const2;
634  double field_linear1, field_linear2;
635  double field_quad1, field_quad2;
636  double field_cubic1, field_cubic2;
637 
638  int ipoints = 0;
639  Element::LinearHex biunit_hexMap( biunit_cube );
640  Element::LinearHex zerobase_hexMap( zerobase_cube );
641 
642  field_const1 = biunit_hexMap.integrate_scalar_field( bcf );
643  field_const2 = zerobase_hexMap.integrate_scalar_field( zcf );
644  std::cout << " binunit_cube, const_field(num_pts=" << ipoints << "): field_val=" << field_const1
645  << std::endl;
646  std::cout << " zerobase_cube, const_field(num_pts=" << ipoints << "): field_val=" << field_const2
647  << std::endl;
648 
649  field_linear1 = biunit_hexMap.integrate_scalar_field( bf1 );
650  field_linear2 = zerobase_hexMap.integrate_scalar_field( zf1 );
651  std::cout << " binunit_cube, field_1(num_pts=" << ipoints << "): field_val=" << field_linear1 << std::endl;
652  std::cout << " zerobase_cube, field_1(num_pts=" << ipoints << "): field_val=" << field_linear2 << std::endl;
653 
654  field_quad1 = biunit_hexMap.integrate_scalar_field( bf2 );
655  field_quad2 = zerobase_hexMap.integrate_scalar_field( zf2 );
656  std::cout << " binunit_cube, field_2(num_pts=" << ipoints << "): field_val=" << field_quad1 << std::endl;
657  std::cout << " zerobase_cube, field_2(num_pts=" << ipoints << "): field_val=" << field_quad2 << std::endl;
658 
659  field_cubic1 = biunit_hexMap.integrate_scalar_field( bf3 );
660  field_cubic2 = zerobase_hexMap.integrate_scalar_field( zf3 );
661  std::cout << " binunit_cube, field_3(num_pts=" << ipoints << "): field_val=" << field_cubic1 << std::endl;
662  std::cout << " zerobase_cube, field_3(num_pts=" << ipoints << "): field_val=" << field_cubic2 << std::endl;
663  }
665  {
666  MB_CHK_SET_ERR( MB_FAILURE, "Failed to set vertices on Element::Map." );
667  }
669  {
670  MB_CHK_SET_ERR( MB_FAILURE, "Failed to get inverse evaluation of coordinate on Element::Map." );
671  }
672  return MB_SUCCESS;
673 }
674 
675 // Function to parse input parameters
676 void get_file_options( int argc,
677  char** argv,
678  std::vector< const char* >& filenames,
679  std::string& normTag,
680  std::vector< const char* >& tagNames,
681  std::vector< const char* >& tagValues,
682  std::string& fileOpts,
683  int* err )
684 {
685  int npos = 1;
686 
687  // get number of files
688  int nfiles = atoi( argv[npos++] );
689 
690  // get mesh filenames
691  filenames.resize( nfiles );
692  for( int i = 0; i < nfiles; i++ )
693  filenames[i] = argv[npos++];
694 
695  // get normTag
696  if( npos < argc )
697  normTag = argv[npos++];
698  else
699  {
700  std::cerr << "Insufficient parameters: norm_tag missing" << std::endl;
701  *err = 1;
702  return;
703  }
704 
705  // get tag selection options
706  if( npos < argc )
707  {
708  char* opts = argv[npos++];
709  // char sep1[1] = {';'};
710  // char sep2[1] = {'='};
711  bool end_vals_seen = false;
712  std::vector< char* > tmpTagOpts;
713 
714  // first get the options
715  for( char* i = strtok( opts, ";" ); i; i = strtok( 0, ";" ) )
716  {
717  if( debug ) std::cout << "get_file_options: i=" << i << std::endl;
718  tmpTagOpts.push_back( i );
719  }
720 
721  // parse out the name and val or just name.
722  for( unsigned int j = 0; j < tmpTagOpts.size(); j++ )
723  {
724  char* e = strtok( tmpTagOpts[j], "=" );
725  if( debug ) std::cout << "get_file_options: name=" << e << std::endl;
726  tagNames.push_back( e );
727  e = strtok( 0, "=" );
728  if( e != NULL )
729  {
730  if( debug ) std::cout << "get_file_options: val=" << e << std::endl;
731  // We have a value
732  if( end_vals_seen )
733  {
734  // ERROR we should not have a value after none are seen
735  std::cerr << "Incorrect parameters: new value seen after end of values" << std::endl;
736  *err = 1;
737  return;
738  }
739  // Otherwise get the value string from e and convert it to an int
740  int* valp = new int;
741  *valp = atoi( e );
742  tagValues.push_back( (const char*)valp );
743  }
744  else
745  {
746  // Otherwise there is no '=' so push a null on the list
747  end_vals_seen = true;
748  tagValues.push_back( (const char*)0 );
749  }
750  }
751  }
752  else
753  {
754  std::cerr << "Insufficient parameters: tag_select_opts missing" << std::endl;
755  *err = 1;
756  return;
757  }
758 
759  // get fileOpts
760  if( npos < argc )
761  fileOpts = argv[npos++];
762  else
763  {
764  std::cerr << "Insufficient parameters: file_opts missing" << std::endl;
765  *err = 1;
766  return;
767  }
768 }
769 
770 // Function to print out a tuple_list.
772 {
773  uint mi, ml, mul, mr;
774  tlp->getTupleSize( mi, ml, mul, mr );
775  std::cout << " tuple data: (n=" << tlp->get_n() << ")" << std::endl;
776  std::cout << " mi:" << mi << " ml:" << ml << " mul:" << mul << " mr:" << mr << std::endl;
777  std::cout << " [" << std::setw( 11 * mi ) << " int data"
778  << " |" << std::setw( 11 * ml ) << " long data"
779  << " |" << std::setw( 11 * mul ) << " Ulong data"
780  << " |" << std::setw( 11 * mr ) << " real data"
781  << " " << std::endl
782  << " ";
783  for( unsigned int i = 0; i < tlp->get_n(); i++ )
784  {
785  if( mi > 0 )
786  {
787  for( unsigned int j = 0; j < mi; j++ )
788  {
789  std::cout << std::setw( 10 ) << tlp->vi_rd[i * mi + j] << " ";
790  }
791  }
792  else
793  {
794  std::cout << " ";
795  }
796  std::cout << "| ";
797 
798  if( ml > 0 )
799  {
800  for( unsigned int j = 0; j < ml; j++ )
801  {
802  std::cout << std::setw( 10 ) << tlp->vl_rd[i * ml + j] << " ";
803  }
804  }
805  else
806  {
807  std::cout << " ";
808  }
809  std::cout << "| ";
810 
811  if( mul > 0 )
812  {
813  for( unsigned int j = 0; j < mul; j++ )
814  {
815  std::cout << std::setw( 10 ) << tlp->vul_rd[i * mul + j] << " ";
816  }
817  }
818  else
819  {
820  std::cout << " ";
821  }
822  std::cout << "| ";
823 
824  if( mr > 0 )
825  {
826  for( unsigned int j = 0; j < mr; j++ )
827  {
828  std::cout << std::setw( 10 ) << tlp->vr_rd[i * mr + j] << " ";
829  }
830  }
831  else
832  {
833  std::cout << " ";
834  }
835 
836  if( i + 1 < tlp->get_n() ) std::cout << std::endl << " ";
837  }
838  std::cout << "]" << std::endl;
839 }
840 
841 // Function to print vertex field values
843  std::vector< std::vector< EntityHandle > >& groups,
844  Tag& norm_hdl,
845  Coupler::IntegType integ_type )
846 {
847  int err = 0;
848  ErrorCode result;
849  std::vector< EntityHandle >::iterator iter_j;
850 
851  for( unsigned int i = 0; i < groups.size(); i++ )
852  {
853  std::cout << " Group - " << std::endl << " ";
854  for( iter_j = groups[i].begin(); iter_j != groups[i].end(); ++iter_j )
855  {
856  EntityHandle ehandle = ( *iter_j );
857  // Check that the entity in iter_j is of the same dimension as the
858  // integ_type we are performing
859  int j_type = mbi->dimension_from_handle( ehandle );
860 
861  if( ( integ_type == Coupler::VOLUME ) && ( j_type != 3 ) ) continue;
862 
863  // Retrieve the vertices from the element
864  const EntityHandle* conn = NULL;
865  int num_verts = 0;
866  result = mbi->get_connectivity( ehandle, conn, num_verts );
867  if( MB_SUCCESS != result ) return 1;
868  std::cout << std::fixed;
869  for( int iv = 0; iv < num_verts; iv++ )
870  {
871  double data = 0;
872  result = mbi->tag_get_data( norm_hdl, &conn[iv], 1, &data );
873  if( MB_SUCCESS != result ) return 1;
874  std::cout << std::setprecision( 8 ) << data << ", ";
875  }
876  std::cout << std::endl << " ";
877  }
878  std::cout << std::endl;
879  std::cout.unsetf( std::ios_base::floatfield ); // turn off fixed notation
880  }
881 
882  return err;
883 }
884 
885 // Function for a constant field value
886 double const_field( double /*x*/, double /*y*/, double /*z*/ )
887 {
888  // return 5.0/40.0;
889  return 5.0;
890 }
891 
892 // Functions for a some field values
893 double field_1( double x, double y, double z )
894 {
895  double f = fabs( x ) + fabs( y ) + fabs( z );
896  // return f/24.0;
897  return f;
898 }
899 
900 double field_2( double x, double y, double z )
901 {
902  double f = x * x + y * y + z * z;
903  // return f/32.0;
904  return f;
905 }
906 
907 double field_3( double x, double y, double z )
908 {
909  double f = 2 * x + 2 * y + 2 * z;
910  // return f/48.0;
911  return f;
912 }
913 
914 // Function used to create field on mesh for testing.
915 double physField( double x, double y, double z )
916 {
917  double out;
918 
919  // 1/r^2 decay from {0,0,0}
920 
921  out = x * x + y * y + z * z;
922  out += 1e-1; // clamp
923  out = 1 / out;
924 
925  return out;
926 }
927 
928 #define UINT_PER_X( X ) ( ( sizeof( X ) + sizeof( uint ) - 1 ) / sizeof( uint ) )
929 #define UINT_PER_REAL UINT_PER_X( realType )
930 #define UINT_PER_LONG UINT_PER_X( slong )
931 #define UINT_PER_ULONG UINT_PER_X( Ulong )
932 #define UINT_PER_UNSIGNED UINT_PER_X( unsigned )
933 
934 // Function for packing tuple_list
935 int pack_tuples( TupleList* tl, void** ptr )
936 {
937  uint mi, ml, mul, mr;
938  tl->getTupleSize( mi, ml, mul, mr );
939 
940  uint n = tl->get_n();
941 
942  int sz_buf = 1 + 4 * UINT_PER_UNSIGNED +
943  tl->get_n() * ( mi + ml * UINT_PER_LONG + mul * UINT_PER_LONG + mr * UINT_PER_REAL );
944 
945  uint* buf = (uint*)malloc( sz_buf * sizeof( uint ) );
946  *ptr = (void*)buf;
947 
948  // copy n
949  memcpy( buf, &n, sizeof( uint ) ), buf += 1;
950  // copy mi
951  memcpy( buf, &mi, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
952  // copy ml
953  memcpy( buf, &ml, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
954  // copy mul
955  memcpy( buf, &mul, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
956  // copy mr
957  memcpy( buf, &mr, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
958  // copy vi_rd
959  memcpy( buf, tl->vi_rd, tl->get_n() * mi * sizeof( sint ) ), buf += tl->get_n() * mi;
960  // copy vl_rd
961  memcpy( buf, tl->vl_rd, tl->get_n() * ml * sizeof( slong ) ), buf += tl->get_n() * ml * UINT_PER_LONG;
962  // copy vul_rd
963  memcpy( buf, tl->vul_rd, tl->get_n() * mul * sizeof( Ulong ) ), buf += tl->get_n() * mul * UINT_PER_ULONG;
964  // copy vr_rd
965  memcpy( buf, tl->vr_rd, tl->get_n() * mr * sizeof( realType ) ), buf += tl->get_n() * mr * UINT_PER_REAL;
966 
967  return sz_buf;
968 }
969 
970 // Function for packing tuple_list
971 void unpack_tuples( void* ptr, TupleList** tlp )
972 {
973  TupleList* tl = new TupleList();
974  *tlp = tl;
975 
976  uint nt;
977  unsigned mit, mlt, mult, mrt;
978  uint* buf = (uint*)ptr;
979 
980  // get n
981  memcpy( &nt, buf, sizeof( uint ) ), buf += 1;
982  // get mi
983  memcpy( &mit, buf, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
984  // get ml
985  memcpy( &mlt, buf, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
986  // get mul
987  memcpy( &mult, buf, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
988  // get mr
989  memcpy( &mrt, buf, sizeof( unsigned ) ), buf += UINT_PER_UNSIGNED;
990 
991  // initialize tl
992  tl->initialize( mit, mlt, mult, mrt, nt );
993  tl->enableWriteAccess();
994  tl->set_n( nt );
995 
996  uint mi, ml, mul, mr;
997  tl->getTupleSize( mi, ml, mul, mr );
998 
999  // get vi_wr
1000  memcpy( tl->vi_wr, buf, tl->get_n() * mi * sizeof( sint ) ), buf += tl->get_n() * mi;
1001  // get vl_wr
1002  memcpy( tl->vl_wr, buf, tl->get_n() * ml * sizeof( slong ) ), buf += tl->get_n() * ml * UINT_PER_LONG;
1003  // get vul_wr
1004  memcpy( tl->vul_wr, buf, tl->get_n() * mul * sizeof( Ulong ) ), buf += tl->get_n() * mul * UINT_PER_ULONG;
1005  // get vr_wr
1006  memcpy( tl->vr_wr, buf, tl->get_n() * mr * sizeof( realType ) ), buf += tl->get_n() * mr * UINT_PER_REAL;
1007 
1008  tl->disableWriteAccess();
1009 
1010  return;
1011 }