MOAB: Mesh Oriented datABase  (version 5.5.0)
scdseq_test.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 //
17 // test the structured sequence stuff
18 //
19 
20 #include "moab/ScdInterface.hpp"
21 #include "moab/Core.hpp"
22 #include "TestUtil.hpp"
23 
24 #include <iostream>
25 
26 using namespace moab;
27 
28 void test_vertex_seq();
29 void test_element_seq();
30 void test_periodic_seq();
32 
33 ErrorCode test_parallel_partition( int* gdims, int nprocs, int part_method );
34 
35 ErrorCode check_vertex_sequence( const ScdBox* this_box,
36  const int imin,
37  const int jmin,
38  const int kmin,
39  const int imax,
40  const int jmax,
41  const int kmax,
42  const EntityHandle this_start );
44 ErrorCode check_element_sequence( const ScdBox* this_box,
45  const HomCoord& min_params,
46  const HomCoord& max_params,
47  const EntityHandle this_start );
49 ErrorCode eseq_test1a( ScdInterface* scdi, HomCoord tmp_min, HomCoord tmp_max );
50 ErrorCode eseq_test1b( ScdInterface* scdi, HomCoord tmp_min, HomCoord tmp_max );
51 ErrorCode eseq_test1c( ScdInterface* scdi, const HomCoord& tmp_min, const HomCoord& tmp_max );
52 ErrorCode eseq_test2a( ScdInterface* scdi, const HomCoord& tmp_min, const HomCoord& tmp_max );
56 
57 ErrorCode create_1d_3_sequences( ScdInterface* scdi, HomCoord tmp_min, HomCoord tmp_max, ScdBox** vseq, ScdBox** eseq );
58 
60 
62  const int int1,
63  const int int2,
64  const int int3,
65  ScdBox** vseq,
66  ScdBox** eseq );
68  const int int1,
69  const int int2,
70  const int int3,
71  const int int4,
72  ScdBox** vseq,
73  ScdBox** eseq );
75 
77 
79 
80 // first comes general-capability code used by various tests; main and test functions
81 // come after these, starting with main
83  const int imin,
84  const int jmin,
85  const int kmin,
86  const int imax,
87  const int jmax,
88  const int kmax,
89  const EntityHandle this_start )
90 {
91  ErrorCode result = MB_SUCCESS;
92 
93  // check data stored in sequence with that in arg list
94  if( imin != this_box->box_min()[0] || jmin != this_box->box_min()[1] || kmin != this_box->box_min()[2] ||
95  imax != this_box->box_max()[0] || jmax != this_box->box_max()[1] || kmax != this_box->box_max()[2] )
96  {
97  std::cout << "min/max params not correct for a sequence." << std::endl;
98  result = MB_FAILURE;
99  }
100 
101  HomCoord ijk1 = this_box->box_min(), ijk2 = this_box->box_max(), dijk = this_box->box_size();
102  if( ijk2 - ijk1 + HomCoord( 1, 1, 1, 0 ) != dijk )
103  {
104  std::cout << "min_params/max_params/param_extents functions returned inconsistent results" << std::endl;
105  result = MB_FAILURE;
106  }
107 
108  if( this_start != this_box->start_vertex() )
109  {
110  std::cout << "Start handle for sequence wrong." << std::endl;
111  result = MB_FAILURE;
112  }
113 
114  return result;
115 }
116 
118  const HomCoord& min_params,
119  const HomCoord& max_params,
120  const EntityHandle this_start )
121 {
122  ErrorCode result = MB_SUCCESS;
123 
124  // check data stored in sequence with that in arg list
125  if( min_params.i() != this_box->box_min()[0] || min_params.j() != this_box->box_min()[1] ||
126  min_params.k() != this_box->box_min()[2] || max_params.i() != this_box->box_max()[0] ||
127  max_params.j() != this_box->box_max()[1] || max_params.k() != this_box->box_max()[2] )
128  {
129  std::cout << "min/max params not correct for a sequence." << std::endl;
130  result = MB_FAILURE;
131  }
132 
133  if( this_box->box_max() - this_box->box_min() + HomCoord( 1, 1, 1, 0 ) != this_box->box_size() )
134  {
135  std::cout << "min_params/max_params/param_extents functions returned inconsistent results" << std::endl;
136  result = MB_FAILURE;
137  }
138 
139  if( this_start != this_box->start_element() )
140  {
141  std::cout << "Start handle for sequence wrong." << std::endl;
142  result = MB_FAILURE;
143  }
144 
145  if( this_box->boundary_complete() == false )
146  {
147  std::cout << "Element sequence didn't pass boundary_complete test." << std::endl;
148  result = MB_FAILURE;
149  }
150 
151  return result;
152 }
153 
155 {
156  ErrorCode result = MB_SUCCESS;
157 
158  // first get the parametric extents
159  HomCoord ijk1 = this_box->box_min(), ijk2 = this_box->box_max();
160 
161  // then the start vertex
162  EntityHandle start_handle = this_box->start_vertex();
163 
164  // now evaluate all the vertices in forward and reverse
165  EntityHandle tmp_handle, tmp_handle2;
166  for( int i = ijk1[0]; i <= ijk2[0]; i++ )
167  {
168  for( int j = ijk1[1]; j <= ijk2[1]; j++ )
169  {
170  for( int k = ijk1[2]; k <= ijk2[2]; k++ )
171  {
172  // compute what the vertex handle is supposed to be
173  EntityHandle this_handle = start_handle + ( i - ijk1[0] ) +
174  ( j - ijk1[1] ) * ( ijk2[0] - ijk1[0] + 1 ) +
175  ( k - ijk1[2] ) * ( ijk2[1] - ijk1[1] + 1 ) * ( ijk2[0] - ijk1[0] + 1 );
176 
177  // get_vertex variants
178  tmp_handle = this_box->get_vertex( i, j, k );
179 
180  if( this_box->get_vertex( i, j, k ) != this_handle )
181  {
182  std::cout << "vertex seq: get_vertex(i, j, k) didn't work, i, j, k = " << i << ", " << j << ", "
183  << k << "." << std::endl;
184  result = MB_FAILURE;
185  }
186 
187  tmp_handle2 = this_box->get_vertex( HomCoord( i, j, k ) );
188  if( tmp_handle2 != this_handle )
189  {
190  std::cout << "vertex seq: get_vertex(HomCoord) didn't work, i, j, k = " << i << ", " << j << ", "
191  << k << "." << std::endl;
192  result = MB_FAILURE;
193  }
194 
195  int itmp, jtmp, ktmp;
196  itmp = jtmp = ktmp = 0xdeadbeef;
197  ErrorCode tmp_result = this_box->get_params( tmp_handle, itmp, jtmp, ktmp );
198  if( MB_SUCCESS != tmp_result || i != itmp || j != jtmp || k != ktmp )
199  {
200  std::cout << "vertex seq: get_params didn't work, i, j, k = " << i << ", " << j << ", " << k
201  << "; itmp, jtmp, ktmp = " << itmp << ", " << jtmp << ", " << ktmp << std::endl;
202  result = MB_FAILURE;
203  }
204 
205  if( !this_box->contains( i, j, k ) || !this_box->contains( HomCoord( i, j, k ) ) )
206  {
207  std::cout << "vertex seq: contains didn't work, i, j, k = " << i << ", " << j << ", " << k << "."
208  << std::endl;
209  result = MB_FAILURE;
210  }
211  }
212  }
213  }
214 
215  return result;
216 }
217 
219 {
220  ErrorCode result = MB_SUCCESS;
221 
222  // first get the parametric extents
223  HomCoord ijk1 = this_box->box_min(), ijk2 = this_box->box_max();
224 
225  // now evaluate all the vertices and elements in forward and reverse
226  EntityHandle tmp_handle, tmp_handle2;
227  int is_periodic_i = ( this_box->locally_periodic_i() ? 1 : 0 ),
228  is_periodic_j = ( this_box->locally_periodic_j() ? 1 : 0 );
229  for( int i = ijk1[0]; i < ijk2[0] + is_periodic_i; i++ )
230  {
231  for( int j = ijk1[1]; j < ijk2[1] + is_periodic_j; j++ )
232  {
233  for( int k = ijk1[2]; k < ijk2[2]; k++ )
234  {
235 
236  // get_vertex variants
237  tmp_handle = this_box->get_vertex( i, j, k );
238 
239  tmp_handle2 = this_box->get_vertex( HomCoord( i, j, k ) );
240  if( tmp_handle2 != tmp_handle )
241  {
242  std::cout << "element seq: get_vertex(HomCoord) and get_vertex(i,j,k) didn't return" << std::endl
243  << "consistent results, i, j, k = " << i << ", " << j << ", " << k << "." << std::endl;
244  result = MB_FAILURE;
245  }
246 
247  // get element variants
248  tmp_handle = this_box->get_element( i, j, k );
249 
250  tmp_handle2 = this_box->get_element( HomCoord( i, j, k ) );
251  if( tmp_handle2 != tmp_handle )
252  {
253  std::cout << "element seq: get_element(HomCoord) and get_element(i,j,k) didn't return" << std::endl
254  << "consistent results, i, j, k = " << i << ", " << j << ", " << k << "." << std::endl;
255  result = MB_FAILURE;
256  }
257 
258  // get_params
259  int itmp, jtmp, ktmp;
260  itmp = jtmp = ktmp = 0xdeadbeef;
261  ErrorCode tmp_result = this_box->get_params( tmp_handle, itmp, jtmp, ktmp );
262  if( MB_SUCCESS != tmp_result || i != itmp || j != jtmp || k != ktmp )
263  {
264  std::cout << "element seq: get_params didn't work, i, j, k = " << i << ", " << j << ", " << k
265  << "; itmp, jtmp, ktmp = " << itmp << ", " << jtmp << ", " << ktmp << std::endl;
266  result = MB_FAILURE;
267  }
268 
269  if( !this_box->contains( i, j, k ) || !this_box->contains( HomCoord( i, j, k ) ) )
270  {
271  std::cout << "element seq: contains didn't work, i, j, k = " << i << ", " << j << ", " << k << "."
272  << std::endl;
273  result = MB_FAILURE;
274  }
275  }
276  }
277  }
278 
279  return result;
280 }
281 
282 int main( int, char** )
283 {
284  // test partition methods
285  int err = RUN_TEST( test_parallel_partitions );
286 
287  // test creating and evaluating vertex sequences
288  err += RUN_TEST( test_vertex_seq );
289 
290  // test creating and evaluating element sequences
291  err += RUN_TEST( test_element_seq );
292 
293  // test periodic sequences
294  err += RUN_TEST( test_periodic_seq );
295 
296  return err;
297 }
298 
300 {
301  Core moab;
302  ScdInterface* scdi;
303  ErrorCode rval = moab.Interface::query_interface( scdi );CHECK_ERR( rval );
304 
305  // get the seq manager from gMB
306  ScdBox* dum_box = NULL;
307 
308  // make a 1d sequence
309  ErrorCode result = scdi->create_scd_sequence( HomCoord( -10, 0, 0 ), HomCoord( 10, 0, 0 ), MBVERTEX, 1, dum_box );CHECK_ERR( result );
310  if( !dum_box || dum_box->start_vertex() == 0 ) CHECK_ERR( MB_FAILURE );
311 
312  // check sequence data
313  result = check_vertex_sequence( dum_box, -10, 0, 0, 10, 0, 0, dum_box->start_vertex() );CHECK_ERR( result );
314 
315  // evaluate that sequence for all possible values
316  result = evaluate_vertex_sequence( dum_box );CHECK_ERR( result );
317 
318  // make a 2d sequence
319  dum_box = NULL;
320  result = scdi->create_scd_sequence( HomCoord( -10, -10, 0 ), HomCoord( 10, 10, 0 ), MBVERTEX, 1, dum_box );CHECK_ERR( result );
321 
322  // check sequence data
323  result = check_vertex_sequence( dum_box, -10, -10, 0, 10, 10, 0, dum_box->start_vertex() );CHECK_ERR( result );
324 
325  // evaluate that sequence for all possible values
326  result = evaluate_vertex_sequence( dum_box );CHECK_ERR( result );
327 
328  // make a 3d sequence
329  dum_box = NULL;
330  result = scdi->create_scd_sequence( HomCoord( -10, -10, -10 ), HomCoord( 10, 10, 10 ), MBVERTEX, 1, dum_box );CHECK_ERR( result );
331  if( !dum_box || dum_box->start_vertex() == 0 ) CHECK_ERR( MB_FAILURE );
332 
333  // check sequence data
334  result = check_vertex_sequence( dum_box, -10, -10, -10, 10, 10, 10, dum_box->start_vertex() );CHECK_ERR( result );
335 
336  // evaluate that sequence for all possible values
337  result = evaluate_vertex_sequence( dum_box );CHECK_ERR( result );
338 }
339 
341 {
342  Core moab;
343  ScdInterface* scdi;
344  ErrorCode rval = moab.Interface::query_interface( scdi );CHECK_ERR( rval );
345 
346  HomCoord TEST_MIN_PARAMS( 0, 0, 0 );
347  HomCoord TEST_BOX_MAX( 11, 5, 2 );
348 
349  // TEST 1: single vertex sequence blocks, unity mapping
350  rval = eseq_test1a( scdi, TEST_MIN_PARAMS, TEST_BOX_MAX );CHECK_ERR( rval );
351  rval = eseq_test1b( scdi, TEST_MIN_PARAMS, TEST_BOX_MAX );CHECK_ERR( rval );
352  rval = eseq_test1c( scdi, TEST_MIN_PARAMS, TEST_BOX_MAX );CHECK_ERR( rval );
353 
354  // TEST 2: composites, 0d difference between element block "owning"
355  // vertex block and element block sharing vertex block
356  rval = eseq_test2a( scdi, TEST_MIN_PARAMS, TEST_BOX_MAX );CHECK_ERR( rval );
357  rval = eseq_test2b( scdi );CHECK_ERR( rval );
358  rval = eseq_test2c( scdi );CHECK_ERR( rval );
359  rval = eseq_test2d( scdi );CHECK_ERR( rval );
360 }
361 
363 {
364  // TEST 1a: 1d single vertex seq block, min/max = (-10,0,0)/(10,0,0)
365  // create vertex seq
366 
367  // first get 1d min/max by resetting j, k components
368  tmp_min[1] = tmp_min[2] = tmp_max[1] = tmp_max[2] = 0;
369 
370  ScdBox *ebox, *vbox;
371  ErrorCode result = scdi->create_scd_sequence( tmp_min, tmp_max, MBVERTEX, 1, vbox );CHECK_ERR( result );
372 
373  // now create the element sequence
374  result = scdi->create_scd_sequence( tmp_min, tmp_max, MBEDGE, 1, ebox );CHECK_ERR( result );
375  int num_edges = ebox->num_elements();
376  CHECK_EQUAL( ( tmp_max[0] - tmp_min[0] ), num_edges );
377 
378  // add vertex seq to element seq
379  result = ebox->add_vbox( vbox, tmp_min, tmp_min, tmp_max, tmp_max, tmp_min, tmp_min );CHECK_ERR( result );
380 
381  // check/evaluate element sequence
382  result = check_element_sequence( ebox, tmp_min, tmp_max, ebox->start_element() );CHECK_ERR( result );
383 
384  result = evaluate_element_sequence( ebox );CHECK_ERR( result );
385 
386  return result;
387 }
388 
390 {
391  // TEST 1b: 2d single vertex seq block, min/max = (-10,-5,0)/(10,5,0)
392 
393  // first get 2d min/max by resetting k component
394  tmp_min[2] = tmp_max[2] = 0;
395 
396  // get the seq manager from gMB
397  ScdBox *ebox, *vbox;
398  ErrorCode result = scdi->create_scd_sequence( tmp_min, tmp_max, MBVERTEX, 1, vbox );CHECK_ERR( result );
399 
400  // now create the element sequence
401  result = scdi->create_scd_sequence( tmp_min, tmp_max, MBQUAD, 1, ebox );CHECK_ERR( result );
402 
403  // add vertex seq to element seq; first need to construct proper 3pt input (p1 is tmp_min)
404  HomCoord p2( tmp_max.i(), tmp_min.j(), tmp_min.k() );
405  HomCoord p3( tmp_min.i(), tmp_max.j(), tmp_min.k() );
406  result = ebox->add_vbox( vbox, tmp_min, tmp_min, p2, p2, p3, p3 );CHECK_ERR( result );
407 
408  std::vector< EntityHandle > connect;
409  EntityHandle dum_ent = ebox->start_element();
410  result = scdi->impl()->get_connectivity( &dum_ent, 1, connect );CHECK_ERR( result );
411  CHECK_EQUAL( (unsigned int)connect.size(), (unsigned int)4 );
412 
413  // check/evaluate element sequence
414  result = check_element_sequence( ebox, tmp_min, tmp_max, ebox->start_element() );CHECK_ERR( result );
415 
416  result = evaluate_element_sequence( ebox );CHECK_ERR( result );
417 
418  result = access_adjacencies( ebox );CHECK_ERR( result );
419 
420  return result;
421 }
422 
423 ErrorCode eseq_test1c( ScdInterface* scdi, const HomCoord& tmp_min, const HomCoord& tmp_max )
424 {
425  // TEST 1c: 3d single vertex seq block, min/max = (-10,-5,-1)/(10,5,1)
426 
427  // get the seq manager from gMB
428  ScdBox *ebox, *vbox;
429  ErrorCode result = scdi->create_scd_sequence( tmp_min, tmp_max, MBVERTEX, 1, vbox );CHECK_ERR( result );
430 
431  // now create the element sequence
432  result = scdi->create_scd_sequence( tmp_min, tmp_max, MBHEX, 1, ebox );CHECK_ERR( result );
433 
434  // add vertex seq to element seq; first need to construct proper 3pt input (p1 is tmp_min)
435  HomCoord p2( tmp_max.i(), tmp_min.j(), tmp_min.k() );
436  HomCoord p3( tmp_min.i(), tmp_max.j(), tmp_min.k() );
437  result = ebox->add_vbox( vbox, tmp_min, tmp_min, p2, p2, p3, p3 );CHECK_ERR( result );
438 
439  // check/evaluate element sequence
440  result = check_element_sequence( ebox, tmp_min, tmp_max, ebox->start_element() );CHECK_ERR( result );
441 
442  result = evaluate_element_sequence( ebox );CHECK_ERR( result );
443 
444  result = access_adjacencies( ebox );CHECK_ERR( result );
445 
446  return result;
447 }
448 
449 ErrorCode eseq_test2a( ScdInterface* scdi, const HomCoord& tmp_min, const HomCoord& tmp_max )
450 {
451  // TEST 2a: 1d composite block, 0d difference between owning/sharing blocks
452  // create vertex seq
453 
454  ScdBox *vbox[3], *ebox[3];
455  ErrorCode result = create_1d_3_sequences( scdi, tmp_min, tmp_max, vbox, ebox );CHECK_ERR( result );
456 
457  // whew; that's done; now check and evaluate
458 
459  // first check to make sure the parameter spaces tack onto one another
460  if( ebox[0]->box_min() != tmp_min || ebox[0]->box_max() != ebox[1]->box_min() ||
461  ebox[1]->box_max() != ebox[2]->box_min() )
462  CHECK_ERR( MB_FAILURE );
463 
464  // check/evaluate element sequences
465  for( int i = 0; i < 3; i++ )
466  {
467  result = check_element_sequence( ebox[i], ebox[i]->box_min(), ebox[i]->box_max(), ebox[i]->start_element() );CHECK_ERR( result );
468 
469  result = evaluate_element_sequence( ebox[i] );CHECK_ERR( result );
470  }
471 
472  return result;
473 }
474 
476 {
477  // TEST 2b: 2d composite block, 0d difference between owning/sharing blocks
478  // create vertex seq
479 
480  ScdBox *ebox[3], *vbox[3];
481  ErrorCode result = create_2d_3_sequences( scdi, vbox, ebox );CHECK_ERR( result );
482 
483  // whew; that's done; now check and evaluate
484 
485  // first check to make sure the parameter spaces tack onto one another
486  if( ebox[0]->box_max() != HomCoord( ebox[1]->box_min().i(), ebox[1]->box_max().j(), 0 ) ||
487  ebox[1]->box_max() != HomCoord( ebox[2]->box_min().i(), ebox[2]->box_max().j(), 0 ) ||
488  // cheat on the i value of ebox0, since it's a periodic bdy (we don't check for that, so you
489  // may get different values for that parameter)
490  ebox[2]->box_max() != HomCoord( ebox[2]->box_max().i(), ebox[0]->box_max().j(), 0 ) )
491  CHECK_ERR( MB_FAILURE );
492 
493  // check/evaluate element sequences
494  for( int i = 0; i < 3; i++ )
495  {
496  result = check_element_sequence( ebox[i], ebox[i]->box_min(), ebox[i]->box_max(), ebox[i]->start_element() );CHECK_ERR( result );
497 
498  result = evaluate_element_sequence( ebox[i] );CHECK_ERR( result );
499  }
500 
501  for( int i = 0; i < 3; i++ )
502  {
503  result = access_adjacencies( ebox[i] );CHECK_ERR( result );
504  }
505 
506  return result;
507 }
508 
510 {
511  // TEST 2c: 2d composite block, 0d difference between owning/sharing blocks,
512  // tri-valent shared vertex between the three blocks
513 
514  // interval settings: only 3 of them
515  int int1 = 5, int2 = 15, int3 = 25;
516  ScdBox *ebox[3], *vbox[3];
517  ErrorCode result = create_2dtri_3_sequences( scdi, int1, int2, int3, vbox, ebox );CHECK_ERR( result );
518 
519  // whew; that's done; now check and evaluate
520 
521  // check/evaluate element sequences
522  for( int i = 0; i < 3; i++ )
523  {
524  result = check_element_sequence( ebox[i], ebox[i]->box_min(), ebox[i]->box_max(), ebox[i]->start_element() );CHECK_ERR( result );
525 
526  result = evaluate_element_sequence( ebox[i] );CHECK_ERR( result );
527  }
528 
529  for( int i = 0; i < 3; i++ )
530  {
531  result = access_adjacencies( ebox[i] );CHECK_ERR( result );
532  }
533 
534  return result;
535 }
536 
538 {
539  // TEST 2d: 3d composite block, 0d difference between owning/sharing blocks,
540  // tri-valent shared edge between the three blocks
541 
542  // interval settings: only 3 of them
543  int int1 = 10, int2 = 10, int3 = 10, int4 = 10;
544  ScdBox *ebox[3], *vbox[3];
545  ErrorCode result = create_3dtri_3_sequences( scdi, int1, int2, int3, int4, vbox, ebox );CHECK_ERR( result );
546 
547  // whew; that's done; now check and evaluate
548 
549  // check/evaluate element sequences
550  for( int i = 0; i < 3; i++ )
551  {
552  result = check_element_sequence( ebox[i], ebox[i]->box_min(), ebox[i]->box_max(), ebox[i]->start_element() );CHECK_ERR( result );
553 
554  result = evaluate_element_sequence( ebox[i] );CHECK_ERR( result );
555  }
556 
557  for( int i = 0; i < 3; i++ )
558  {
559  result = access_adjacencies( ebox[i] );CHECK_ERR( result );
560  }
561 
562  return result;
563 }
564 
566 {
567  Core moab;
568  ScdInterface* scdi;
569  ErrorCode rval = moab.Interface::query_interface( scdi );CHECK_ERR( rval );
570  HomCoord TEST_MIN_PARAMS( 0, 0, 0 );
571  HomCoord TEST_BOX_MAX( 11, 5, 2 );
572 
573  // periodic in i
574  ScdBox* new_box;
575  int lperiodic[2] = { 1, 0 };
576  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
577  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
578 
579  // periodic in j
580  lperiodic[0] = 0;
581  lperiodic[1] = 1;
582  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
583  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
584 
585  // periodic in i and j
586  lperiodic[0] = 1;
587  lperiodic[1] = 1;
588  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
589  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
590 
591  // 2d, periodic in i
592  TEST_BOX_MAX[2] = 0;
593  lperiodic[0] = 1;
594  lperiodic[1] = 0;
595  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
596  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
597 
598  // 2d, periodic in j
599  lperiodic[0] = 0;
600  lperiodic[1] = 1;
601  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
602  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
603 
604  // 2d, periodic in i and j
605  lperiodic[0] = 1;
606  lperiodic[1] = 1;
607  rval = scdi->construct_box( TEST_MIN_PARAMS, TEST_BOX_MAX, NULL, 0, new_box, lperiodic );CHECK_ERR( rval );
608  rval = evaluate_element_sequence( new_box );CHECK_ERR( rval );
609 }
610 
611 ErrorCode create_1d_3_sequences( ScdInterface* scdi, HomCoord tmp_min, HomCoord tmp_max, ScdBox** vbox, ScdBox** ebox )
612 {
613  // first get 1d min/max by resetting j, k components
614  tmp_min[1] = tmp_min[2] = tmp_max[1] = tmp_max[2] = 0;
615 
616  // split the sequence in three in i parameter, at 1/2, 1/3 and 1/6, such that the
617  // total # vertices is the expected number from tmp_max - tmp_min)
618  int idiff = ( tmp_max[0] - tmp_min[0] + 1 ) / 6;
619  HomCoord vseq0_minmax[2] = { HomCoord( tmp_min ), HomCoord( tmp_min[0] + 3 * idiff - 1, tmp_max[1], tmp_max[2] ) };
620  HomCoord vseq1_minmax[2] = { HomCoord( tmp_min ), HomCoord( tmp_min[0] + 2 * idiff - 1, tmp_max[1], tmp_max[2] ) };
621  HomCoord vseq2_minmax[2] = { HomCoord( tmp_min ), HomCoord( tmp_max[0] - 5 * idiff, tmp_max[1], tmp_max[2] ) };
622 
623  // create three vertex sequences
624  vbox[0] = vbox[1] = vbox[2] = NULL;
625 
626  // first vertex sequence
627  ErrorCode result = scdi->create_scd_sequence( vseq0_minmax[0], vseq0_minmax[1], MBVERTEX, 1, vbox[0] );CHECK_ERR( result );
628 
629  // second vertex sequence
630  result = scdi->create_scd_sequence( vseq1_minmax[0], vseq1_minmax[1], MBVERTEX, 1, vbox[1] );CHECK_ERR( result );
631 
632  // third vertex sequence
633  result = scdi->create_scd_sequence( vseq2_minmax[0], vseq2_minmax[1], MBVERTEX, 1, vbox[2] );CHECK_ERR( result );
634 
635  // now create the three element sequences
636  ebox[0] = ebox[1] = ebox[2] = NULL;
637 
638  // create the first element sequence
639  result = scdi->create_scd_sequence( vseq0_minmax[0], vseq0_minmax[1], MBEDGE, 1, ebox[0] );CHECK_ERR( result );
640 
641  // add first vertex seq to first element seq, forward orientation, unity transform
642  result = ebox[0]->add_vbox( vbox[0], vseq0_minmax[0], vseq0_minmax[0], vseq0_minmax[1], vseq0_minmax[1],
643  vseq0_minmax[0], vseq0_minmax[0] );CHECK_ERR( result );
644 
645  // create the second element sequence; make it use the second vseq in reverse and start
646  // with the end vertex of the first sequence; parameterize it such that it tacks onto the
647  // end of the previous ebox
648  result = scdi->create_scd_sequence(
649  HomCoord( vseq0_minmax[1].i(), 0, 0 ),
650  HomCoord( 1 + vseq0_minmax[1].i() + vseq1_minmax[1].i() - vseq1_minmax[0].i(), 0, 0 ), MBEDGE, 1, ebox[1] );CHECK_ERR( result );
651 
652  // add shared vertex from first vseq to this ebox; parameter space should be the same since
653  // we're adding to that parameter space
654  result = ebox[1]->add_vbox( vbox[0], vseq0_minmax[0], vseq0_minmax[0], vseq0_minmax[1], vseq0_minmax[1],
655  vseq0_minmax[0], vseq0_minmax[0], true, HomCoord( ebox[1]->box_min().i(), 0, 0 ),
656  HomCoord( ebox[1]->box_min().i(), 0, 0 ) );CHECK_ERR( result );
657 
658  // add second vseq to this ebox, but reversed; parameter space should be such that the
659  // last vertex in the second vseq occurs first, and so on
660  result = ebox[1]->add_vbox( vbox[1], vseq1_minmax[1], ebox[1]->box_min() + HomCoord::getUnitv( 0 ), vseq1_minmax[0],
661  ebox[1]->box_max(), vseq1_minmax[1], ebox[1]->box_min() + HomCoord::getUnitv( 0 ) );CHECK_ERR( result );
662 
663  // create the third element sequence; make it use the third vseq (forward sense) and start
664  // with the start vertex of the second vseq; parameterize it such that it tacks onto the
665  // end of the previous ebox
666  result = scdi->create_scd_sequence(
667  ebox[1]->box_max(), HomCoord( ebox[1]->box_max().i() + 1 + vseq2_minmax[1].i() - vseq2_minmax[0].i(), 0, 0 ),
668  MBEDGE, 1, ebox[2] );CHECK_ERR( result );
669 
670  // add shared vertex from second vseq to this ebox; parameter space mapping such that we get
671  // first vertex only of that vseq
672  result = ebox[2]->add_vbox( vbox[1], vseq0_minmax[0], ebox[2]->box_min(), vseq0_minmax[0] + HomCoord::getUnitv( 0 ),
673  ebox[2]->box_min() - HomCoord::getUnitv( 0 ), vseq0_minmax[0], ebox[2]->box_min(), true,
674  ebox[2]->box_min(), ebox[2]->box_min() );CHECK_ERR( result );
675 
676  // add third vseq to this ebox, forward orientation
677  result = ebox[2]->add_vbox( vbox[2], vseq2_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 0 ), vseq2_minmax[1],
678  ebox[2]->box_max(), vseq1_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 0 ) );CHECK_ERR( result );
679 
680  return result;
681 }
682 
684 {
685  // create 3 rectangular sequences attached end to end and back (periodic); sequences are
686  // assorted orientations, sequences have globally-consistent (periodic in i) parameter space
687 
688  // set vbox parametric spaces directly
689  HomCoord vbox0_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( 5, 5, 0 ) };
690  HomCoord vbox1_minmax[2] = { HomCoord( -2, 4, 0 ), HomCoord( 8, 9, 0 ) };
691  HomCoord vbox2_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( 8, 5, 0 ) };
692 
693  // create three vertex sequences
694  vbox[0] = vbox[1] = vbox[2] = NULL;
695 
696  // first vertex sequence
697  ErrorCode result = scdi->create_scd_sequence( vbox0_minmax[0], vbox0_minmax[1], MBVERTEX, 1, vbox[0] );CHECK_ERR( result );
698 
699  // second vertex sequence
700  result = scdi->create_scd_sequence( vbox1_minmax[0], vbox1_minmax[1], MBVERTEX, 1, vbox[1] );CHECK_ERR( result );
701 
702  // third vertex sequence
703  result = scdi->create_scd_sequence( vbox2_minmax[0], vbox2_minmax[1], MBVERTEX, 1, vbox[2] );CHECK_ERR( result );
704 
705  // now create the three element sequences
706  ebox[0] = ebox[1] = ebox[2] = NULL;
707 
708  // create the first element sequence
709  result = scdi->create_scd_sequence( vbox0_minmax[0], vbox0_minmax[1], MBQUAD, 1, ebox[0] );CHECK_ERR( result );
710 
711  // add first vertex seq to first element seq, forward orientation, unity transform
712  result = ebox[0]->add_vbox( vbox[0],
713  // p1: imin,jmin
714  vbox0_minmax[0], vbox0_minmax[0],
715  // p2: imax,jmin
716  HomCoord( vbox0_minmax[1].i(), vbox0_minmax[0].j(), 0 ),
717  HomCoord( vbox0_minmax[1].i(), vbox0_minmax[0].j(), 0 ),
718  // p3: imin,jmax
719  HomCoord( vbox0_minmax[0].i(), vbox0_minmax[1].j(), 0 ),
720  HomCoord( vbox0_minmax[0].i(), vbox0_minmax[1].j(), 0 ) );
721 
722  CHECK_ERR( result );
723 
724  // create the second element sequence; make it use the right side of the first vbox;
725  // parameterize it such that it tacks onto imax of the previous ebox
726  result = scdi->create_scd_sequence( HomCoord( ebox[0]->box_max().i(), ebox[0]->box_min().j(), 0 ),
727  HomCoord( vbox0_minmax[1].i() + 1 + vbox1_minmax[1].i() - vbox1_minmax[0].i(),
728  ebox[0]->box_max().j(), 0 ),
729  MBQUAD, 1, ebox[1] );CHECK_ERR( result );
730 
731  // add shared side from first vbox to this ebox; parameter space should be the same since
732  // we're adding to that parameter space
733  result =
734  ebox[1]->add_vbox( vbox[0],
735  // p1: lower right of box 0, lower left of box 1
736  HomCoord( vbox0_minmax[1].i(), vbox0_minmax[0].j(), 0 ), ebox[1]->box_min(),
737  // p2: one up from p1
738  HomCoord( vbox0_minmax[1].i(), vbox0_minmax[0].j(), 0 ) + HomCoord::getUnitv( 1 ),
739  ebox[1]->box_min() + HomCoord::getUnitv( 1 ),
740  // p3: one right of p1
741  HomCoord( vbox0_minmax[1].i(), vbox0_minmax[0].j(), 0 ) + HomCoord::getUnitv( 0 ),
742  ebox[1]->box_min() + HomCoord::getUnitv( 0 ),
743  // set bb such that it's the right side of the vbox, left of local ebox
744  true, ebox[1]->box_min(), HomCoord( ebox[1]->box_min().i(), ebox[1]->box_max().j(), 0 ) );CHECK_ERR( result );
745 
746  // add second vbox to this ebox, with different orientation but all of it (no bb input)
747  result = ebox[1]->add_vbox( vbox[1],
748  // p1: one right of top left of ebox1
749  vbox1_minmax[0], HomCoord( ebox[1]->box_min().i() + 1, ebox[1]->box_max().j(), 0 ),
750  // p2: one right from p1
751  vbox1_minmax[0] + HomCoord::getUnitv( 0 ),
752  HomCoord( ebox[1]->box_min().i() + 2, ebox[1]->box_max().j(), 0 ),
753  // p3: one down from p1
754  vbox1_minmax[0] + HomCoord::getUnitv( 1 ),
755  HomCoord( ebox[1]->box_min().i() + 1, ebox[1]->box_max().j() - 1, 0 ) );CHECK_ERR( result );
756 
757  // create the third element sequence; make it use the third vbox (middle) as well as the side of
758  // the second sequence (left) and a side of the first sequence (right); parameterize it such
759  // that it tacks onto the end of the previous ebox and the beginning of the 1st sequence (i.e.
760  // periodic in i)
761  result =
762  scdi->create_scd_sequence( HomCoord( ebox[1]->box_max().i(), ebox[1]->box_min().j(), 0 ),
763  // add one extra for each of left and right sides
764  HomCoord( ebox[1]->box_max().i() + 1 + vbox2_minmax[1].i() - vbox2_minmax[0].i() + 1,
765  ebox[1]->box_max().j(), 0 ),
766  MBEDGE, 1, ebox[2] );CHECK_ERR( result );
767 
768  // add shared side from second vbox to this ebox; parameter space mapping such that we get
769  // a side only of that vbox
770  result =
771  ebox[2]->add_vbox( vbox[1],
772  // p1: bottom left
773  vbox1_minmax[1], ebox[2]->box_min(),
774  // p2: one right from p1
775  vbox1_minmax[1] + HomCoord::getUnitv( 0 ), ebox[2]->box_min() + HomCoord::getUnitv( 0 ),
776  // p3: one up
777  vbox1_minmax[1] - HomCoord::getUnitv( 1 ), ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
778  // bb input such that we only get left side of ebox parameter space
779  true, ebox[2]->box_min(), HomCoord( ebox[2]->box_min().i(), ebox[2]->box_max().j(), 0 ) );CHECK_ERR( result );
780 
781  // add shared side from first vbox to this ebox; parameter space mapping such that we get
782  // a side only of that vbox
783  result = ebox[2]->add_vbox(
784  vbox[0],
785  // p1: bottom right
786  vbox0_minmax[0], HomCoord( ebox[2]->box_max().i(), ebox[2]->box_min().j(), 0 ),
787  // p2: one right from p1
788  vbox0_minmax[0] + HomCoord::getUnitv( 0 ), HomCoord( ebox[2]->box_max().i() + 1, ebox[2]->box_min().j(), 0 ),
789  // p3: one up from p1
790  vbox0_minmax[0] + HomCoord::getUnitv( 1 ), HomCoord( ebox[2]->box_max().i(), ebox[2]->box_min().j() + 1, 0 ),
791  // bb input such that we only get left side of ebox parameter space
792  true, HomCoord( ebox[2]->box_max().i(), ebox[2]->box_min().j(), 0 ), ebox[2]->box_max() );CHECK_ERR( result );
793 
794  // add third vbox to this ebox
795  result =
796  ebox[2]->add_vbox( vbox[2],
797  // p1: top right and left one
798  vbox2_minmax[0], ebox[2]->box_max() - HomCoord::getUnitv( 0 ),
799  // p2: one left of p1
800  vbox2_minmax[0] + HomCoord::getUnitv( 0 ), ebox[2]->box_max() - HomCoord::getUnitv( 0 ) * 2,
801  // p3: one down from p1
802  vbox2_minmax[0] + HomCoord::getUnitv( 1 ),
803  ebox[2]->box_max() - HomCoord::getUnitv( 0 ) - HomCoord::getUnitv( 1 ) );CHECK_ERR( result );
804 
805  return result;
806 }
807 
809  const int int1,
810  const int int2,
811  const int int3,
812  ScdBox** vbox,
813  ScdBox** ebox )
814 {
815  // create 3 rectangular sequences arranged such that the all share a common (tri-valent) corner;
816  // orient each region such that its origin is at the tri-valent corner and the k direction is
817  // out of the page
818  //
819  // int1 and int2 controls the i and j intervals in region 0, int3 follows from that.
820 
821  // input is 3 interval settings controlling the 3 degrees of freedom on the interfacesp
822 
823  // set vbox parametric spaces directly from int1-3
824  // use 0-based parameterization on vbox's just for fun, which means we'll have to transform into
825  // ebox system
826  HomCoord vbox0_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int1, int2, 0 ) };
827  HomCoord vbox1_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int3 - 1, int1, 0 ) };
828  HomCoord vbox2_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int2 - 1, int3 - 1, 0 ) };
829 
830  // create three vertex sequences
831  vbox[0] = vbox[1] = vbox[2] = NULL;
832 
833  // first vertex sequence
834  ErrorCode result = scdi->create_scd_sequence( vbox0_minmax[0], vbox0_minmax[1], MBVERTEX, 1, vbox[0] );CHECK_ERR( result );
835 
836  // second vertex sequence
837  result = scdi->create_scd_sequence( vbox1_minmax[0], vbox1_minmax[1], MBVERTEX, 1, vbox[1] );CHECK_ERR( result );
838 
839  // third vertex sequence
840  result = scdi->create_scd_sequence( vbox2_minmax[0], vbox2_minmax[1], MBVERTEX, 1, vbox[2] );CHECK_ERR( result );
841 
842  // now create the three element sequences
843 
844  // set ebox parametric spaces directly from int1-3
845  // use 0-based parameterization on ebox's just for fun, which means we'll have to transform into
846  // ebox system
847  HomCoord ebox0_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int1, int2, 0 ) };
848  HomCoord ebox1_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int3, int1, 0 ) };
849  HomCoord ebox2_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int2, int3, 0 ) };
850 
851  ebox[0] = ebox[1] = ebox[2] = NULL;
852 
853  // create the first element sequence
854  result = scdi->create_scd_sequence( ebox0_minmax[0], ebox0_minmax[1], MBQUAD, 1, ebox[0] );CHECK_ERR( result );
855 
856  // only need to add one vbox to this, unity transform
857  result = ebox[0]->add_vbox( vbox[0],
858  // trick: if I know it's going to be unity, just input
859  // 3 sets of equivalent points
860  vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0],
861  vbox0_minmax[0] );
862 
863  CHECK_ERR( result );
864 
865  // create the second element sequence
866  result = scdi->create_scd_sequence( ebox1_minmax[0], ebox1_minmax[1], MBQUAD, 1, ebox[1] );CHECK_ERR( result );
867 
868  // add shared side from first vbox to this ebox, with bb to get just the line
869  result =
870  ebox[1]->add_vbox( vbox[0],
871  // p1: origin in both systems
872  vbox0_minmax[0], ebox0_minmax[0],
873  // p2: one unit along the shared line (i in one, j in other)
874  vbox0_minmax[0] + HomCoord::getUnitv( 0 ), ebox0_minmax[0] + HomCoord::getUnitv( 1 ),
875  // p3: arbitrary
876  vbox0_minmax[0], ebox0_minmax[0],
877  // set bb such that it's the jmin side of vbox
878  true, ebox[1]->box_min(), HomCoord( ebox[1]->box_min().i(), ebox[1]->box_max().j(), 0 ) );CHECK_ERR( result );
879 
880  // add second vbox to this ebox, with different orientation but all of it (no bb input)
881  result = ebox[1]->add_vbox( vbox[1],
882  // p1: origin/i+1 (vbox/ebox)
883  vbox1_minmax[0], ebox1_minmax[0] + HomCoord::getUnitv( 0 ),
884  // p2: j+1 from p1
885  vbox1_minmax[0] + HomCoord::getUnitv( 1 ),
886  ebox1_minmax[0] + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ),
887  // p3: i+1 from p1
888  vbox1_minmax[0] + HomCoord::getUnitv( 0 ),
889  ebox[1]->box_min() + HomCoord::getUnitv( 0 ) * 2 );CHECK_ERR( result );
890 
891  // create the third element sequence
892  result = scdi->create_scd_sequence( ebox2_minmax[0], ebox2_minmax[1], MBQUAD, 1, ebox[2] );CHECK_ERR( result );
893 
894  // add shared side from second vbox to this ebox
895  result =
896  ebox[2]->add_vbox( vbox[1],
897  // p1: origin/j+1 (vbox/ebox)
898  vbox1_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
899  // p2: i+1/j+2 (vbox/ebox)
900  vbox1_minmax[0] + HomCoord::getUnitv( 0 ), ebox[2]->box_min() + HomCoord::getUnitv( 1 ) * 2,
901  // p3: arbitrary
902  vbox1_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
903  // bb input such that we only get one side of ebox parameter space
904  true, ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
905  HomCoord( ebox[2]->box_min().i(), ebox[2]->box_max().j(), 0 ) );CHECK_ERR( result );
906 
907  // add shared side from first vbox to this ebox
908  result = ebox[2]->add_vbox( vbox[0],
909  // p1: origin/origin
910  vbox1_minmax[0], ebox2_minmax[0],
911  // p2: j+1/i+1
912  vbox1_minmax[0] + HomCoord::getUnitv( 1 ), ebox2_minmax[0] + HomCoord::getUnitv( 0 ),
913  // p3: arbitrary
914  vbox1_minmax[0], ebox2_minmax[0],
915  // bb input such that we only get one side of ebox parameter space
916  true, ebox2_minmax[0], HomCoord( ebox2_minmax[1].i(), ebox2_minmax[0].j(), 0 ) );CHECK_ERR( result );
917 
918  // add third vbox to this ebox
919  result = ebox[2]->add_vbox( vbox[2],
920  // p1: origin/i+1,j+1
921  vbox2_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ),
922  // p2: i+1 from p1
923  vbox2_minmax[0] + HomCoord::getUnitv( 0 ),
924  ebox[2]->box_min() + HomCoord::getUnitv( 0 ) * 2 + HomCoord::getUnitv( 1 ),
925  // p3: j+1 from p1
926  vbox2_minmax[0] + HomCoord::getUnitv( 1 ),
927  ebox[2]->box_min() + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ) * 2 );CHECK_ERR( result );
928 
929  return result;
930 }
931 
933  const int int1,
934  const int int2,
935  const int int3,
936  const int int4,
937  ScdBox** vbox,
938  ScdBox** ebox )
939 {
940  // create 3 brick sequences arranged such that the all share a common (tri-valent) edge;
941  // orient each region similarly to the 2dtri_3_sequences test problem, swept into 3d in the
942  // positive k direction. This direction is divided into int4 intervals
943  //
944  // int1 and int2 controls the i and j intervals in region 0, int3 follows from that; int4
945  // divides the k axis
946 
947  // input is 4 interval settings controlling the 4 degrees of freedom on the interfacesp
948 
949  // set vbox parametric spaces directly from int1-4
950  // use 0-based parameterization on vbox's just for fun, which means we'll have to transform into
951  // ebox system
952  HomCoord vbox0_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int1, int2, int4 ) };
953  HomCoord vbox1_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int3 - 1, int1, int4 ) };
954  HomCoord vbox2_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int2 - 1, int3 - 1, int4 ) };
955 
956  // create three vertex sequences
957  vbox[0] = vbox[1] = vbox[2] = NULL;
958 
959  // first vertex sequence
960  ErrorCode result = scdi->create_scd_sequence( vbox0_minmax[0], vbox0_minmax[1], MBVERTEX, 1, vbox[0] );CHECK_ERR( result );
961 
962  // second vertex sequence
963  result = scdi->create_scd_sequence( vbox1_minmax[0], vbox1_minmax[1], MBVERTEX, 1, vbox[1] );CHECK_ERR( result );
964 
965  // third vertex sequence
966  result = scdi->create_scd_sequence( vbox2_minmax[0], vbox2_minmax[1], MBVERTEX, 1, vbox[2] );CHECK_ERR( result );
967 
968  // now create the three element sequences
969 
970  // set ebox parametric spaces directly from int1-4
971  // use 0-based parameterization on ebox's just for fun, which means we'll have to transform into
972  // ebox system
973  HomCoord ebox0_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int1, int2, int4 ) };
974  HomCoord ebox1_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int3, int1, int4 ) };
975  HomCoord ebox2_minmax[2] = { HomCoord( 0, 0, 0 ), HomCoord( int2, int3, int4 ) };
976 
977  ebox[0] = ebox[1] = ebox[2] = NULL;
978 
979  // create the first element sequence
980  result = scdi->create_scd_sequence( ebox0_minmax[0], ebox0_minmax[1], MBHEX, 1, ebox[0] );CHECK_ERR( result );
981 
982  // only need to add one vbox to this, unity transform
983  result = ebox[0]->add_vbox( vbox[0],
984  // trick: if I know it's going to be unity, just input
985  // 3 sets of equivalent points
986  vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0], vbox0_minmax[0],
987  vbox0_minmax[0] );
988 
989  CHECK_ERR( result );
990 
991  // create the second element sequence
992  result = scdi->create_scd_sequence( ebox1_minmax[0], ebox1_minmax[1], MBHEX, 1, ebox[1] );CHECK_ERR( result );
993 
994  // add shared side from first vbox to this ebox, with bb to get just the face
995  result = ebox[1]->add_vbox( vbox[0],
996  // p1: origin in both systems
997  vbox0_minmax[0], ebox1_minmax[0],
998  // p2: one unit along the shared line (i in one, j in other)
999  vbox0_minmax[0] + HomCoord::getUnitv( 0 ), ebox1_minmax[0] + HomCoord::getUnitv( 1 ),
1000  // p3: +k in both (not arbitrary, since interface is 2d)
1001  vbox0_minmax[0] + HomCoord::getUnitv( 2 ), ebox1_minmax[0] + HomCoord::getUnitv( 2 ),
1002  // set bb such that it's the jmin side of vbox
1003  true, ebox[1]->box_min(),
1004  HomCoord( ebox[1]->box_min().i(), ebox[1]->box_max().j(), ebox[1]->box_max().k() ) );CHECK_ERR( result );
1005 
1006  // add second vbox to this ebox, with different orientation but all of it (no bb input)
1007  result = ebox[1]->add_vbox( vbox[1],
1008  // p1: origin/i+1 (vbox/ebox)
1009  vbox1_minmax[0], ebox1_minmax[0] + HomCoord::getUnitv( 0 ),
1010  // p2: j+1 from p1
1011  vbox1_minmax[0] + HomCoord::getUnitv( 1 ),
1012  ebox1_minmax[0] + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ),
1013  // p3: i+1 from p1
1014  vbox1_minmax[0] + HomCoord::getUnitv( 0 ),
1015  ebox[1]->box_min() + HomCoord::getUnitv( 0 ) * 2 );CHECK_ERR( result );
1016 
1017  // create the third element sequence
1018  result = scdi->create_scd_sequence( ebox2_minmax[0], ebox2_minmax[1], MBHEX, 1, ebox[2] );CHECK_ERR( result );
1019 
1020  // add shared side from second vbox to this ebox
1021  result =
1022  ebox[2]->add_vbox( vbox[1],
1023  // p1: origin/j+1 (vbox/ebox)
1024  vbox1_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
1025  // p2: i+1/j+2 (vbox/ebox)
1026  vbox1_minmax[0] + HomCoord::getUnitv( 0 ), ebox[2]->box_min() + HomCoord::getUnitv( 1 ) * 2,
1027  // p3: +k in both (not arbitrary, since interface is 2d)
1028  vbox1_minmax[0] + HomCoord::getUnitv( 2 ),
1029  ebox[2]->box_min() + HomCoord::getUnitv( 1 ) + HomCoord::getUnitv( 2 ),
1030  // bb input such that we only get one side of ebox parameter space
1031  true, ebox[2]->box_min() + HomCoord::getUnitv( 1 ),
1032  HomCoord( ebox[2]->box_min().i(), ebox[2]->box_max().j(), ebox[2]->box_max().k() ) );CHECK_ERR( result );
1033 
1034  // add shared side from first vbox to this ebox
1035  result = ebox[2]->add_vbox( vbox[0],
1036  // p1: origin/origin
1037  vbox0_minmax[0], ebox2_minmax[0],
1038  // p2: j+1/i+1
1039  vbox0_minmax[0] + HomCoord::getUnitv( 1 ), ebox2_minmax[0] + HomCoord::getUnitv( 0 ),
1040  // p3: +k in both (not arbitrary, since interface is 2d)
1041  vbox0_minmax[0] + HomCoord::getUnitv( 2 ), ebox[2]->box_min() + HomCoord::getUnitv( 2 ),
1042  // bb input such that we only get one side of ebox parameter space
1043  true, ebox2_minmax[0],
1044  HomCoord( ebox2_minmax[1].i(), ebox2_minmax[0].j(), ebox2_minmax[1].k() ) );CHECK_ERR( result );
1045 
1046  // add third vbox to this ebox
1047  result = ebox[2]->add_vbox( vbox[2],
1048  // p1: origin/i+1,j+1
1049  vbox2_minmax[0], ebox[2]->box_min() + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ),
1050  // p2: i+1 from p1
1051  vbox2_minmax[0] + HomCoord::getUnitv( 0 ),
1052  ebox[2]->box_min() + HomCoord::getUnitv( 0 ) * 2 + HomCoord::getUnitv( 1 ),
1053  // p3: j+1 from p1
1054  vbox2_minmax[0] + HomCoord::getUnitv( 1 ),
1055  ebox[2]->box_min() + HomCoord::getUnitv( 0 ) + HomCoord::getUnitv( 1 ) * 2 );CHECK_ERR( result );
1056 
1057  return result;
1058 }
1059 
1061 {
1062  // access the adjacencies in this box in a few places
1063  HomCoord box_size = box->box_size(), box_min = box->box_min(), box_max = box->box_max();
1064 
1065  EntityHandle dum_entity;
1066  const EntityHandle* connect;
1067  int num_connect;
1068  ErrorCode rval;
1069  bool is_2d = ( box_size.k() <= 1 );
1070 
1071  // edges first; bottom:
1072  for( int dir = 0; dir < 3; dir++ )
1073  {
1074  // don't do 3rd direction for 2d box
1075  if( 2 == dir && is_2d ) continue;
1076 
1077  rval = box->get_adj_edge_or_face( 1, box_min.i(), box_min.j(), box_min.k(), dir, dum_entity, true );
1078  if( MB_SUCCESS != rval ) return rval;
1079 
1080  // do a simple API call on that entity to make sure we can
1081  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1082  if( MB_SUCCESS != rval ) return rval;
1083  }
1084  // middle:
1085  for( int dir = 0; dir < 3; dir++ )
1086  {
1087  // don't do 3rd direction for 2d box
1088  if( 2 == dir && is_2d ) continue;
1089 
1090  rval = box->get_adj_edge_or_face( 1, box_min.i() + .5 * box_size.i(), box_min.j() + .5 * box_size.j(),
1091  box_min.k() + .5 * box_size.k(), dir, dum_entity, true );
1092  if( MB_SUCCESS != rval ) return rval;
1093 
1094  // do a simple API call on that entity to make sure we can
1095  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1096  if( MB_SUCCESS != rval ) return rval;
1097  }
1098 
1099  // top:
1100  for( int dir = 0; dir < 3; dir++ )
1101  {
1102  // don't do 3rd direction for 2d box
1103  if( 2 == dir && is_2d ) continue;
1104 
1105  rval = box->get_adj_edge_or_face( 1, ( box_max.i() == box_min.i() ? box_max.i() : box_max.i() - 1 ),
1106  ( box_max.j() == box_min.j() ? box_max.j() : box_max.j() - 1 ),
1107  ( box_max.k() == box_min.k() ? box_max.k() : box_max.k() - 1 ), dir,
1108  dum_entity, true );
1109  if( MB_SUCCESS != rval ) return rval;
1110 
1111  // do a simple API call on that entity to make sure we can
1112  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1113  if( MB_SUCCESS != rval ) return rval;
1114  }
1115 
1116  if( is_2d ) return MB_SUCCESS;
1117 
1118  // now faces; bottom:
1119  for( int dir = 0; dir < 3; dir++ )
1120  {
1121  rval = box->get_adj_edge_or_face( 2, box_min.i(), box_min.j(), box_min.k(), dir, dum_entity, true );
1122  if( MB_SUCCESS != rval ) return rval;
1123 
1124  // do a simple API call on that entity to make sure we can
1125  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1126  if( MB_SUCCESS != rval ) return rval;
1127  }
1128  // middle:
1129  for( int dir = 0; dir < 3; dir++ )
1130  {
1131  // don't do 3rd direction for 2d box
1132  if( 2 == dir && is_2d ) continue;
1133 
1134  rval = box->get_adj_edge_or_face( 2, box_min.i() + .5 * box_size.i(), box_min.j() + .5 * box_size.j(),
1135  box_min.k() + .5 * box_size.k(), dir, dum_entity, true );
1136  if( MB_SUCCESS != rval ) return rval;
1137 
1138  // do a simple API call on that entity to make sure we can
1139  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1140  if( MB_SUCCESS != rval ) return rval;
1141  }
1142 
1143  // top:
1144  for( int dir = 0; dir < 3; dir++ )
1145  {
1146  // don't do 3rd direction for 2d box
1147  if( 2 == dir && is_2d ) continue;
1148 
1149  rval = box->get_adj_edge_or_face( 2, ( box_max.i() == box_min.i() ? box_max.i() : box_max.i() - 1 ),
1150  ( box_max.j() == box_min.j() ? box_max.j() : box_max.j() - 1 ),
1151  ( box_max.k() == box_min.k() ? box_max.k() : box_max.k() - 1 ), dir,
1152  dum_entity, true );
1153  if( MB_SUCCESS != rval ) return rval;
1154 
1155  // do a simple API call on that entity to make sure we can
1156  rval = box->sc_impl()->impl()->get_connectivity( dum_entity, connect, num_connect );
1157  if( MB_SUCCESS != rval ) return rval;
1158  }
1159 
1160  return MB_SUCCESS;
1161 }
1162 
1164 {
1165 
1166  Core moab;
1167  ScdInterface* scdi;
1168  ErrorCode rval = moab.Interface::query_interface( scdi );CHECK_ERR( rval );
1169  int gdims[] = { 0, 0, 0, 48, 40, 18 };
1170 
1171  // test for various numbers of procs, powers of two
1172  int maxpow = 4;
1173 
1174  int fails = 0;
1175  for( int exp = 2; exp <= maxpow; exp += 2 )
1176  {
1177  int nprocs = 0.1 + pow( 2.0, (double)exp );
1178 
1179  // alljorkori
1181  if( MB_SUCCESS != rval ) fails++;
1182 
1183  // alljkbal
1185  if( MB_SUCCESS != rval ) fails++;
1186 
1187  // sqij
1188  rval = test_parallel_partition( gdims, nprocs, ScdParData::SQIJ );
1189  if( MB_SUCCESS != rval ) fails++;
1190 
1191  // sqjk
1192  rval = test_parallel_partition( gdims, nprocs, ScdParData::SQJK );
1193  if( MB_SUCCESS != rval ) fails++;
1194 
1195  // sqijk
1196  rval = test_parallel_partition( gdims, nprocs, ScdParData::SQIJK );
1197  if( MB_SUCCESS != rval ) fails++;
1198  }
1199 
1200  if( fails ) CHECK_ERR( MB_FAILURE );
1201 }
1202 
1203 ErrorCode test_parallel_partition( int* gdims, int nprocs, int part_method )
1204 {
1205  ErrorCode rval;
1206  int pto, pfrom, across_bdy_a[3], across_bdy_b[3], rdims_a[6], rdims_b[6], facedims_a[6], facedims_b[6], ldims[6],
1207  lper[3], pijk[3];
1208  ScdParData spd;
1209  for( int i = 0; i < 6; i++ )
1210  spd.gDims[i] = gdims[i];
1211  for( int i = 0; i < 3; i++ )
1212  spd.gPeriodic[i] = 0;
1213  spd.partMethod = part_method;
1214  int fails = 0;
1215 
1216  for( int p = 0; p < nprocs / 2; p++ )
1217  {
1218  rval = ScdInterface::compute_partition( nprocs, p, spd, ldims, lper, pijk );
1219  if( MB_SUCCESS != rval ) continue;
1220 
1221  for( int k = -1; k <= 1; k++ )
1222  {
1223  for( int j = -1; j <= 1; j++ )
1224  {
1225  for( int i = -1; i <= 1; i++ )
1226  {
1227  int dijka[] = { i, j, k }, dijkb[] = { -i, -j, -k };
1228  rval = ScdInterface::get_neighbor( nprocs, p, spd, dijka, pto, rdims_a, facedims_a, across_bdy_a );
1229  if( MB_SUCCESS != rval ) return rval;
1230  if( -1 == pto ) continue;
1231 
1232  bool fail = false;
1233  if( facedims_a[0] < rdims_a[0] || facedims_a[0] > rdims_a[3] || facedims_a[1] < rdims_a[1] ||
1234  facedims_a[1] > rdims_a[4] || facedims_a[2] < rdims_a[2] || facedims_a[2] > rdims_a[5] )
1235  fail = true;
1236 
1237  // non-negative value of pto; check corresponding input from that proc to this
1238 
1239  rval =
1240  ScdInterface::get_neighbor( nprocs, pto, spd, dijkb, pfrom, rdims_b, facedims_b, across_bdy_b );
1241  if( MB_SUCCESS != rval ) return rval;
1242  for( int ind = 0; ind < 3; ind++ )
1243  if( facedims_a[ind] < rdims_b[ind] || facedims_b[ind] > rdims_b[ind + 3] ) fail = true;
1244  for( int ind = 0; ind < 6; ind++ )
1245  {
1246  if( facedims_a[ind] != facedims_b[ind] || rdims_b[ind] != ldims[ind] ) fail = true;
1247  }
1248  if( across_bdy_a[0] != across_bdy_b[0] || across_bdy_a[1] != across_bdy_b[1] ) fail = true;
1249 #define PARRAY( a ) "(" << ( a )[0] << "," << ( a )[1] << "," << ( a )[2] << ")"
1250 #define PARRAY3( a, b, c ) "(" << ( a ) << "," << ( b ) << "," << ( c ) << ")"
1251 #define PARRAY6( a ) PARRAY( a ) << "-" << PARRAY( ( ( a ) + 3 ) )
1252  if( fail )
1253  {
1254  fails++;
1255  for( int l = 0; l < 3; l++ )
1256  spd.pDims[l] = pijk[l];
1257  std::cerr << "partMeth = " << part_method << ", p/np = " << p << "/" << nprocs
1258  << ", (i,j,k) = " << PARRAY3( i, j, k ) << ", ldims = " << PARRAY6( ldims )
1259  << std::endl
1260  << "facedims_a = " << PARRAY6( facedims_a )
1261  << ", facedims_b = " << PARRAY6( facedims_b ) << std::endl
1262  << "rdims_a = " << PARRAY6( rdims_a ) << ", rdims_b = " << PARRAY6( rdims_b )
1263  << std::endl;
1264  std::cerr << "ScdParData: " << spd << std::endl;
1265  }
1266  } // i
1267  } // j
1268  } // k
1269  } // p
1270 
1271  return ( fails ? MB_FAILURE : MB_SUCCESS );
1272 }