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   /*!
18     MBTest.cpp
19     Test Harness for MB mesh database system
20   */
21 
22 #ifdef WIN32
23 #ifdef _DEBUG
24   // turn off warnings that say they debugging identifier has been truncated
25   // this warning comes up when using some STL containers
26 #pragma warning(disable : 4786)
27 #endif
28 #endif
29 
30 #include <iostream>
31 #include <fstream>
32 #include <algorithm>
33 #include <cstdio>
34 #include <time.h>
35 #include <assert.h>
36 #include <math.h>
37 #include <stdio.h>
38 #include "moab/Interface.hpp"
39 #include "MBTagConventions.hpp"
40 #include "moab/Range.hpp"
41 #include "moab/Skinner.hpp"
42 #include "moab/MeshTopoUtil.hpp"
43 #include "moab/CN.hpp"
44 #include "moab/OrientedBox.hpp"
45 #include "moab/CartVect.hpp"
46 #include "moab/WriteUtilIface.hpp"
47 
48 #ifdef MOAB_HAVE_MPI
49 #include "moab_mpi.h"
50 #endif
51 
52 #ifndef IS_BUILDING_MB
53 #define IS_BUILDING_MB
54 #endif
55 #include "Internals.hpp"
56 #include "moab/Core.hpp"
57 #include "SequenceManager.hpp"
58 #include "EntitySequence.hpp"
59 #include "RangeSeqIntersectIter.hpp"
60 #include "moab/Error.hpp"
61 #include "moab/ScdInterface.hpp"
62 
63 /* Use the following define to specify that our tests
64    return an error code and not the default void */
65 #define TEST_USES_ERR_CODES
66 #include "TestUtil.hpp"
67 
68 using namespace std;
69 using namespace moab;
70 
71 #define CHKERR(A) do { if (MB_SUCCESS != (A)) { \
72   std::cerr << "Failure (error code " << (A) << ") at " __FILE__ ":" \
73             << __LINE__ << std::endl; \
74   return A; } } while(false)
75 
76 
77 #ifdef MOAB_HAVE_NETCDF
load_file_one(Interface * iface)78 ErrorCode load_file_one( Interface* iface )
79 {
80   std::string file_name = TestDir + "/mbtest1.g";
81   ErrorCode error = iface->load_mesh( file_name.c_str() );
82   if (MB_SUCCESS != error) {
83     std::cout << "Failed to load input file: " << file_name << std::endl;
84     std::string error_reason;
85     iface->get_last_error(error_reason);
86     cout << error_reason << std::endl;
87   }
88   return error;
89 }
90 #endif
91 
92 /* Create a regular 2x2x2 hex mesh */
93 ErrorCode create_some_mesh( Interface* iface );
94 
95 ErrorCode check_valid_connectivity( Interface* iface );
96 
97 
98   /*!
99     @test
100     Vertex Coordinates
101     @li Get coordinates of vertex 1 correctly
102     @li Get coordinates of vertex 8 correctly
103     @li Get coordinates of vertex 6 correctly
104   */
mb_vertex_coordinate_test()105 ErrorCode mb_vertex_coordinate_test()
106 {
107   Core moab;
108   Interface* MB = &moab;
109   ErrorCode error = create_some_mesh( MB );
110   MB_CHK_ERR(error);
111 
112   Range vertices;
113   error = MB->get_entities_by_type(0,  MBVERTEX, vertices);
114   MB_CHK_ERR(error);
115 
116   std::vector<double> all_coords(3*vertices.size());
117   double* coord_iter = &all_coords[0];
118   for ( Range::iterator iter = vertices.begin();
119         iter != vertices.end(); ++iter)
120   {
121     error = MB->get_coords(&(*iter), 1, coord_iter );
122     MB_CHK_ERR(error);
123     coord_iter += 3;
124   }
125 
126     // check blocked coordinates
127   const size_t N = vertices.size()+1;
128   std::vector<double> x(N), y(N), z(N);
129     // set last value so we can check later that nothing wrote past the
130     // intended end of an array
131   x[vertices.size()] = y[vertices.size()] = z[vertices.size()] = -3.14159;
132   error = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
133   for (size_t i = 0; i < vertices.size(); ++i) {
134     CHECK_REAL_EQUAL( all_coords[3*i  ], x[i], 1E-12 );
135     CHECK_REAL_EQUAL( all_coords[3*i+1], y[i], 1E-12 );
136     CHECK_REAL_EQUAL( all_coords[3*i+2], z[i], 1E-12 );
137   }
138     // checkthat get_coords did not write past intended end of arrays
139   CHECK_REAL_EQUAL( -3.14159, x[vertices.size()], 1E-12 );
140   CHECK_REAL_EQUAL( -3.14159, y[vertices.size()], 1E-12 );
141   CHECK_REAL_EQUAL( -3.14159, z[vertices.size()], 1E-12 );
142 
143     // add invalid handle to end of range and try query again
144   vertices.insert( vertices.back() + 1 );
145   error = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
146   CHECK_EQUAL( MB_ENTITY_NOT_FOUND, error );
147 
148     // Try getting coordinates for a hex (should fail)
149   Range hexes;
150   error = MB->get_entities_by_type( 0, MBHEX, hexes );MB_CHK_ERR(error);
151   EntityHandle handle = hexes.front();
152   error = MB->get_coords(&handle, 1, &x[0]);MB_CHK_ERR(error);
153   CHECK_REAL_EQUAL(0.5, x[0], 1E-12);
154   CHECK_REAL_EQUAL(0.5, x[1], 1E-12);
155   CHECK_REAL_EQUAL(0.5, x[2], 1E-12);
156 
157   return MB_SUCCESS;
158 }
159 
160   /*!
161     @test
162     MB Vertex Tag Test
163     @li Add, Set and correctly get an int tag
164     @li Add, Set and correctly get a boolean tag
165     @li Add, Set and correctly get a double tag
166     @li Add, Set and correctly get a struct tag
167   */
mb_vertex_tag_test()168 ErrorCode mb_vertex_tag_test()
169 {
170   Core moab;
171   Interface* MB = &moab;
172   ErrorCode error = create_some_mesh( MB );
173   if (MB_SUCCESS != error)
174     return error;
175 
176     // Add an int Vertex Tag to the database
177 
178   Tag tag_id;
179 
180     // Create a dense tag for all vertices
181   error = MB->tag_get_handle("int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE|MB_TAG_EXCL);
182   if (error != MB_SUCCESS)
183     return error;
184 
185     // put a value in vertex 1 and retrieve
186   std::vector<EntityHandle> verts;
187   error = MB->get_entities_by_type( 0, MBVERTEX, verts );
188   if (MB_SUCCESS != error) return error;
189   EntityHandle handle = verts[0];
190   int input_value = 11;
191   error = MB->tag_set_data(tag_id, &handle, 1, &input_value);
192   if (MB_SUCCESS != error) return error;
193 
194   int output_value;
195   error = MB->tag_get_data(tag_id, &handle, 1, &output_value);
196   if(MB_SUCCESS != error) return error;
197   else if (output_value != input_value)
198     return MB_FAILURE;
199 
200     // put a value in vertex 5 and retrieve
201 
202   handle = verts[5];
203   input_value = 11;
204   error = MB->tag_set_data(tag_id, &handle, 1, &input_value);
205   if (MB_SUCCESS != error) return error;
206   error = MB->tag_get_data(tag_id, &handle, 1, &output_value);
207   if (MB_SUCCESS != error) return error;
208   else if(output_value != input_value)
209     return MB_FAILURE;
210 
211     // put a value in vertex 98088234 which doesn't exist
212   handle = *std::max_element( verts.begin(), verts.end() ) + 1;
213   input_value = 11;
214 
215   error = MB->tag_set_data(tag_id, &handle, 1, &input_value);
216   if (error == MB_SUCCESS)
217     return error;
218 
219   error = MB->tag_get_data(tag_id, &handle, 1, &output_value);
220   if (error == MB_SUCCESS)
221     return error;
222 
223   if(output_value != input_value)
224     return MB_FAILURE;
225 
226     // Add a bool Vertex Tag to the database
227 
228   error = MB->tag_get_handle("bool_tag", sizeof(bool), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE|MB_TAG_EXCL);
229   if (error != MB_SUCCESS)
230     return error;
231 
232     // put a value in vertex 5 and retrieve
233 
234   handle = verts[5];
235   bool bool_input_value = true;
236   bool bool_output_value = false;
237   error = MB->tag_set_data(tag_id, &handle, 1, &bool_input_value);
238   if (error != MB_SUCCESS) return error;
239   error = MB->tag_get_data(tag_id, &handle, 1, &bool_output_value);
240   if (error != MB_SUCCESS) return error;
241   else if(bool_output_value != bool_input_value)
242     return MB_FAILURE;
243 
244     // Add a double Vertex Tag to the database
245 
246   error = MB->tag_get_handle("double_tag", 1, MB_TYPE_DOUBLE, tag_id, MB_TAG_SPARSE|MB_TAG_EXCL);
247   if (error != MB_SUCCESS)
248     return error;
249 
250     // put a value in vertex 8: and retrieve
251 
252   handle = verts[8];
253   double double_input_value = 1.0;
254   double double_output_value = 0.0;
255   error = MB->tag_set_data(tag_id, &handle, 1, &double_input_value);
256   if (error != MB_SUCCESS) return error;
257 
258   error = MB->tag_get_data(tag_id, &handle, 1, &double_output_value);
259   if (error != MB_SUCCESS) return error;
260   else if(double_output_value != double_input_value)
261     return MB_FAILURE;
262 
263     // Add a struct Vertex Tag to the database
264 
265   struct TagStruct {
266     int test_int;
267     double test_double;
268   };
269   error = MB->tag_get_handle("struct_tag", sizeof(TagStruct), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE|MB_TAG_EXCL);
270   if (error != MB_SUCCESS)
271     return error;
272 
273     // put a value in vertex 7 and retrieve
274 
275   handle = verts[7];
276   TagStruct input_tag_struct;
277   input_tag_struct.test_int = 55;
278   input_tag_struct.test_double = -1.2345;
279   TagStruct output_tag_struct;
280   error = MB->tag_set_data(tag_id, &handle, 1, &input_tag_struct);
281   if (error != MB_SUCCESS) return error;
282   error = MB->tag_get_data(tag_id, &handle, 1, &output_tag_struct);
283   if (error != MB_SUCCESS) return error;
284   else if(output_tag_struct.test_int != input_tag_struct.test_int ||
285           output_tag_struct.test_double != input_tag_struct.test_double)
286     return MB_FAILURE;
287 
288 
289     // Create sparse tags for 10 random entities including some outside the
290     // range of allowable entities.
291 
292   error = MB->tag_get_handle("sparse_int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE|MB_TAG_EXCL);
293 
294   if (error != MB_SUCCESS )
295     return error;
296 
297     //print_yes = true;
298   int i;
299   for (i=0; i<10; i++)
300   {
301       // use invalid handles for odd values
302 
303     if (i % 2)
304       handle = verts[i] + *std::max_element( verts.begin(), verts.end() );
305     else
306       handle = verts[i];
307 
308     input_value = 11;
309     error = MB->tag_set_data(tag_id, &handle, 1, &input_value);
310 
311       // should fail on odd values of i
312     if ( !(i % 2) )
313     {
314       if (error != MB_SUCCESS )  // even case and if failed
315         return error;
316     }
317     else
318     {
319       if ( error == MB_SUCCESS)  // odd case and it says it worked!
320         return MB_FAILURE;
321     }
322 
323 
324     error = MB->tag_get_data(tag_id, &handle, 1, &output_value);
325     if ( (i % 2) && error != MB_FAILURE && error != MB_TAG_NOT_FOUND)
326       return error;
327 
328     if( (i % 2) && output_value != input_value)
329       return MB_FAILURE;
330   }
331 
332     // get the tag_name of the last tag created above
333   std::string int_tag_name;
334   error = MB->tag_get_name (tag_id, int_tag_name);
335   if (error != MB_SUCCESS)
336     return error;
337 
338   if (int_tag_name != "sparse_int_tag")
339     return MB_FAILURE;
340 
341     // get the tag handle of the last tag created above
342   Tag int_tag_handle;
343   error = MB->tag_get_handle (int_tag_name.c_str(), 1, MB_TYPE_INTEGER, int_tag_handle);
344   if (MB_SUCCESS != error) return error;
345 
346   if (int_tag_handle != tag_id)
347     return MB_FAILURE;
348 
349     // test tag_get_tags_on_entity and tag_delete_data
350   std::vector<Tag> all_tags;
351   handle = verts[0];
352   error = MB->tag_get_tags_on_entity(handle, all_tags);
353   if (MB_SUCCESS != error)
354     return error;
355 
356   if (!all_tags.empty()) {
357     error = MB->tag_delete_data(all_tags[0], &handle, 1);
358     if (MB_SUCCESS != error)
359       return error;
360 
361     error = MB->tag_delete(all_tags[0]);
362     if (MB_SUCCESS != error)
363       return error;
364   }
365     // delete tags test
366 
367     // delete 2 of the sparse tags that were created above.
368   handle = verts[2];
369   error = MB->tag_delete_data(tag_id, &handle, 1);
370   if (error != MB_SUCCESS )
371     return error;
372 
373   handle = verts[6];
374   error = MB->tag_delete_data(tag_id, &handle, 1);
375   if (error != MB_SUCCESS )
376     return error;
377 
378     // delete all the rest of the sparse tags.
379 
380   error = MB->tag_delete(tag_id);
381   if (error != MB_SUCCESS )
382     return error;
383 
384     // delete the dense tag named bool_tag
385   Tag bool_tag_handle;
386   error = MB->tag_get_handle ("bool_tag", sizeof(bool), MB_TYPE_OPAQUE, bool_tag_handle);
387   if (error != MB_SUCCESS) return error;
388 
389   error = MB->tag_delete(bool_tag_handle);
390   if (error != MB_SUCCESS )
391     return error;
392 
393   return error;
394 }
395 
396 
mb_temporary_test()397 ErrorCode mb_temporary_test()
398 {
399   Core moab;
400   Interface* gMB = &moab;
401 
402   double array[3] = {0.0, 0.0, 0.0};
403   EntityHandle h_node1;
404   ErrorCode result = gMB->create_vertex(array, h_node1);
405   if (MB_SUCCESS != result)
406     return result;
407 
408   EntityHandle ordered_meshset1;
409   result = gMB->create_meshset(MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset1);
410   if (MB_SUCCESS != result)
411     return result;
412 
413   EntityHandle ordered_meshset2;
414   result = gMB->create_meshset(MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset2);
415   if (MB_SUCCESS != result)
416     return result;
417 
418   result = gMB->add_entities(ordered_meshset1, &h_node1, 1);
419   if (MB_SUCCESS != result)
420     return result;
421 
422   result = gMB->remove_entities(ordered_meshset1, &h_node1, 1);
423   if (MB_SUCCESS != result)
424     return result;
425 
426   result = gMB->add_entities(ordered_meshset2, &h_node1, 1);
427   if (MB_SUCCESS != result)
428     return result;
429 
430   bool create_if_missing = false;
431   std::vector<EntityHandle> meshsets;
432   result = gMB->get_adjacencies(&h_node1, 1, 4, create_if_missing, meshsets);
433   if (MB_SUCCESS != result)
434     return result;
435 
436   if (1u != meshsets.size())
437     return MB_FAILURE;
438 
439   return MB_SUCCESS;
440 }
441 
mb_adjacent_vertex_test()442 ErrorCode mb_adjacent_vertex_test()
443 {
444   Core moab;
445   Interface* mb = &moab;
446   ErrorCode rval = create_some_mesh( mb );
447   if (MB_SUCCESS != rval)
448     return rval;
449 
450   Range hexes, expt_vert, got_vert, some_hexes;
451   Range::const_iterator i, j;
452   int n;
453 
454     // get all hexes
455   rval = mb->get_entities_by_type( 0, MBHEX, hexes );
456   if (rval != MB_SUCCESS)
457     return rval;
458   if (hexes.empty())  // can't do test if no elements
459     return MB_FAILURE;
460 
461     // get every third hex and its vertices
462   n = 0;
463   for (i = hexes.begin(); i != hexes.end(); ++i) {
464     if (++n % 3)
465       continue;
466     some_hexes.insert( *i );
467     const EntityHandle* conn;
468     int len;
469     rval = mb->get_connectivity( *i, conn, len );
470     if (MB_SUCCESS != rval)
471       return rval;
472     for (int k = 0; k < len; ++k)
473       expt_vert.insert( conn[k] );
474   }
475 
476     // use get_adjacencies to get vertices
477   rval = mb->get_adjacencies( some_hexes, 0, false, got_vert, Interface::UNION );
478   if (MB_SUCCESS != rval) {
479     std::cout << "get_adjacencies failed with error code " << rval << std::endl;
480     return rval;
481   }
482 
483   i = expt_vert.begin();
484   j = got_vert.begin();
485   while (i != expt_vert.end() && j != got_vert.end()) {
486     if (*i < *j) {
487       std::cout << "Result missing vertex: " << *i << std::endl;
488       return MB_FAILURE;
489     }
490     else if (*j < *i) {
491       std::cout << "Result contains extra vertex: " << *j << std::endl;
492       return MB_FAILURE;
493     }
494     ++i;
495     ++j;
496   }
497 
498   if (i != expt_vert.end()) {
499     std::cout << "Result missing vertex: " << *i << std::endl;
500     return MB_FAILURE;
501   }
502   else if (j != got_vert.end()) {
503     std::cout << "Result contains extra vertex: " << *j << std::endl;
504     return MB_FAILURE;
505   }
506 
507   return MB_SUCCESS;
508 }
509 #ifdef MOAB_HAVE_NETCDF
mb_adjacencies_test()510 ErrorCode mb_adjacencies_test()
511 {
512   Core moab;
513   Interface* mb = &moab;
514   ErrorCode result = load_file_one( mb );
515   if (MB_SUCCESS != result)
516     return result;
517 
518     // this test does the following:
519     // 1. For each element, creates vertex-element adjacencies (only for
520     //    lowest-id vertex)
521     // 2. Creates all lower-order ancillary entities
522     // 3. Checks for proper number of same
523     //
524     // assume mesh has already been read
525 
526   EntityType seq_type;
527   Range handle_range;
528 
529     // lets create a skin of the hexes
530     // this may be far from being the most efficient, but
531     // it certainly does exercise the adjacency routines
532 
533   Range::iterator iter;
534   Range::reverse_iterator riter;
535 
536     // first get the hexes
537   Range hexes;
538   result = mb->get_entities_by_type(0, MBHEX, hexes);
539   if (MB_SUCCESS != result)
540     return result;
541 
542 
543   unsigned int num_hexes = hexes.size();
544 
545     // make sure we got hexes
546   for(riter = hexes.rbegin(); riter != hexes.rend(); ++riter)
547   {
548     if( TYPE_FROM_HANDLE(*riter) != MBHEX)
549       return MB_FAILURE;
550   }
551 
552 
553 
554     // get all the nodes that these hexes are connected to
555   Range nodes;
556   result = mb->get_adjacencies(hexes, 0, false, nodes, Interface::UNION);
557   if (MB_SUCCESS != result)
558     return result;
559 
560     // make sure we got nodes
561   for(iter = nodes.begin(); iter != nodes.end(); ++iter)
562   {
563     if( TYPE_FROM_HANDLE(*iter) != MBVERTEX)
564       return MB_FAILURE;
565   }
566 
567     // find the interior nodes; assume a structured mesh
568   Range interior_nodes;
569   std::vector<EntityHandle> attached_hexes;
570   for( iter = nodes.begin(); iter != nodes.end();)
571   {
572     attached_hexes.clear();
573     result = mb->get_adjacencies(&(*iter), 1, 3, false, attached_hexes);
574     if (MB_SUCCESS != result)
575       return result;
576     attached_hexes.erase(std::remove_if(attached_hexes.begin(),
577                                         attached_hexes.end(),
578                                         type_not_equals(mb, MBHEX)),
579                          attached_hexes.end());
580 
581 
582 
583       // if this node has less than 8 hexes attached to it, it is not
584       // an interior node
585     if (attached_hexes.size() == 8)
586     {
587         // add to the interior nodes list and remove from the nodes list
588       interior_nodes.insert(*iter);
589       iter = nodes.erase(iter);
590     }
591     else
592       ++iter;
593 
594   }
595 
596     // get interior quads from interior nodes
597   Range interior_quads;
598   result = mb->get_adjacencies(interior_nodes, 2, true, interior_quads, Interface::UNION);
599   if (MB_SUCCESS != result)
600     return result;
601 
602     // get a list of quads generated adjacent to the exterior nodes
603   Range temp_quads, exterior_quads;
604   result = mb->get_adjacencies(nodes, 2, true, temp_quads, Interface::UNION);
605   if (MB_SUCCESS != result)
606     return result;
607 
608     // now remove any interior quads from the previous quads list
609     // and we should be left with exterior quads
610   std::set_difference(temp_quads.begin(), temp_quads.end(),
611                       interior_quads.begin(), interior_quads.end(),
612                       range_inserter(exterior_quads));
613 
614     // check to make sure we have the right number of quads; for hexes, should be
615     // .5(6*num_hexes - num_exterior_quads)
616   unsigned int num_expected_int_quads = (6*num_hexes - exterior_quads.size())/2;
617   if (num_expected_int_quads != interior_quads.size())
618     return MB_FAILURE;
619 
620     // delete the interior quads
621   result = mb->delete_entities(interior_quads);
622   if (MB_SUCCESS != result)
623     return result;
624 
625   Range remaining_quads;
626   result = mb->get_entities_by_type(0, MBQUAD, remaining_quads);
627   if (MB_SUCCESS != result)
628     return result;
629 
630   if(remaining_quads.size() != exterior_quads.size())
631     return MB_FAILURE;
632 
633 
634     // 3. Checks for proper number of same
635     // re-retrieve and store the handle ranges for all element types
636 
637   int num_ents;
638 
639   for (seq_type = MBEDGE; seq_type != MBENTITYSET; seq_type++)
640   {
641     handle_range.clear();
642 
643     result = mb->get_entities_by_type(0, seq_type, handle_range);
644     if (MB_SUCCESS != result)
645       return result;
646 
647     result = mb->get_number_entities_by_type(0, seq_type, num_ents);
648     if (MB_SUCCESS != result)
649       return result;
650 
651     if(handle_range.size() != (unsigned int) num_ents)
652       return MB_FAILURE;
653   }
654 
655   return result;
656 
657 }
658 
659 #endif
660 
mb_adjacencies_create_delete_test()661 ErrorCode mb_adjacencies_create_delete_test()
662 {
663   Core moab;
664   Interface* mb = &moab;
665   ErrorCode rval;
666 
667   double coords[] = { 0, 0, 0, 2, 0, 0, 1, 2, 0 };
668   Range verts;
669   rval = mb->create_vertices( coords, 3, verts );
670   if (MB_SUCCESS != rval)
671     return rval;
672   if (verts.size() != 3)
673     return MB_FAILURE;
674   EntityHandle vert_arr[3];
675 
676   EntityHandle tri;
677   std::copy( verts.begin(), verts.end(), vert_arr );
678   rval = mb->create_element( MBTRI, vert_arr, 3, tri );
679   if (MB_SUCCESS != rval)
680     return rval;
681 
682   vert_arr[2] = vert_arr[0];
683   EntityHandle forward_edge, reverse_edge;
684   rval = mb->create_element( MBEDGE, vert_arr, 2, forward_edge );
685   if (MB_SUCCESS != rval)
686     return rval;
687 
688   std::vector<EntityHandle> results;
689   rval = mb->get_adjacencies( &forward_edge, 1, 2, false, results );
690   if (results.size() != 1 || results.front() != tri) {
691     std::cerr << "Adjacency query from forward edge to tri failed at "
692               << __FILE__ <<  ":" << __LINE__ << std::endl;
693     return MB_FAILURE;
694   }
695   results.clear();
696   rval = mb->get_adjacencies( &tri, 1, 1, false, results );
697   if (results.size() != 1 || results.front() != forward_edge) {
698     std::cerr << "Adjacency query from tri to forward edge failed at "
699               << __FILE__ <<  ":" << __LINE__ << std::endl;
700     return MB_FAILURE;
701   }
702 
703   rval = mb->delete_entities( &forward_edge, 1 );
704   if (MB_SUCCESS != rval)
705     return rval;
706 
707   results.clear();
708   rval = mb->get_adjacencies( &tri, 1, 1, false, results );
709   if (!results.empty()) {
710     std::cerr << "Adjacency query from tri returned non-existent edge at "
711               << __FILE__ <<  ":" << __LINE__ << std::endl;
712     return MB_FAILURE;
713   }
714 
715   rval = mb->create_element( MBEDGE, vert_arr+1, 2, reverse_edge );
716   if (MB_SUCCESS != rval)
717     return rval;
718 
719   results.clear();
720   rval = mb->get_adjacencies( &reverse_edge, 1, 2, false, results );
721   if (results.size() != 1 || results.front() != tri) {
722     std::cerr << "Adjacency query from reverse edge to tri failed at "
723               << __FILE__ <<  ":" << __LINE__ << std::endl;
724     return MB_FAILURE;
725   }
726   results.clear();
727   rval = mb->get_adjacencies( &tri, 1, 1, false, results );
728   if (results.size() != 1 || results.front() != reverse_edge) {
729     std::cerr << "Adjacency query from tri to reverse edge failed at "
730               << __FILE__ <<  ":" << __LINE__ << std::endl;
731     return MB_FAILURE;
732   }
733 
734   return MB_SUCCESS;
735 }
736 
create_two_hex_full_mesh(Interface * mb,EntityHandle vertices[12],EntityHandle hexes[2],EntityHandle hex1_faces[6],EntityHandle hex2_faces[6],EntityHandle hex1_edges[12],EntityHandle hex2_edges[12])737 static ErrorCode create_two_hex_full_mesh( Interface* mb,
738                                              EntityHandle vertices[12],
739                                              EntityHandle hexes[2],
740                                              EntityHandle hex1_faces[6],
741                                              EntityHandle hex2_faces[6],
742                                              EntityHandle hex1_edges[12],
743                                              EntityHandle hex2_edges[12] )
744 {
745   ErrorCode rval;
746  // create a simple mesh containing 2 hexes
747   const double coords[] = { 0, 0, 0,
748                             1, 0, 0,
749                             2, 0, 0,
750                             0, 1, 0,
751                             1, 1, 0,
752                             2, 1, 0,
753                             0, 0, 1,
754                             1, 0, 1,
755                             2, 0, 1,
756                             0, 1, 1,
757                             1, 1, 1,
758                             2, 1, 1 };
759   for (int i = 0; i < 12; ++i)
760     if (MB_SUCCESS != mb->create_vertex( coords + 3*i, vertices[i] ))
761       return MB_FAILURE;
762   EntityHandle hex1_conn[] = { vertices[6], vertices[7], vertices[1], vertices[0],
763                                  vertices[9], vertices[10],vertices[4], vertices[3] };
764   EntityHandle hex2_conn[] = { vertices[7], vertices[8], vertices[2], vertices[1],
765                                  vertices[10],vertices[11],vertices[5], vertices[4] };
766   EntityHandle shared_quad_conn[] = { vertices[7], vertices[1], vertices[4], vertices[10] };
767   EntityHandle hex1_face_conn[][4] = {
768     { vertices[6], vertices[7], vertices[10],vertices[9] },
769     { vertices[7], vertices[6], vertices[0], vertices[1] },
770     { vertices[1], vertices[0], vertices[3], vertices[4] },
771     { vertices[9], vertices[10],vertices[4], vertices[3] },
772     { vertices[3], vertices[0], vertices[6], vertices[9] } };
773   EntityHandle hex2_face_conn[][4] = {
774     { vertices[7], vertices[8], vertices[11],vertices[10] },
775     { vertices[8], vertices[7], vertices[1], vertices[2] },
776     { vertices[2], vertices[1], vertices[4], vertices[5] },
777     { vertices[10],vertices[11],vertices[5], vertices[4] },
778     { vertices[5], vertices[2], vertices[8], vertices[11] } };
779   EntityHandle shared_edge_conn[][2] = { { vertices[1], vertices[7] },
780                                            { vertices[7], vertices[10]},
781                                            { vertices[10],vertices[4] },
782                                            { vertices[4], vertices[1] } };
783   EntityHandle hex1_edge_conn[][2] = { { vertices[6], vertices[7] },
784                                          { vertices[9], vertices[10] },
785                                          { vertices[3], vertices[4] },
786                                          { vertices[0], vertices[1] },
787                                          { vertices[6], vertices[9] },
788                                          { vertices[9], vertices[3] },
789                                          { vertices[3], vertices[0] },
790                                          { vertices[0], vertices[6] } };
791   EntityHandle hex2_edge_conn[][2] = { { vertices[7], vertices[8] },
792                                          { vertices[10], vertices[11] },
793                                          { vertices[4], vertices[5] },
794                                          { vertices[1], vertices[2] },
795                                          { vertices[8], vertices[11] },
796                                          { vertices[11], vertices[5] },
797                                          { vertices[5], vertices[2] },
798                                          { vertices[2], vertices[8] } };
799   rval = mb->create_element( MBHEX, hex1_conn, 8, hexes[0] );
800   if (MB_SUCCESS != rval)
801     return rval;
802   rval = mb->create_element( MBHEX, hex2_conn, 8, hexes[1] );
803   if (MB_SUCCESS != rval)
804     return rval;
805   rval = mb->create_element( MBQUAD, shared_quad_conn, 4, hex1_faces[0] );
806   if (MB_SUCCESS != rval)
807     return rval;
808   hex2_faces[0] = hex1_faces[0];
809   for (int i = 0; i < 5; ++i) {
810     rval = mb->create_element( MBQUAD, hex1_face_conn[i], 4, hex1_faces[i+1] );
811     if (MB_SUCCESS != rval)
812       return rval;
813     rval = mb->create_element( MBQUAD, hex2_face_conn[i], 4, hex2_faces[i+1] );
814     if (MB_SUCCESS != rval)
815       return rval;
816   }
817   for (int i = 0; i < 4; ++i) {
818     rval = mb->create_element( MBEDGE, shared_edge_conn[i], 2, hex1_edges[i] );
819     if (MB_SUCCESS != rval)
820       return rval;
821     hex2_edges[i] = hex1_edges[i];
822   }
823   for (int i = 0; i < 8; ++i) {
824     rval = mb->create_element( MBEDGE, hex1_edge_conn[i], 2, hex1_edges[i+4] );
825     if (MB_SUCCESS != rval)
826       return rval;
827     rval = mb->create_element( MBEDGE, hex2_edge_conn[i], 2, hex2_edges[i+4] );
828     if (MB_SUCCESS != rval)
829       return rval;
830   }
831   return MB_SUCCESS;
832 }
833 
mb_upward_adjacencies_test()834 ErrorCode mb_upward_adjacencies_test()
835 {
836   ErrorCode rval;
837   Core moab;
838   Interface* mb = &moab;
839 
840   // create a simple mesh containing 2 hexes
841   EntityHandle vertices[12], hexes[2], hex1_faces[6], hex2_faces[6], hex1_edges[12], hex2_edges[12];
842   rval = create_two_hex_full_mesh( mb, vertices, hexes, hex1_faces, hex2_faces, hex1_edges, hex2_edges );
843   MB_CHK_ERR(rval);
844 
845     // test adjacences from dim to 3
846   for (int dim = 0; dim < 3; ++dim) {
847     std::vector<EntityHandle> hex1_ent, hex2_ent, shared;
848     const EntityHandle *list1, *list2;
849     int n;
850     switch (dim) {
851       case 0:
852         rval = mb->get_connectivity( hexes[0], list1, n );
853         MB_CHK_ERR(rval);
854         rval = mb->get_connectivity( hexes[1], list2, n );
855         MB_CHK_ERR(rval);
856         break;
857       case 1:
858         list1 = hex1_edges;
859         list2 = hex2_edges;
860         n = 12;
861         break;
862       case 2:
863         list1 = hex1_faces;
864         list2 = hex2_faces;
865         n = 6;
866         break;
867     }
868       // split entities into those uniquely in hex1, those uniquely in hex2
869       // and those shared between the two
870     for (int i = 0; i < n; ++i) {
871       if (std::find(list2, list2+n, list1[i]) - list2 == n)
872         hex1_ent.push_back(list1[i]);
873       else
874         shared.push_back(list1[i]);
875       if (std::find(list1, list1+n, list2[i]) - list1 == n)
876         hex2_ent.push_back(list2[i]);
877     }
878       // for each shared entity check that get_adjacencies returns both hexes
879     for (size_t j = 0; j < shared.size(); ++j) {
880       std::vector<EntityHandle> adj;
881       rval = mb->get_adjacencies( &shared[j], 1, 3, false, adj );
882       MB_CHK_ERR(rval);
883       if (adj.size() != 2) {
884         std::cout << "Expected 2 hexes adjacent to " << dim << "D entity " << j
885                   << ". Got " << adj.size() << " hexes." << std::endl;
886         return MB_FAILURE;
887       }
888       if (!(adj[0] == hexes[0] && adj[1] == hexes[1]) &&
889           !(adj[0] == hexes[1] && adj[1] == hexes[0])) {
890         std::cout << "Got incorrect hexes adjacent to " << dim << "D entity " << j << std::endl;
891         return MB_FAILURE;
892       }
893     }
894 
895     for (size_t j = 0; j < hex1_ent.size(); ++j) {
896       std::vector<EntityHandle> adj;
897       rval = mb->get_adjacencies( &hex1_ent[j], 1, 3, false, adj );
898       MB_CHK_ERR(rval);
899       CHECK(adj.size() == 1 && adj[0] == hexes[0]);
900     }
901 
902     for (size_t j = 0; j < hex2_ent.size(); ++j) {
903       std::vector<EntityHandle> adj;
904       rval = mb->get_adjacencies( &hex2_ent[j], 1, 3, false, adj );
905       MB_CHK_ERR(rval);
906       CHECK(adj.size() == 1 && adj[0] == hexes[1]);
907     }
908   }
909 
910     // For each edge, get adjacent faces, and for each face
911     // get adjacent hexes.  Result should be the same as
912     // direct query from edges to hexes
913   std::vector<EntityHandle> all_edges(24);
914   std::copy( hex1_edges, hex1_edges+12, all_edges.begin() );
915   std::copy( hex2_edges, hex2_edges+12, all_edges.begin()+12 );
916   std::sort( all_edges.begin(), all_edges.end() );
917   all_edges.erase( std::unique(all_edges.begin(), all_edges.end()), all_edges.end() );
918   for (size_t j = 0; j < all_edges.size(); ++j) {
919     std::vector<EntityHandle> edge_hexes, edge_faces, face_hexes;
920     rval = mb->get_adjacencies( &all_edges[j], 1, 3, false, edge_hexes );
921     MB_CHK_ERR(rval);
922     rval = mb->get_adjacencies( &all_edges[j], 1, 2, false, edge_faces );
923     MB_CHK_ERR(rval);
924     rval = mb->get_adjacencies( &edge_faces[0], edge_faces.size(), 3,
925                                 false, face_hexes, Interface::UNION );
926     MB_CHK_ERR(rval);
927     if (edge_hexes.size() != face_hexes.size()) {
928       std::cout << "Inconsistent adjacency data for edge " << j
929                 << ". edge->face->hex resulted in " << face_hexes.size()
930                 << "hexes while edge->hex resulted in " << edge_hexes.size()
931                 << std::endl;
932       return MB_FAILURE;
933     }
934     switch (edge_hexes.size()) {
935       case 1:
936         CHECK(edge_hexes[0] == face_hexes[0]);
937         break;
938       case 2:
939         CHECK((edge_hexes[0] == face_hexes[0] && edge_hexes[1] == face_hexes[1]) ||
940               (edge_hexes[0] == face_hexes[1] && edge_hexes[1] == face_hexes[0]));
941         break;
942       default:
943         std::cout << "Got " << edge_hexes.size() << " hexes adjacent to edge " << j << std::endl;
944         return MB_FAILURE;
945     }
946   }
947   return MB_SUCCESS;
948 }
949 
mb_adjacent_create_test()950 ErrorCode mb_adjacent_create_test()
951 {
952   Core moab;
953   Interface& mb = moab;
954   ErrorCode rval;
955 
956     // create vertices
957   const double coords[][3] =
958     { {-0.5, -0.5,  0.5 },
959       {-0.5, -0.5, -0.5 },
960       {-0.5,  0.5, -0.5 },
961       {-0.5,  0.5,  0.5 },
962       { 0.5, -0.5,  0.5 },
963       { 0.5, -0.5, -0.5 },
964       { 0.5,  0.5, -0.5 },
965       { 0.5,  0.5,  0.5 } };
966   EntityHandle verts[8] = {0};
967   for (int i = 0; i < 8; ++i) {
968     rval = mb.create_vertex( coords[i], verts[i] );
969     MB_CHK_ERR(rval);
970   }
971     // create a single hex
972   const EntityHandle hconn[8] = { verts[0], verts[1], verts[2], verts[3],
973                                   verts[4], verts[5], verts[6], verts[7] };
974   EntityHandle hex;
975   rval = mb.create_element( MBHEX, hconn, 8, hex );
976   MB_CHK_ERR(rval);
977     // create hex faces
978   std::vector<EntityHandle> quads;
979   rval = mb.get_adjacencies( &hex, 1, 2, true, quads, Interface::UNION );
980   MB_CHK_ERR(rval);
981   CHECK_EQUAL( (size_t)6, quads.size() );
982     // check that we got each of the 6 expected faces, with outwards
983     // normals assuming CCW order and correct connectivity
984   const EntityHandle faces[6][4] = {
985     { verts[0], verts[1], verts[5], verts[4] },
986     { verts[1], verts[2], verts[6], verts[5] },
987     { verts[2], verts[3], verts[7], verts[6] },
988     { verts[3], verts[0], verts[4], verts[7] },
989     { verts[3], verts[2], verts[1], verts[0] },
990     { verts[4], verts[5], verts[6], verts[7] } };
991   for (int i = 0; i < 6; ++i) { // for each expected face
992     // get sorted list of verts first for easy comparison
993     std::vector<EntityHandle> exp_sorted(4);
994     std::copy( faces[i], faces[i]+4, exp_sorted.begin() );
995     std::sort( exp_sorted.begin(), exp_sorted.end() );
996     // search for matching face in output
997     int j = 0;
998     std::vector<EntityHandle> conn;
999     for (; j < 6; ++j) {
1000       conn.clear();
1001       rval = mb.get_connectivity( &quads[j], 1, conn );
1002       MB_CHK_ERR(rval);
1003       CHECK_EQUAL( (size_t)4, conn.size() );
1004       std::vector<EntityHandle> sorted(conn);
1005       std::sort( sorted.begin(), sorted.end() );
1006       if (sorted == exp_sorted)
1007         break;
1008     }
1009     if (j == 6) {
1010       std::cerr << "No adjacent face matching hex face " << i << std::endl;
1011       CHECK(j<6);
1012     }
1013     // check order
1014     int k = std::find( conn.begin(), conn.end(), faces[i][0] ) - conn.begin();
1015     for (j = 1; j < 4; ++j)
1016       if (faces[i][j] != conn[(j+k)%4])
1017         break;
1018     if (j != 4) {
1019       std::cerr << "Incorrect vertex order for hex face " << i << std::endl;
1020       std::cerr << "Expected: " << faces[i][0] << ", " << faces[i][1] << ", "
1021                                 << faces[i][2] << ", " << faces[i][3] << std::endl;
1022       std::cerr << "Actual:   " << conn[0] << ", " << conn[1] << ", "
1023                                 << conn[2] << ", " << conn[3] << std::endl;
1024       CHECK(false);
1025     }
1026   }
1027   return MB_SUCCESS;
1028 }
1029 
nothing_but_type(Range & range,EntityType type)1030 ErrorCode nothing_but_type( Range& range, EntityType type )
1031 {
1032 
1033     //make sure there's nothing but hexes in hex_ms
1034   Range::iterator iter, end_iter;
1035   iter = range.begin();
1036   end_iter = range.end();
1037 
1038   for(; iter != end_iter; ++iter)
1039   {
1040     if( TYPE_FROM_HANDLE(*iter) != type )
1041     {
1042       return MB_FAILURE;
1043     }
1044   }
1045   return MB_SUCCESS;
1046 }
1047 
check_esets(Interface * MB,const int num_sets)1048 ErrorCode check_esets(Interface * MB, const int num_sets)
1049 {
1050   int entity_sets_size;
1051   ErrorCode result = MB->get_number_entities_by_type(0, MBENTITYSET, entity_sets_size);
1052   if (MB_SUCCESS != result ||
1053       entity_sets_size != num_sets) return MB_FAILURE;
1054 
1055   return MB_SUCCESS;
1056 }
1057 
mb_mesh_sets_test(int flags)1058 ErrorCode mb_mesh_sets_test(int flags)
1059 {
1060   Core moab;
1061   Interface* MB = &moab;
1062   ErrorCode result = create_some_mesh( MB );
1063   if (MB_SUCCESS != result)
1064     return result;
1065 
1066   Range temp_range;
1067   std::vector<EntityHandle> temp_vector;
1068   EntityType ent_type;
1069 
1070   EntityHandle ms_array[MBENTITYSET] = {0};
1071   unsigned int number_array[MBENTITYSET] = {0};
1072   unsigned int num_dim_array[4] = { 0, 0, 0, 0 };
1073   int count, start_num_sets;
1074 
1075   result = MB->get_number_entities_by_type(0, MBENTITYSET, start_num_sets);
1076   if (MB_SUCCESS != result) return result;
1077 
1078     //add entities to meshsets
1079   for (ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++)
1080   {
1081     result = MB->create_meshset( flags, ms_array[ent_type] );
1082     if( result != MB_SUCCESS )
1083       return result;
1084 
1085     temp_range.clear();
1086     result = MB->get_entities_by_type(0, ent_type, temp_range );
1087     if( result != MB_SUCCESS )
1088       return result;
1089     result = MB->get_number_entities_by_type(0, ent_type, count);
1090     if (result != MB_SUCCESS)
1091       return result;
1092     if ((unsigned)count != temp_range.size())
1093       return MB_FAILURE;
1094     result = MB->add_entities( ms_array[ent_type], temp_range);
1095     if( result != MB_SUCCESS )
1096       return result;
1097 
1098     number_array[ent_type] = temp_range.size(); //KGM
1099     num_dim_array[CN::Dimension(ent_type)] += count;
1100 
1101       //Check to make sure mesh set really has correct number of entities in it
1102     temp_range.clear();
1103     temp_vector.clear();
1104     result = MB->get_entities_by_handle(ms_array[ent_type], temp_range);
1105     if(result != MB_SUCCESS)
1106       return result;
1107     if(number_array[ent_type] != temp_range.size())
1108     {
1109       cout<<"Number of entities in meshset test is not correct"<<endl;
1110       return MB_FAILURE;
1111     }
1112     if (!temp_range.all_of_type( ent_type ))
1113       return MB_FAILURE;
1114 
1115     result = MB->get_entities_by_handle(ms_array[ent_type], temp_vector);
1116     if(result != MB_SUCCESS)
1117       return result;
1118     if(number_array[ent_type] != temp_vector.size())
1119     {
1120       cout<<"Number of entities in meshset test is not correct"<<endl;
1121       return MB_FAILURE;
1122     }
1123 
1124     temp_range.clear();
1125     result = MB->get_entities_by_type( ms_array[ent_type], ent_type, temp_range);
1126     if(result != MB_SUCCESS)
1127       return result;
1128     if(number_array[ent_type] != temp_range.size())
1129     {
1130       cout<<"Number of entities by type in meshset test is not correct"<<endl;
1131       return MB_FAILURE;
1132     }
1133     if (!temp_range.all_of_type( ent_type ))
1134       return MB_FAILURE;
1135 
1136     temp_range.clear();
1137     result = MB->get_entities_by_type( ms_array[ent_type], MBVERTEX, temp_range);
1138     if(result != MB_SUCCESS)
1139       return result;
1140     if(0 != temp_range.size())
1141       return MB_FAILURE;
1142 
1143     temp_range.clear();
1144     result = MB->get_entities_by_dimension( ms_array[ent_type], CN::Dimension(ent_type), temp_range);
1145     if(result != MB_SUCCESS)
1146       return result;
1147     if(number_array[ent_type] != temp_range.size())
1148     {
1149       cout<<"Number of entities by dimension in meshset test is not correct"<<endl;
1150       return MB_FAILURE;
1151     }
1152     if (!temp_range.all_of_type( ent_type ))
1153       return MB_FAILURE;
1154 
1155     temp_range.clear();
1156     result = MB->get_entities_by_dimension( ms_array[ent_type], 0, temp_range);
1157     if(result != MB_SUCCESS)
1158       return result;
1159     if(0 != temp_range.size())
1160     {
1161       cout<<"Number of entities by dimension in meshset test is not correct"<<endl;
1162       return MB_FAILURE;
1163     }
1164 
1165     result = MB->get_number_entities_by_handle( ms_array[ent_type], count );
1166     if (result != MB_SUCCESS)
1167       return result;
1168     if ((unsigned)count != number_array[ent_type])
1169       return MB_FAILURE;
1170 
1171     result = MB->get_number_entities_by_type( ms_array[ent_type], ent_type, count );
1172     if (result != MB_SUCCESS)
1173       return result;
1174     if ((unsigned)count != number_array[ent_type])
1175       return MB_FAILURE;
1176 
1177     result = MB->get_number_entities_by_type( ms_array[ent_type], MBVERTEX, count );
1178     if (result != MB_SUCCESS)
1179       return result;
1180     if (count != 0)
1181       return MB_FAILURE;
1182 
1183     result = MB->get_number_entities_by_dimension( ms_array[ent_type], CN::Dimension(ent_type), count );
1184     if (result != MB_SUCCESS)
1185       return result;
1186     if ((unsigned)count != number_array[ent_type])
1187       return MB_FAILURE;
1188 
1189     result = MB->get_number_entities_by_dimension( ms_array[ent_type], 0, count );
1190     if (result != MB_SUCCESS)
1191       return result;
1192     if (count != 0)
1193       return MB_FAILURE;
1194   }
1195 
1196   result = check_esets(MB, start_num_sets + MBENTITYSET - MBEDGE);
1197   if (MB_SUCCESS != result) return result;
1198 
1199   for (int dim = 1; dim < 4; ++dim) {
1200     result = MB->get_number_entities_by_dimension( 0, dim, count );
1201     if (MB_SUCCESS != result)
1202       return MB_FAILURE;
1203     if ((unsigned)count != num_dim_array[dim])
1204       return MB_FAILURE;
1205   }
1206 
1207     //----------TEST RECURSIVE OPERATIONS----------------//
1208   EntityHandle recursive1, recursive2;
1209   result = MB->create_meshset( MESHSET_SET, recursive1 );
1210   if( result != MB_SUCCESS )
1211     return result;
1212   result = MB->create_meshset( 0, recursive2 );
1213   if( result != MB_SUCCESS )
1214     return result;
1215   unsigned num_sets = MBENTITYSET-MBEDGE;
1216   result = MB->add_entities( recursive2, ms_array+MBEDGE, num_sets );
1217   if (MB_SUCCESS != result)
1218     return result;
1219   result = MB->add_entities( recursive1, &recursive2, 1 );
1220   if (MB_SUCCESS != result)
1221     return result;
1222 
1223   temp_range.clear();
1224   result = MB->get_entities_by_type( recursive1, MBENTITYSET, temp_range );
1225   if (MB_SUCCESS != result)
1226     return result;
1227   if (temp_range.size() != 1 || *(temp_range.begin()) != recursive2)
1228     return MB_FAILURE;
1229 
1230   temp_range.clear();
1231   result = MB->get_entities_by_type( recursive2, MBENTITYSET, temp_range );
1232   if (MB_SUCCESS != result)
1233     return result;
1234   if (temp_range.size() != num_sets || !temp_range.all_of_type(MBENTITYSET))
1235     return MB_FAILURE;
1236 
1237   temp_range.clear();
1238   result = MB->get_entities_by_handle( recursive1, temp_range );
1239   if (MB_SUCCESS != result)
1240     return result;
1241   if (temp_range.size() != 1 || *(temp_range.begin()) != recursive2)
1242     return MB_FAILURE;
1243 
1244   temp_range.clear();
1245   result = MB->get_entities_by_handle( recursive2, temp_range );
1246   if (MB_SUCCESS != result)
1247     return result;
1248   if (temp_range.size() != num_sets || !temp_range.all_of_type(MBENTITYSET))
1249     return MB_FAILURE;
1250 
1251 
1252   unsigned total = 0;
1253   for (ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++)
1254   {
1255     total += number_array[ent_type];
1256     temp_range.clear();
1257     result = MB->get_entities_by_type( recursive1, ent_type, temp_range, true );
1258     if(result != MB_SUCCESS)
1259       return result;
1260     if(number_array[ent_type] != temp_range.size())
1261     {
1262       cout<<"Recursive number of entities by type in meshset test is not correct"<<endl;
1263       return MB_FAILURE;
1264     }
1265     if (!temp_range.all_of_type( ent_type ))
1266       return MB_FAILURE;
1267     result = MB->get_number_entities_by_type( recursive1, ent_type, count, true );
1268     if(result != MB_SUCCESS)
1269       return result;
1270     if(number_array[ent_type] != (unsigned)count)
1271     {
1272       cout<<"Recursive number of entities by type in meshset test is not correct"<<endl;
1273       return MB_FAILURE;
1274     }
1275     if (!temp_range.all_of_type( ent_type ))
1276       return MB_FAILURE;
1277   }
1278   if (0 == total) {
1279     cout << "Invalid test input.  No entities!" << endl;
1280     return MB_FAILURE;
1281   }
1282 
1283   for (int dim = 1; dim < 4; ++dim) {
1284     temp_range.clear();
1285     result = MB->get_entities_by_dimension( recursive1, dim, temp_range, true );
1286     if (MB_SUCCESS != result)
1287       return MB_FAILURE;
1288     if (temp_range.size() != num_dim_array[dim])
1289       return MB_FAILURE;
1290     if (!temp_range.all_of_dimension(dim))
1291       return MB_FAILURE;
1292     result = MB->get_number_entities_by_dimension( recursive1, dim, count, true );
1293     if (MB_SUCCESS != result)
1294       return MB_FAILURE;
1295     if ((unsigned)count != num_dim_array[dim])
1296       return MB_FAILURE;
1297   }
1298 
1299   temp_range.clear();
1300   result = MB->get_entities_by_handle( recursive1, temp_range, true );
1301   if(result != MB_SUCCESS)
1302     return result;
1303   if(total != temp_range.size())
1304   {
1305     cout<<"Recursive number of entities in meshset test is not correct"<<endl;
1306     return MB_FAILURE;
1307   }
1308 
1309     // try circular relation
1310   result = MB->add_entities( recursive2, &recursive1, 1 );
1311   if (MB_SUCCESS != result) {
1312     std::cout << "Failed to create circular set containment" << std::endl;
1313     return result;
1314   }
1315   temp_range.clear();
1316   result = MB->get_entities_by_handle( recursive1, temp_range, true );
1317   if(result != MB_SUCCESS)
1318     return result;
1319   if(total != temp_range.size())
1320   {
1321     cout<<"Recursive number of entities in meshset test is not correct"<<endl;
1322     return MB_FAILURE;
1323   }
1324 
1325   result = check_esets(MB, start_num_sets + MBENTITYSET - MBEDGE + 2);
1326   if (MB_SUCCESS != result) return result;
1327 
1328     //----------TEST BOOLEAN OPERATIONS----------------//
1329 
1330   EntityHandle temp_ms1, temp_ms2;
1331   result = MB->create_meshset(flags, temp_ms1);
1332   if(result  != MB_SUCCESS )
1333     return result;
1334   result = MB->create_meshset(flags, temp_ms2);
1335   if(result != MB_SUCCESS )
1336     return result;
1337 
1338     //Subtract
1339     //add all edges and hexes of ms_array[MBHEX] and ms_array[MBEDGE] to temp_ms1
1340     //get all Edge entities
1341   temp_range.clear();
1342   result = MB->get_entities_by_handle(ms_array[MBEDGE], temp_range );
1343   if(result != MB_SUCCESS )
1344     return result;
1345 
1346     //add Edges to ms1
1347   result = MB->add_entities( temp_ms1, temp_range );
1348   if(result != MB_SUCCESS )
1349     return result;
1350 
1351   temp_range.clear();
1352   result = MB->get_entities_by_handle(ms_array[MBHEX], temp_range );
1353   if(result != MB_SUCCESS )
1354     return result;
1355 
1356     //add Hexes to ms1
1357   result = MB->add_entities( temp_ms1, temp_range );
1358   if(result != MB_SUCCESS )
1359     return result;
1360 
1361 
1362     //subtract bars meshset out of hex meshset
1363   result = MB->subtract_meshset( temp_ms1, ms_array[MBEDGE]);
1364   if(result != MB_SUCCESS )
1365     return result;
1366 
1367     //Perform the check
1368   temp_range.clear();
1369   result = MB->get_entities_by_handle(temp_ms1, temp_range );
1370   if(result != MB_SUCCESS )
1371     return result;
1372 
1373   if(number_array[MBHEX] != temp_range.size())
1374   {
1375     cout<<"MBset subtraction is bad"<<endl;
1376     return MB_FAILURE;
1377   }
1378     //make sure there's nothing but hexes in hex_ms
1379   if( nothing_but_type( temp_range, MBHEX ) != MB_SUCCESS )
1380     return MB_FAILURE;
1381 
1382   result = check_esets(MB, start_num_sets + MBENTITYSET - MBEDGE + 4);
1383   if (MB_SUCCESS != result) return result;
1384 
1385     //------------Intersect------------
1386     //
1387     //clean out the temp_ms1
1388   MB->clear_meshset(&temp_ms1, 1);
1389 
1390   temp_range.clear();
1391     //get all quad entities
1392   temp_range.clear();
1393   result = MB->get_entities_by_handle(ms_array[MBQUAD], temp_range );
1394   if(result != MB_SUCCESS )
1395     return result;
1396 
1397 
1398     //add tets them to ms1
1399   result = MB->add_entities( temp_ms1, temp_range ) ;
1400   if(result != MB_SUCCESS )
1401     return result;
1402 
1403     //get all tet entities
1404   temp_range.clear();
1405   result = MB->get_entities_by_handle(ms_array[MBTET], temp_range );
1406   if(result != MB_SUCCESS )
1407     return result;
1408 
1409 
1410     //add tets them to ms1
1411   result = MB->add_entities( temp_ms1, temp_range ) ;
1412   if(result != MB_SUCCESS )
1413     return result;
1414 
1415     //intersect temp_ms1 (which contains all quads and tets) with tet meshset
1416     //temp_ms1 meshset is altered
1417   result = MB->intersect_meshset(temp_ms1, ms_array[MBTET]) ;
1418   if(result != MB_SUCCESS )
1419     return result;
1420 
1421     //Perform the check, only tets should be in temp_ms1
1422   temp_range.clear();
1423   result = MB->get_entities_by_handle(temp_ms1, temp_range );
1424   if(result != MB_SUCCESS )
1425     return result;
1426   if(number_array[MBTET] != temp_range.size())
1427   {
1428     cout<<"MBset intersection is bad"<<endl;
1429     return MB_FAILURE;
1430   }
1431 
1432     //make sure there's nothing but tet in range
1433   if( nothing_but_type( temp_range, MBTET ) != MB_SUCCESS )
1434     return MB_FAILURE;
1435 
1436   result = check_esets(MB, start_num_sets + MBENTITYSET - MBEDGE + 4);
1437   if (MB_SUCCESS != result) return result;
1438 
1439     //-------------Unite--------------
1440     //fill temp_ms1 with tets and tris
1441     //get all tris
1442   temp_range.clear();
1443   result = MB->get_entities_by_handle(ms_array[MBTRI], temp_range );
1444   if(result != MB_SUCCESS )
1445     return result;
1446 
1447     //add tets them to ms1
1448   result = MB->add_entities( temp_ms1, temp_range ) ;
1449   if(result != MB_SUCCESS )
1450     return result;
1451 
1452   temp_range.clear();
1453   result = MB->get_entities_by_handle(ms_array[MBTET], temp_range );
1454   if(result != MB_SUCCESS )
1455     return result;
1456 
1457     //add tets them to ms1
1458   result = MB->add_entities( temp_ms1, temp_range ) ;
1459   if(result != MB_SUCCESS )
1460     return result;
1461 
1462 
1463     //fill temp_ms2 with tris and hexes
1464   temp_range.clear();
1465   result = MB->get_entities_by_handle(ms_array[MBTRI], temp_range );
1466   if(result != MB_SUCCESS )
1467     return result;
1468 
1469     //add tets them to ms1
1470   result = MB->add_entities( temp_ms2, temp_range ) ;
1471   if(result != MB_SUCCESS )
1472     return result;
1473 
1474   temp_range.clear();
1475   result = MB->get_entities_by_handle(ms_array[MBQUAD], temp_range );
1476   if(result != MB_SUCCESS )
1477     return result;
1478 
1479     //add tets them to ms1
1480   result = MB->add_entities( temp_ms2, temp_range ) ;
1481   if(result != MB_SUCCESS )
1482     return result;
1483 
1484 
1485     //temp_ms1 is now filled with tets and tris
1486     //temp_ms2 is now filled with quads and tris
1487   int size1 = 0, size2 = 0;
1488   result = MB->get_number_entities_by_handle(ms_array[MBTRI], size1 ) ;
1489   if(result != MB_SUCCESS )
1490     return result;
1491 
1492   result = MB->intersect_meshset(temp_ms1, temp_ms2 ) ;
1493   if(result != MB_SUCCESS )
1494     return result;
1495   result = MB->get_number_entities_by_handle(temp_ms1, size2 ) ;
1496   if(result != MB_SUCCESS )
1497     return result;
1498 
1499   if(size1 != size2)
1500   {
1501     return MB_FAILURE;
1502   }
1503 
1504   temp_range.clear();
1505   result = MB->get_entities_by_handle(temp_ms1, temp_range );
1506   if(result != MB_SUCCESS )
1507     return result;
1508 
1509     //make sure there's nothing but tris in temp_range
1510   if( nothing_but_type( temp_range, MBTRI ) != MB_SUCCESS)
1511     return MB_FAILURE;
1512 
1513 
1514   result = check_esets(MB, start_num_sets + MBENTITYSET - MBEDGE + 4);
1515   if (MB_SUCCESS != result) return result;
1516 
1517     //-------------Misc tests--------------
1518   EntityHandle temp_ms3;
1519   result = MB->create_meshset(flags, temp_ms3);
1520   if(result  != MB_SUCCESS )
1521     return result;
1522 
1523   EntityHandle handle_array[] = {1, 2, 3, 4, 5, 7, 8, 9, 10};
1524   const int num_handle = sizeof(handle_array)/sizeof(handle_array[0]);
1525     //add ents to set
1526   result = MB->add_entities( temp_ms3, handle_array, num_handle );
1527   if(result  != MB_SUCCESS )
1528     return result;
1529 
1530     // try adding again
1531   result = MB->add_entities( temp_ms3, handle_array, num_handle );
1532   if(result  != MB_SUCCESS )
1533     return result;
1534 
1535   int num_ents;
1536   result = MB->get_number_entities_by_handle(temp_ms3, num_ents);
1537   if(result  != MB_SUCCESS )
1538     return result;
1539 
1540   int num_expected = (flags & MESHSET_SET) ? num_handle : 2*num_handle;
1541   if (num_ents != num_expected)
1542     return MB_FAILURE;
1543 
1544   return MB_SUCCESS;
1545 }
1546 
compare_lists(std::vector<EntityHandle> vect,const EntityHandle * array,int count,bool ordered=true)1547 static bool compare_lists( std::vector<EntityHandle> vect,
1548                            const EntityHandle* array,
1549                            int count,
1550                            bool ordered = true )
1551 {
1552   if (vect.size() != (size_t)count)
1553     return false;
1554   for (int i = 0; i < count; ++i) {
1555     if (ordered) {
1556       if (vect[i] != array[i])
1557         return false;
1558     }
1559     else if (std::find(vect.begin(),vect.end(),array[i]) == vect.end())
1560       return false;
1561   }
1562   return true;
1563 }
1564 
1565     //Test parent/child stuff in meshsets
mb_mesh_set_parent_child_test()1566 ErrorCode mb_mesh_set_parent_child_test()
1567 {
1568   Core moab;
1569   Interface *MB = &moab;
1570 
1571   ErrorCode rval;
1572   std::vector<EntityHandle> list;
1573   Range range;
1574   Range::iterator iter;
1575   int count;
1576 
1577     // create a few mesh sets
1578   const int num_sets = 10;
1579   EntityHandle sets[num_sets];
1580   for (int i = 0; i < num_sets; ++i) {
1581     rval = MB->create_meshset( i % 2 ? MESHSET_SET : 0, sets[i] );
1582     if (MB_SUCCESS != rval)
1583       return rval;
1584   }
1585 
1586     // test adding child meshsets
1587 
1588     // add first child
1589   rval = MB->add_child_meshset( sets[0], sets[1] );
1590   if (MB_SUCCESS != rval) return rval;
1591   list.clear();
1592   rval = MB->get_child_meshsets( sets[0], list );
1593   if (MB_SUCCESS != rval) return rval;
1594   if (!compare_lists( list, sets+1, 1 ))
1595     return MB_FAILURE;
1596     // try to add child again
1597   rval = MB->add_child_meshset( sets[0], sets[1] );
1598   if (MB_SUCCESS != rval) return rval;
1599   list.clear();
1600   rval = MB->get_child_meshsets( sets[0], list );
1601   if (MB_SUCCESS != rval) return rval;
1602   if (!compare_lists( list, sets+1, 1 ))
1603     return MB_FAILURE;
1604 
1605     // add second child
1606   rval = MB->add_child_meshset( sets[0], sets[2] );
1607   if (MB_SUCCESS != rval) return rval;
1608   list.clear();
1609   rval = MB->get_child_meshsets( sets[0], list );
1610   if (MB_SUCCESS != rval) return rval;
1611   if (!compare_lists( list, sets+1, 2 ))
1612     return MB_FAILURE;
1613     // try adding child again
1614   rval = MB->add_child_meshset( sets[0], sets[1] );
1615   if (MB_SUCCESS != rval) return rval;
1616   list.clear();
1617   rval = MB->get_child_meshsets( sets[0], list );
1618   if (MB_SUCCESS != rval) return rval;
1619   if (!compare_lists( list, sets+1, 2 ))
1620     return MB_FAILURE;
1621 
1622     // add third child
1623   rval = MB->add_child_meshset( sets[0], sets[3] );
1624   if (MB_SUCCESS != rval) return rval;
1625   list.clear();
1626   rval = MB->get_child_meshsets( sets[0], list );
1627   if (MB_SUCCESS != rval) return rval;
1628   if (!compare_lists( list, sets+1, 3 ))
1629     return MB_FAILURE;
1630     // try adding child again
1631   rval = MB->add_child_meshset( sets[0], sets[1] );
1632   if (MB_SUCCESS != rval) return rval;
1633   list.clear();
1634   rval = MB->get_child_meshsets( sets[0], list );
1635   if (MB_SUCCESS != rval) return rval;
1636   if (!compare_lists( list, sets+1, 3 ))
1637     return MB_FAILURE;
1638 
1639     // add fourth child
1640   rval = MB->add_child_meshset( sets[0], sets[4] );
1641   if (MB_SUCCESS != rval) return rval;
1642   list.clear();
1643   rval = MB->get_child_meshsets( sets[0], list );
1644   if (MB_SUCCESS != rval) return rval;
1645   if (!compare_lists( list, sets+1, 4 ))
1646     return MB_FAILURE;
1647 
1648     // make sure range query returns same result
1649   std::sort( list.begin(), list.end() );
1650   rval = MB->get_child_meshsets( sets[0], range );
1651   iter = range.begin();
1652   for (unsigned i = 0; i < 4; ++i, ++iter)
1653     if (*iter != list[i])
1654       return MB_FAILURE;
1655 
1656     // remove first child
1657   rval = MB->remove_child_meshset( sets[0], sets[1] );
1658   if (MB_SUCCESS != rval) return rval;
1659   list.clear();
1660   rval = MB->get_child_meshsets( sets[0], list );
1661   if (MB_SUCCESS != rval) return rval;
1662   if (!compare_lists( list, sets+2, 3 ))
1663     return MB_FAILURE;
1664     // try removing child again
1665   rval = MB->remove_child_meshset( sets[0], sets[1] );
1666   if (MB_SUCCESS != rval) return rval;
1667 
1668     // remove second child
1669   rval = MB->remove_child_meshset( sets[0], sets[2] );
1670   if (MB_SUCCESS != rval) return rval;
1671   list.clear();
1672   rval = MB->get_child_meshsets( sets[0], list );
1673   if (!compare_lists( list, sets+3, 2 ))
1674     return MB_FAILURE;
1675     // try removing child again
1676   rval = MB->remove_child_meshset( sets[0], sets[2] );
1677   if (MB_SUCCESS != rval) return rval;
1678 
1679     // remove third child
1680   rval = MB->remove_child_meshset( sets[0], sets[3] );
1681   if (MB_SUCCESS != rval) return rval;
1682   list.clear();
1683   rval = MB->get_child_meshsets( sets[0], list );
1684   if (list.size() != 1 || list[0] != sets[4])
1685     return MB_FAILURE;
1686 
1687     // remove fourth child
1688   rval = MB->remove_child_meshset( sets[0], sets[4] );
1689   if (MB_SUCCESS != rval) return rval;
1690   list.clear();
1691   rval = MB->get_child_meshsets( sets[0], list );
1692   if (!list.empty())
1693     return MB_FAILURE;
1694 
1695 
1696     // test adding parent meshsets
1697 
1698     // add first parent
1699   rval = MB->add_parent_meshset( sets[0], sets[1] );
1700   if (MB_SUCCESS != rval) return rval;
1701   list.clear();
1702   rval = MB->get_parent_meshsets( sets[0], list );
1703   if (MB_SUCCESS != rval) return rval;
1704   if (!compare_lists( list, sets+1, 1 ))
1705     return MB_FAILURE;
1706     // try to add parent again
1707   rval = MB->add_parent_meshset( sets[0], sets[1] );
1708   if (MB_SUCCESS != rval) return rval;
1709   list.clear();
1710   rval = MB->get_parent_meshsets( sets[0], list );
1711   if (MB_SUCCESS != rval) return rval;
1712   if (!compare_lists( list, sets+1, 1 ))
1713     return MB_FAILURE;
1714 
1715     // add second parent
1716   rval = MB->add_parent_meshset( sets[0], sets[2] );
1717   if (MB_SUCCESS != rval) return rval;
1718   list.clear();
1719   rval = MB->get_parent_meshsets( sets[0], list );
1720   if (MB_SUCCESS != rval) return rval;
1721   if (!compare_lists( list, sets+1, 2 ))
1722     return MB_FAILURE;
1723     // try adding parent again
1724   rval = MB->add_parent_meshset( sets[0], sets[1] );
1725   if (MB_SUCCESS != rval) return rval;
1726   list.clear();
1727   rval = MB->get_parent_meshsets( sets[0], list );
1728   if (MB_SUCCESS != rval) return rval;
1729   if (!compare_lists( list, sets+1, 2 ))
1730     return MB_FAILURE;
1731 
1732     // add third parent
1733   rval = MB->add_parent_meshset( sets[0], sets[3] );
1734   if (MB_SUCCESS != rval) return rval;
1735   list.clear();
1736   rval = MB->get_parent_meshsets( sets[0], list );
1737   if (MB_SUCCESS != rval) return rval;
1738   if (!compare_lists( list, sets+1, 3 ))
1739     return MB_FAILURE;
1740     // try adding parent again
1741   rval = MB->add_parent_meshset( sets[0], sets[1] );
1742   if (MB_SUCCESS != rval) return rval;
1743   list.clear();
1744   rval = MB->get_parent_meshsets( sets[0], list );
1745   if (MB_SUCCESS != rval) return rval;
1746   if (!compare_lists( list, sets+1, 3 ))
1747     return MB_FAILURE;
1748 
1749     // add fourth parent
1750   rval = MB->add_parent_meshset( sets[0], sets[4] );
1751   if (MB_SUCCESS != rval) return rval;
1752   list.clear();
1753   rval = MB->get_parent_meshsets( sets[0], list );
1754   if (MB_SUCCESS != rval) return rval;
1755   if (!compare_lists( list, sets+1, 4 ))
1756     return MB_FAILURE;
1757 
1758     // make sure range query returns same result
1759   std::sort( list.begin(), list.end() );
1760   rval = MB->get_parent_meshsets( sets[0], range );
1761   iter = range.begin();
1762   for (unsigned i = 0; i < 4; ++i, ++iter)
1763     if (*iter != list[i])
1764       return MB_FAILURE;
1765 
1766     // remove first parent
1767   rval = MB->remove_parent_meshset( sets[0], sets[1] );
1768   if (MB_SUCCESS != rval) return rval;
1769   list.clear();
1770   rval = MB->get_parent_meshsets( sets[0], list );
1771   if (MB_SUCCESS != rval) return rval;
1772   if (!compare_lists( list, sets+2, 3 ))
1773     return MB_FAILURE;
1774     // try removing parent again
1775   rval = MB->remove_parent_meshset( sets[0], sets[1] );
1776   if (MB_SUCCESS != rval) return rval;
1777 
1778     // remove second parent
1779   rval = MB->remove_parent_meshset( sets[0], sets[2] );
1780   if (MB_SUCCESS != rval) return rval;
1781   list.clear();
1782   rval = MB->get_parent_meshsets( sets[0], list );
1783   if (!compare_lists( list, sets+3, 2 ))
1784     return MB_FAILURE;
1785     // try removing parent again
1786   rval = MB->remove_parent_meshset( sets[0], sets[2] );
1787   if (MB_SUCCESS != rval) return rval;
1788 
1789     // remove third parent
1790   rval = MB->remove_parent_meshset( sets[0], sets[3] );
1791   if (MB_SUCCESS != rval) return rval;
1792   list.clear();
1793   rval = MB->get_parent_meshsets( sets[0], list );
1794   if (list.size() != 1 || list[0] != sets[4])
1795     return MB_FAILURE;
1796 
1797     // remove fourth parent
1798   rval = MB->remove_parent_meshset( sets[0], sets[4] );
1799   if (MB_SUCCESS != rval) return rval;
1800   list.clear();
1801   rval = MB->get_parent_meshsets( sets[0], list );
1802   if (!list.empty())
1803     return MB_FAILURE;
1804 
1805 
1806     // setup tests of recursive child query
1807     //              0
1808     //            /   \         .
1809     //          1       2
1810     //        /   \   /   \       .
1811     //      3       4       5
1812     //        \   /   \   /
1813     //          6       7
1814   rval = MB->add_child_meshset( sets[0], sets[1] );
1815   if (MB_SUCCESS != rval) return rval;
1816   rval = MB->add_child_meshset( sets[0], sets[2] );
1817   if (MB_SUCCESS != rval) return rval;
1818   rval = MB->add_child_meshset( sets[1], sets[3] );
1819   if (MB_SUCCESS != rval) return rval;
1820   rval = MB->add_child_meshset( sets[1], sets[4] );
1821   if (MB_SUCCESS != rval) return rval;
1822   rval = MB->add_child_meshset( sets[2], sets[4] );
1823   if (MB_SUCCESS != rval) return rval;
1824   rval = MB->add_child_meshset( sets[2], sets[5] );
1825   if (MB_SUCCESS != rval) return rval;
1826   rval = MB->add_child_meshset( sets[3], sets[6] );
1827   if (MB_SUCCESS != rval) return rval;
1828   rval = MB->add_child_meshset( sets[4], sets[6] );
1829   if (MB_SUCCESS != rval) return rval;
1830   rval = MB->add_child_meshset( sets[4], sets[7] );
1831   if (MB_SUCCESS != rval) return rval;
1832   rval = MB->add_child_meshset( sets[5], sets[7] );
1833   if (MB_SUCCESS != rval) return rval;
1834 
1835     // test query at depth of 1
1836   list.clear();
1837   rval = MB->get_child_meshsets( sets[0], list, 1 );
1838   if (MB_SUCCESS != rval) return rval;
1839   if (list.size() != 2 || list[0] != sets[1] || list[1] != sets[2])
1840     return MB_FAILURE;
1841   rval = MB->num_child_meshsets( sets[0], &count, 1 );
1842   if (MB_SUCCESS != rval) return rval;
1843   if (count != 2)
1844     return MB_FAILURE;
1845 
1846     // test query at depth of 2
1847   list.clear();
1848   rval = MB->get_child_meshsets( sets[0], list, 2 );
1849   if (MB_SUCCESS != rval) return rval;
1850   if (!compare_lists( list, sets+1, 5, false ))
1851     return MB_FAILURE;
1852   rval = MB->num_child_meshsets( sets[0], &count, 2 );
1853   if (MB_SUCCESS != rval) return rval;
1854   if (count != 5)
1855     return MB_FAILURE;
1856 
1857     // test query at depth of 3
1858   list.clear();
1859   rval = MB->get_child_meshsets( sets[0], list, 3 );
1860   if (MB_SUCCESS != rval) return rval;
1861   if (!compare_lists( list, sets+1, 7, false ))
1862     return MB_FAILURE;
1863   rval = MB->num_child_meshsets( sets[0], &count, 3 );
1864   if (MB_SUCCESS != rval) return rval;
1865   if (count != 7)
1866     return MB_FAILURE;
1867 
1868     // test query at depth of 4
1869   list.clear();
1870   rval = MB->get_child_meshsets( sets[0], list, 4 );
1871   if (MB_SUCCESS != rval) return rval;
1872   if (!compare_lists( list, sets+1, 7, false ))
1873     return MB_FAILURE;
1874   rval = MB->num_child_meshsets( sets[0], &count, 4 );
1875   if (MB_SUCCESS != rval) return rval;
1876   if (count != 7)
1877     return MB_FAILURE;
1878 
1879     // test query at all
1880   list.clear();
1881   rval = MB->get_child_meshsets( sets[0], list, 0 );
1882   if (MB_SUCCESS != rval) return rval;
1883   if (!compare_lists( list, sets+1, 7, false ))
1884     return MB_FAILURE;
1885   rval = MB->num_child_meshsets( sets[0], &count, 0 );
1886   if (MB_SUCCESS != rval) return rval;
1887   if (count != 7)
1888     return MB_FAILURE;
1889 
1890     // clean up child links
1891   rval = MB->remove_child_meshset( sets[0], sets[1] );
1892   if (MB_SUCCESS != rval) return rval;
1893   rval = MB->remove_child_meshset( sets[0], sets[2] );
1894   if (MB_SUCCESS != rval) return rval;
1895   rval = MB->remove_child_meshset( sets[1], sets[3] );
1896   if (MB_SUCCESS != rval) return rval;
1897   rval = MB->remove_child_meshset( sets[1], sets[4] );
1898   if (MB_SUCCESS != rval) return rval;
1899   rval = MB->remove_child_meshset( sets[2], sets[4] );
1900   if (MB_SUCCESS != rval) return rval;
1901   rval = MB->remove_child_meshset( sets[2], sets[5] );
1902   if (MB_SUCCESS != rval) return rval;
1903   rval = MB->remove_child_meshset( sets[3], sets[6] );
1904   if (MB_SUCCESS != rval) return rval;
1905   rval = MB->remove_child_meshset( sets[4], sets[6] );
1906   if (MB_SUCCESS != rval) return rval;
1907   rval = MB->remove_child_meshset( sets[4], sets[7] );
1908   if (MB_SUCCESS != rval) return rval;
1909   rval = MB->remove_child_meshset( sets[5], sets[7] );
1910   if (MB_SUCCESS != rval) return rval;
1911   for (int i = 0; i < 5; ++i)
1912     if (MB_SUCCESS != MB->num_child_meshsets(sets[i], &count) || count)
1913       return MB_FAILURE;
1914 
1915     // setup tests of recursive parent query
1916     //          6       7
1917     //        /   \   /   \       .
1918     //      3       4       5
1919     //        \   /   \   /
1920     //          1       2
1921     //            \   /
1922     //              0
1923   rval = MB->add_parent_meshset( sets[0], sets[1] );
1924   if (MB_SUCCESS != rval) return rval;
1925   rval = MB->add_parent_meshset( sets[0], sets[2] );
1926   if (MB_SUCCESS != rval) return rval;
1927   rval = MB->add_parent_meshset( sets[1], sets[3] );
1928   if (MB_SUCCESS != rval) return rval;
1929   rval = MB->add_parent_meshset( sets[1], sets[4] );
1930   if (MB_SUCCESS != rval) return rval;
1931   rval = MB->add_parent_meshset( sets[2], sets[4] );
1932   if (MB_SUCCESS != rval) return rval;
1933   rval = MB->add_parent_meshset( sets[2], sets[5] );
1934   if (MB_SUCCESS != rval) return rval;
1935   rval = MB->add_parent_meshset( sets[3], sets[6] );
1936   if (MB_SUCCESS != rval) return rval;
1937   rval = MB->add_parent_meshset( sets[4], sets[6] );
1938   if (MB_SUCCESS != rval) return rval;
1939   rval = MB->add_parent_meshset( sets[4], sets[7] );
1940   if (MB_SUCCESS != rval) return rval;
1941   rval = MB->add_parent_meshset( sets[5], sets[7] );
1942   if (MB_SUCCESS != rval) return rval;
1943 
1944     // test query at depth of 1
1945   list.clear();
1946   rval = MB->get_parent_meshsets( sets[0], list, 1 );
1947   if (MB_SUCCESS != rval) return rval;
1948   if (list.size() != 2 || list[0] != sets[1] || list[1] != sets[2])
1949     return MB_FAILURE;
1950   rval = MB->num_parent_meshsets( sets[0], &count, 1 );
1951   if (MB_SUCCESS != rval) return rval;
1952   if (count != 2)
1953     return MB_FAILURE;
1954 
1955     // test query at depth of 2
1956   list.clear();
1957   rval = MB->get_parent_meshsets( sets[0], list, 2 );
1958   if (MB_SUCCESS != rval) return rval;
1959   if (!compare_lists( list, sets+1, 5, false ))
1960     return MB_FAILURE;
1961   rval = MB->num_parent_meshsets( sets[0], &count, 2 );
1962   if (MB_SUCCESS != rval) return rval;
1963   if (count != 5)
1964     return MB_FAILURE;
1965 
1966     // test query at depth of 3
1967   list.clear();
1968   rval = MB->get_parent_meshsets( sets[0], list, 3 );
1969   if (MB_SUCCESS != rval) return rval;
1970   if (!compare_lists( list, sets+1, 7, false ))
1971     return MB_FAILURE;
1972   rval = MB->num_parent_meshsets( sets[0], &count, 3 );
1973   if (MB_SUCCESS != rval) return rval;
1974   if (count != 7)
1975     return MB_FAILURE;
1976 
1977     // test query at depth of 4
1978   list.clear();
1979   rval = MB->get_parent_meshsets( sets[0], list, 4 );
1980   if (MB_SUCCESS != rval) return rval;
1981   if (!compare_lists( list, sets+1, 7, false ))
1982     return MB_FAILURE;
1983   rval = MB->num_parent_meshsets( sets[0], &count, 4 );
1984   if (MB_SUCCESS != rval) return rval;
1985   if (count != 7)
1986     return MB_FAILURE;
1987 
1988     // test query at all
1989   list.clear();
1990   rval = MB->get_parent_meshsets( sets[0], list, 0 );
1991   if (MB_SUCCESS != rval) return rval;
1992   if (!compare_lists( list, sets+1, 7, false ))
1993     return MB_FAILURE;
1994   rval = MB->num_parent_meshsets( sets[0], &count, 0 );
1995   if (MB_SUCCESS != rval) return rval;
1996   if (count != 7)
1997     return MB_FAILURE;
1998 
1999     // clean up parent links
2000   rval = MB->remove_parent_meshset( sets[0], sets[1] );
2001   if (MB_SUCCESS != rval) return rval;
2002   rval = MB->remove_parent_meshset( sets[0], sets[2] );
2003   if (MB_SUCCESS != rval) return rval;
2004   rval = MB->remove_parent_meshset( sets[1], sets[3] );
2005   if (MB_SUCCESS != rval) return rval;
2006   rval = MB->remove_parent_meshset( sets[1], sets[4] );
2007   if (MB_SUCCESS != rval) return rval;
2008   rval = MB->remove_parent_meshset( sets[2], sets[4] );
2009   if (MB_SUCCESS != rval) return rval;
2010   rval = MB->remove_parent_meshset( sets[2], sets[5] );
2011   if (MB_SUCCESS != rval) return rval;
2012   rval = MB->remove_parent_meshset( sets[3], sets[6] );
2013   if (MB_SUCCESS != rval) return rval;
2014   rval = MB->remove_parent_meshset( sets[4], sets[6] );
2015   if (MB_SUCCESS != rval) return rval;
2016   rval = MB->remove_parent_meshset( sets[4], sets[7] );
2017   if (MB_SUCCESS != rval) return rval;
2018   rval = MB->remove_parent_meshset( sets[5], sets[7] );
2019   if (MB_SUCCESS != rval) return rval;
2020   for (int i = 0; i < 5; ++i)
2021     if (MB_SUCCESS != MB->num_parent_meshsets(sets[i], &count) || count)
2022       return MB_FAILURE;
2023 
2024 
2025     // test combined parent/child links
2026 
2027     // test creation
2028   rval = MB->add_parent_child( sets[9], sets[8] );
2029   if (MB_SUCCESS != rval) return rval;
2030   list.clear();
2031   rval = MB->get_child_meshsets( sets[9], list );
2032   if (MB_SUCCESS != rval) return rval;
2033   if (list.size() != 1 || list[0] != sets[8])
2034     return MB_FAILURE;
2035   list.clear();
2036   rval = MB->get_parent_meshsets( sets[8], list );
2037   if (MB_SUCCESS != rval) return rval;
2038   if (list.size() != 1 || list[0] != sets[9])
2039     return MB_FAILURE;
2040 
2041     // test deletion of parent/child
2042   rval = MB->add_parent_child( sets[7], sets[9] );
2043   if (MB_SUCCESS != rval) return rval;
2044   rval = MB->delete_entities( &sets[9], 1 );
2045   if (MB_SUCCESS != rval) return rval;
2046   list.clear();
2047   rval = MB->get_parent_meshsets( sets[8], list );
2048   if (!list.empty())
2049     return MB_FAILURE;
2050   list.clear();
2051   rval = MB->get_child_meshsets( sets[7], list );
2052   if (!list.empty())
2053     return MB_FAILURE;
2054 
2055     // clean up remaining sets
2056   return MB->delete_entities( sets, 9 );
2057 }
2058 
mb_mesh_sets_set_test()2059 ErrorCode mb_mesh_sets_set_test()
2060 {
2061   return mb_mesh_sets_test( MESHSET_SET );
2062 }
2063 
mb_mesh_sets_list_test()2064 ErrorCode mb_mesh_sets_list_test()
2065 {
2066   return mb_mesh_sets_test( MESHSET_ORDERED );
2067 }
2068 
2069 // Verify that all query functions *append* to output Range
mb_mesh_set_appends(int flags)2070 ErrorCode mb_mesh_set_appends( int flags )
2071 {
2072   Core moab;
2073   Interface* mb = &moab;
2074   ErrorCode rval = create_some_mesh( mb );
2075   if (MB_SUCCESS != rval)
2076     return rval;
2077 
2078     // get all handles and subdivide into vertex and non-vertex ents
2079   Range all_ents, verts, elems, results;
2080   rval = mb->get_entities_by_handle( 0, all_ents );
2081   if (MB_SUCCESS != rval)
2082     return rval;
2083   Range::iterator ve = all_ents.upper_bound( MBVERTEX );
2084   verts.merge( all_ents.begin(), ve );
2085   elems.merge( ve, all_ents.end() );
2086 
2087     // If we're not testing queries from the root set,
2088     // create a set containing all the vertices
2089   EntityHandle set = 0;
2090   if (flags != -1) {
2091     rval = mb->create_meshset( flags, set );
2092     if (MB_SUCCESS != rval)
2093       return rval;
2094     rval = mb->add_entities( set, verts );
2095     if (MB_SUCCESS != rval)
2096       return rval;
2097   }
2098 
2099     // Test get_entities_by_handle.  This one doesn't make
2100     // much sense if we're testing the root set, but it doesn't
2101     // hurt to test it anyway.
2102   results = elems;
2103   rval = mb->get_entities_by_handle( set, results );
2104   if (MB_SUCCESS != rval)
2105     return rval;
2106   if (results != all_ents)
2107     return MB_FAILURE;
2108 
2109     // Test get_entities_by_dimension
2110   results = elems;
2111   rval = mb->get_entities_by_dimension( set, 0, results );
2112   if (MB_SUCCESS != rval)
2113     return rval;
2114   if (results != all_ents)
2115     return MB_FAILURE;
2116 
2117     // Test get_entities_by_type
2118   results = elems;
2119   rval = mb->get_entities_by_type( set, MBVERTEX, results );
2120   if (MB_SUCCESS != rval)
2121     return rval;
2122   if (results != all_ents)
2123     return MB_FAILURE;
2124 
2125     // choose a single entity for testing tag queries
2126   EntityHandle entity = verts.front();
2127   Range expected( elems );
2128   expected.insert( entity );
2129 
2130   Tag sparse, dense;
2131   const int zero = 0, one = 1;
2132   const void* vals[] = {&one};
2133 
2134     // Test get_entities_by_type_and_tag w/ sparse tag and no value
2135   rval = mb->tag_get_handle( "mb_mesh_set_appends_sparse",
2136                          1, MB_TYPE_INTEGER, sparse, MB_TAG_SPARSE|MB_TAG_EXCL );
2137   if (MB_SUCCESS != rval)
2138     return rval;
2139   rval = mb->tag_set_data( sparse, &entity, 1, &one );
2140   if (MB_SUCCESS != rval)
2141     return rval;
2142   results = elems;
2143   rval = mb->get_entities_by_type_and_tag( set,
2144                                            TYPE_FROM_HANDLE(entity),
2145                                            &sparse, 0, 1,
2146                                            results, Interface::UNION );
2147   if (MB_SUCCESS != rval)
2148     return rval;
2149   if (results != expected)
2150     return MB_FAILURE;
2151     // Test again, but specify tag value
2152   results = elems;
2153   rval = mb->get_entities_by_type_and_tag( set,
2154                                            TYPE_FROM_HANDLE(entity),
2155                                            &sparse, vals, 1,
2156                                            results, Interface::UNION );
2157   if (MB_SUCCESS != rval)
2158     return rval;
2159   if (results != expected)
2160     return MB_FAILURE;
2161 
2162     // Test get_entities_by_type_and_tag w/ dense tag
2163   rval = mb->tag_get_handle( "mb_mesh_set_appends_dense",
2164                          1, MB_TYPE_INTEGER, dense,
2165                          MB_TAG_DENSE|MB_TAG_EXCL, &zero );
2166   if (MB_SUCCESS != rval)
2167     return rval;
2168   rval = mb->tag_set_data( dense, &entity, 1, &one );
2169   if (MB_SUCCESS != rval)
2170     return rval;
2171   results = elems;
2172   rval = mb->get_entities_by_type_and_tag( set,
2173                                            TYPE_FROM_HANDLE(entity),
2174                                            &dense, vals, 1,
2175                                            results, Interface::UNION );
2176   if (MB_SUCCESS != rval)
2177     return rval;
2178   if (results != expected)
2179     return MB_FAILURE;
2180 
2181   return MB_SUCCESS;
2182 }
2183 
mb_mesh_set_set_appends()2184 ErrorCode mb_mesh_set_set_appends()
2185 {
2186   return mb_mesh_set_appends( MESHSET_SET );
2187 }
2188 
mb_mesh_set_list_appends()2189 ErrorCode mb_mesh_set_list_appends()
2190 {
2191   return mb_mesh_set_appends( MESHSET_ORDERED );
2192 }
2193 
mb_mesh_set_root_appends()2194 ErrorCode mb_mesh_set_root_appends()
2195 {
2196   return mb_mesh_set_appends( -1 );
2197 }
2198 
mb_mesh_set_set_replace_test()2199 ErrorCode mb_mesh_set_set_replace_test()
2200 {
2201   Core moab;
2202   Interface* mb = &moab;
2203   ErrorCode rval;
2204   Range r;
2205     // create 10 vertices to put in set
2206   std::vector<double> coords(30);
2207   rval = mb->create_vertices( &coords[0], 10, r );
2208   MB_CHK_ERR(rval);
2209   std::vector<EntityHandle> verts(r.size());
2210   std::copy( r.begin(), r.end(), verts.begin() );
2211   r.clear();
2212     // create a set
2213   EntityHandle set;
2214   rval = mb->create_meshset( MESHSET_SET, set );
2215   MB_CHK_ERR(rval);
2216     // put every other vertex in set
2217   for (size_t i = 0; i < 10; i += 2)
2218     r.insert( verts[i] );
2219   rval = mb->add_entities( set, r );
2220   MB_CHK_ERR(rval);
2221   r.clear();
2222     // swap 3 of the vertices
2223   EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
2224   EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
2225   rval = mb->replace_entities( set, old_ents, new_ents, 3 );
2226   MB_CHK_ERR(rval);
2227     // check new set contents
2228   rval = mb->get_entities_by_handle( set, r );
2229   MB_CHK_ERR(rval);
2230   Range r2;
2231   r2.insert( verts[0] );
2232   r2.insert( verts[1] );
2233   r2.insert( verts[9] );
2234   r2.insert( verts[5] );
2235   r2.insert( verts[8] );
2236   if (r != r2) {
2237     std::cerr << "Range does not contain expected values." << std::endl
2238               << "  Expected: " << r2 << std::endl
2239               << "  Actual  : " << r  << std::endl;
2240     return MB_FAILURE;
2241   }
2242 
2243   return MB_SUCCESS;
2244 }
2245 
mb_mesh_set_list_replace_test()2246 ErrorCode mb_mesh_set_list_replace_test()
2247 {
2248   Core moab;
2249   Interface* mb = &moab;
2250   ErrorCode rval;
2251     // create 10 vertices to put in set
2252   Range r;
2253   std::vector<double> coords(30);
2254   rval = mb->create_vertices( &coords[0], 10, r );
2255   MB_CHK_ERR(rval);
2256   std::vector<EntityHandle> verts(r.size());
2257   std::copy( r.begin(), r.end(), verts.begin() );
2258   r.clear();
2259     // create a set
2260   EntityHandle set;
2261   rval = mb->create_meshset( MESHSET_ORDERED, set );
2262   MB_CHK_ERR(rval);
2263     // put all vertices in set, but add the first one a second time
2264   std::vector<EntityHandle> list( verts );
2265   list.push_back( verts.front() );
2266   rval = mb->add_entities( set, &list[0], list.size() );MB_CHK_ERR(rval);
2267     // swap 3 of the vertices
2268   EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
2269   EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
2270   rval = mb->replace_entities( set, old_ents, new_ents, 3 );MB_CHK_ERR(rval);
2271     // check new set contents
2272   std::vector<EntityHandle> list2;
2273   rval = mb->get_entities_by_handle( set, list2 );
2274   MB_CHK_ERR(rval);
2275   list[2] = verts[1];
2276   list[4] = verts[9];
2277   list[6] = verts[5];
2278   if (list != list2) {
2279     std::cerr << "Range does not contain expected values." << std::endl;
2280     std::cerr << "  Expected: ";
2281     std::copy( list.begin(), list.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
2282     std::cerr << std::endl << "  Actual  : ";
2283     std::copy( list2.begin(), list2.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
2284     std::cerr << std::endl;
2285     return MB_FAILURE;
2286   }
2287     // now try replacing a repeated value
2288   rval = mb->replace_entities( set, &verts[0], &verts[3], 1 );
2289   MB_CHK_ERR(rval);
2290   list[0] = list[10] = verts[3];
2291   list2.clear();
2292   rval = mb->get_entities_by_handle( set, list2 );
2293   MB_CHK_ERR(rval);
2294   if (list != list2) {
2295     std::cerr << "Range does not contain expected values." << std::endl;
2296     std::cerr << "  Expected: ";
2297     std::copy( list.begin(), list.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
2298     std::cerr << std::endl << "  Actual  : ";
2299     std::copy( list2.begin(), list2.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
2300     std::cerr << std::endl;
2301     return MB_FAILURE;
2302   }
2303 
2304   return MB_SUCCESS;
2305 }
2306 
2307 /* Test the following changes to a meshset:
2308   set       MB-> tracking
2309   tracking  MB-> set
2310   unordered MB-> ordered
2311   ordered   MB-> unordered
2312 */
mb_mesh_set_flag_test()2313 ErrorCode mb_mesh_set_flag_test()
2314 {
2315   Core moab;
2316   Interface* mb = &moab;
2317 
2318   ErrorCode rval;
2319     // create 10 vertices to put in set
2320   Range verts;
2321   std::vector<double> coords(30);
2322   rval = mb->create_vertices( &coords[0], 10, verts );
2323   MB_CHK_ERR(rval);
2324 
2325   // CHECK SET->TRACKING
2326   // create a set and add the verts
2327   EntityHandle set;
2328   rval = mb->create_meshset( MESHSET_SET, set );
2329   MB_CHK_ERR(rval);
2330   rval = mb->add_entities( set, verts);
2331   MB_CHK_ERR(rval);
2332   // the verts should not be tracking adjacencies
2333   Range adj_sets;
2334   rval = mb->get_adjacencies( verts, 4, false, adj_sets);
2335   MB_CHK_ERR(rval);
2336   if(!adj_sets.empty()) {
2337     std::cerr << "range should be empty but contains:" << std::endl;
2338     rval = mb->list_entities( adj_sets );
2339     return MB_FAILURE;
2340   }
2341   // check to make sure the flags on MESHSET_SET
2342   unsigned int flags;
2343   rval = mb->get_meshset_options( set, flags );MB_CHK_ERR(rval);
2344   if(!(MESHSET_SET&flags) || (MESHSET_TRACK_OWNER&flags) || (MESHSET_ORDERED&flags) ){
2345     std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
2346     return MB_FAILURE;
2347   }
2348   // change to a tracking set and check flags
2349   rval = mb->set_meshset_options( set, MESHSET_TRACK_OWNER);MB_CHK_ERR(rval);
2350   rval = mb->get_meshset_options( set, flags );MB_CHK_ERR(rval);
2351   if( (MESHSET_SET&flags) || !(MESHSET_TRACK_OWNER&flags) || (MESHSET_ORDERED&flags) ){
2352     std::cerr << "set should be MESHSET_TRACK_OWNER only, flags=" << flags
2353               << std::endl;
2354     return MB_FAILURE;
2355   }
2356   // check adjacencies
2357   rval = mb->get_adjacencies( verts, 4, false, adj_sets);
2358   MB_CHK_ERR(rval);
2359   if(1 != adj_sets.size()) {
2360     std::cerr << "range should contain a set, adj_sets.size()="
2361               << adj_sets.size() << std::endl;
2362     rval = mb->list_entities( adj_sets );
2363     return MB_FAILURE;
2364   }
2365 
2366   // CHECK TRACKING->SET
2367   // change to a standard set and check flags
2368   rval = mb->set_meshset_options( set, MESHSET_SET);MB_CHK_ERR(rval);
2369   rval = mb->get_meshset_options( set, flags );MB_CHK_ERR(rval);
2370   if(!(MESHSET_SET&flags) || (MESHSET_TRACK_OWNER&flags) || (MESHSET_ORDERED&flags) ){
2371     std::cerr << "set should be MESHSET_SET only, flags=" << flags
2372               << std::endl;
2373     return MB_FAILURE;
2374   }
2375   // the set should no longer be adjacent to the vertices
2376   adj_sets.clear();
2377   rval = mb->get_adjacencies( verts, 4, false, adj_sets);
2378   MB_CHK_ERR(rval);
2379   if(!adj_sets.empty()) {
2380     std::cerr << "range should be empty but contains:" << std::endl;
2381     rval = mb->list_entities( adj_sets );
2382     return MB_FAILURE;
2383   }
2384   // CHECK UNORDERED->ORDERED
2385   // add a duplicate vert
2386   rval = mb->add_entities( set, &verts.front(), 1);
2387   MB_CHK_ERR(rval);
2388   // unordered sets cannot hold duplicates so size shouldn't change
2389   std::vector<EntityHandle> entities;
2390   rval = mb->get_entities_by_handle( set, entities );
2391   if(10 != entities.size()) {
2392     std::cerr << "set should not hold duplicate entities" << std::endl;
2393     return MB_FAILURE;
2394   }
2395   // change to an ordered set and check flags
2396   rval = mb->set_meshset_options( set, MESHSET_ORDERED);
2397   MB_CHK_ERR(rval);
2398   rval = mb->get_meshset_options( set, flags );MB_CHK_ERR(rval);
2399   if( (MESHSET_SET&flags) || (MESHSET_TRACK_OWNER&flags) || !(MESHSET_ORDERED&flags) ){
2400     std::cerr << "set should be MESHSET_ORDERED only, flags=" << flags
2401               << std::endl;
2402     return MB_FAILURE;
2403   }
2404   // swap the order with some entities to that the handles aren't ordered
2405   rval = mb->clear_meshset( &set, 1 );
2406   MB_CHK_ERR(rval);
2407   entities.clear();
2408   entities.resize(2);
2409   entities[0] = verts[1];
2410   entities[1] = verts[0];
2411   rval = mb->add_entities( set, &entities[0], 2);
2412   MB_CHK_ERR(rval);
2413   // check to ensure the entities keep their order
2414   entities.clear();
2415   rval = mb->get_entities_by_handle( set, entities );
2416   if(verts[0]!=entities[1] || verts[1]!=entities[0]) {
2417     std::cerr << "ordered set did not keep its order" << std::endl;
2418     return MB_FAILURE;
2419   }
2420 
2421   // CHECK ORDERED->UNORDERED
2422   // change to an unordered set and check flags
2423   rval = mb->set_meshset_options( set, MESHSET_SET);
2424   MB_CHK_ERR(rval);
2425   rval = mb->get_meshset_options( set, flags );MB_CHK_ERR(rval);
2426   if(!(MESHSET_SET&flags) || (MESHSET_TRACK_OWNER&flags) || MESHSET_ORDERED&flags){
2427     std::cerr << "set should be MESHSET_SET only, flags=" << flags
2428               << std::endl;
2429     return MB_FAILURE;
2430   }
2431   // the entities in the set should now be ordered by handle
2432   entities.clear();
2433   rval = mb->get_entities_by_handle( set, entities );
2434   if(verts[0]!=entities[0] || verts[1]!=entities[1]) {
2435     std::cerr << "unordered set is still ordered" << std::endl;
2436     return MB_FAILURE;
2437   }
2438   return MB_SUCCESS;
2439 }
2440 
2441 #ifdef MOAB_HAVE_NETCDF
2442   // number of entities of type MBVERTEX, MBEDGE, MBDTri, MBQUAD, MBTET, and MBHEX
2443   // in mbtest1.g  (all other values are 0.
2444 static const EntityType types[] = { MBVERTEX, MBEDGE, MBTRI, MBQUAD, MBTET, MBHEX };
2445 const int num_types = sizeof(types)/sizeof(types[0]);
2446 static const unsigned int num_entities[num_types+1] = {47,12,18,8,22,8,0};
2447 
mb_delete_mesh_test()2448 ErrorCode mb_delete_mesh_test()
2449 {
2450   Core moab;
2451   Interface* gMB = &moab;
2452   ErrorCode error = load_file_one( gMB );
2453   if (MB_SUCCESS != error)
2454     return error;
2455 
2456     // Lets also test the global MB pointer (gMB) here.
2457   error = gMB->delete_mesh();
2458   if (error != MB_SUCCESS)
2459     return error;
2460 
2461     // load the mesh again
2462   error = load_file_one( gMB );
2463   if (error != MB_SUCCESS)
2464     return error;
2465 
2466 
2467     // step through each element type
2468   for (EntityType type = MBVERTEX; type != MBENTITYSET; type++)
2469   {
2470     // There should be entities
2471     Range entities;
2472     error = gMB->get_entities_by_type(0,  type, entities);
2473     if (error != MB_SUCCESS)
2474       return error;
2475 
2476     size_t idx = std::find( types, types+num_types, type ) - types;
2477     if ( entities.size() != num_entities[idx] )
2478       return MB_FAILURE;
2479   }
2480 
2481   return MB_SUCCESS;
2482 }
2483 
mb_mesh_set_tracking_test()2484 ErrorCode mb_mesh_set_tracking_test()
2485 {
2486   Core moab;
2487   Interface* MB = &moab;
2488 
2489     //read in a file so you have some data in the database
2490 
2491   ErrorCode error = load_file_one( MB );
2492   if (error != MB_SUCCESS)
2493     return error;
2494 
2495   EntityHandle ms1, ms2, ms3;
2496 
2497     //create meshsets
2498   ErrorCode result = MB->create_meshset( MESHSET_TRACK_OWNER | MESHSET_ORDERED, ms1 ) ;
2499   if(result != MB_SUCCESS )
2500     return result;
2501   result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms2 ) ;
2502   if(result != MB_SUCCESS )
2503     return result;
2504   result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms3 ) ;
2505   if(result != MB_SUCCESS )
2506     return result;
2507 
2508     // get all hexes
2509   Range hexes;
2510   result = MB->get_entities_by_type(0, MBHEX, hexes);
2511   if(result != MB_SUCCESS )
2512     return result;
2513 
2514     // get all tris
2515   Range tris;
2516   result = MB->get_entities_by_type(0, MBTRI, tris );
2517   if(result != MB_SUCCESS )
2518     return result;
2519 
2520     // get all tets
2521   Range temp_range;
2522   result = MB->get_entities_by_type(0, MBTET, temp_range);
2523   if(result != MB_SUCCESS )
2524     return result;
2525 
2526     //copy all the tets from the range into a vector 'tets'
2527   std::vector<EntityHandle> tets( temp_range.size() );
2528   std::copy(temp_range.begin(), temp_range.end(), tets.begin() );
2529 
2530     //Quick check on 'get_entities_by_dimension()'
2531   Range dim_3_range;
2532   result = MB->get_entities_by_dimension(0, 3, dim_3_range) ;
2533   if(result != MB_SUCCESS )
2534     return result;
2535 
2536     //hexes and tets should be only dimension 3 entities
2537   if( hexes.size() + tets.size() != dim_3_range.size() )
2538     return MB_FAILURE;
2539 
2540     //put all hexes in ms1, ms2, ms3
2541   result = MB->add_entities(ms1, hexes); //add ents in a range
2542   if(result != MB_SUCCESS )
2543     return result;
2544     // to ordered meshset
2545 
2546   result = MB->add_entities(ms2, hexes); //add ents in a range
2547   if(result != MB_SUCCESS )
2548     return result;
2549     //to unordered meshset
2550 
2551   result = MB->add_entities(ms3, hexes);
2552   if(result != MB_SUCCESS )
2553     return result;
2554 
2555     //put all tets in ms1, ms2
2556   if(MB->add_entities(ms1, &tets[0], tets.size()) != MB_SUCCESS )  //add ents in a vector
2557     return MB_FAILURE;                             //to ordered meshset
2558 
2559   if(MB->add_entities(ms2, &tets[0], tets.size()) != MB_SUCCESS )  //add ents in a vector
2560     return MB_FAILURE;                             //to unordered meshset
2561 
2562     //put all tris in ms1
2563   result = MB->add_entities(ms1, tris) ;
2564   if(result != MB_SUCCESS )
2565     return result;
2566 
2567   Range::iterator iter;
2568   iter = tris.begin();
2569 
2570   std::vector< EntityHandle > temp_vec;
2571 
2572     //ask a tri which meshsets it is in
2573   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2574   if(result != MB_SUCCESS )
2575     return result;
2576 
2577     //cout<<"tris temp_vec.size() = "<<temp_vec.size()<<endl;
2578   if( temp_vec.size() != 2 )
2579     return MB_FAILURE;
2580 
2581     //ask a tet which meshsets it is in
2582   temp_vec.clear();
2583   std::vector<EntityHandle>::iterator vec_iter = tets.begin();
2584   result = MB->get_adjacencies( &(*vec_iter), 1, 4, false, temp_vec ) ;
2585   if(result != MB_SUCCESS )
2586     return result;
2587 
2588     //cout<<"tet temp_vec.size() = "<<temp_vec.size()<<endl;
2589   if( temp_vec.size() != 3 )
2590     return MB_FAILURE;
2591 
2592     //ask a hex which meshsets it is in
2593   temp_vec.clear();
2594   iter = hexes.begin();
2595   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2596   if(result != MB_SUCCESS )
2597     return result;
2598 
2599     //should be in 4 temp_vec
2600   if( temp_vec.size() != 4 )
2601     return MB_FAILURE;
2602 
2603     //take this hex out of the ms1, ms2, ms3
2604   if(MB->remove_entities(ms1, &(*iter), 1) != MB_SUCCESS ) //remove ents in a vector
2605     return MB_FAILURE;                                   //from ordered meshset
2606 
2607   if(MB->remove_entities(ms2, &(*iter), 1) != MB_SUCCESS ) //remove ents in a vector
2608     return MB_FAILURE;                                   //from unordered meshset
2609 
2610   temp_range.clear();
2611   temp_range.insert(*iter);
2612   if(MB->remove_entities(ms3, temp_range) != MB_SUCCESS ) //remove ents in a range
2613     return MB_FAILURE;                                     //from unordered meshset
2614 
2615 
2616     //ask the hex how many meshsets it is in
2617   temp_vec.clear();
2618   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2619   if(result != MB_SUCCESS )
2620     return result;
2621   if( temp_vec.size() != 1 )
2622     return MB_FAILURE;
2623 
2624     //add the hex back into ms1
2625   result = MB->add_entities(ms1, temp_range) ;
2626   if(result != MB_SUCCESS )
2627     return result;
2628 
2629     //ask the hex how many meshsets it is in
2630   temp_vec.clear();
2631   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2632   if(result != MB_SUCCESS )
2633     return result;
2634   if( temp_vec.size() != 2 )
2635     return MB_FAILURE;
2636 
2637   temp_range.clear();
2638   temp_range.insert(*iter);
2639   if(MB->remove_entities(ms1, temp_range) != MB_SUCCESS ) //remove ents in a range
2640     return MB_FAILURE;                                     //from an ordered meshset
2641 
2642     //ask the hex how many meshsets it is in
2643   temp_vec.clear();
2644   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2645   if(result != MB_SUCCESS )
2646     return result;
2647   if( temp_vec.size() != 1 )
2648     return MB_FAILURE;
2649 
2650 
2651     //Deleting a meshset
2652 
2653   iter = tris.begin();
2654   temp_vec.clear();
2655     //ask a tri which meshsets it is in
2656   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2657   if(result != MB_SUCCESS )
2658     return result;
2659 
2660   if( temp_vec.size() != 2 )
2661     return MB_FAILURE;
2662 
2663     //Try deleting a meshset
2664   result = MB->delete_entities(&ms1, 1);
2665   if(result != MB_SUCCESS )
2666     return result;
2667 
2668   temp_vec.clear();
2669     //Query tri again for meshsets it's in
2670   result = MB->get_adjacencies( &(*iter), 1, 4, false, temp_vec ) ;
2671   if(result != MB_SUCCESS )
2672     return result;
2673 
2674   if( temp_vec.size() != 1 )
2675     return MB_FAILURE;
2676 
2677     //Delete an entitiy from ms2....make sure it's removed out of ms2
2678   int num_before = 0;
2679   MB->get_number_entities_by_handle(ms2, num_before);
2680   vec_iter = tets.begin();
2681   result = MB->delete_entities( &(*vec_iter), 1);
2682   if(result != MB_SUCCESS )
2683     return result;
2684 
2685   int num_after = 0;
2686   MB->get_number_entities_by_handle(ms2, num_after);
2687   if( num_before != num_after + 1)
2688     return MB_FAILURE;
2689 
2690 
2691   return MB_SUCCESS;
2692 
2693 }
2694 #endif
2695 
2696 // Compare internal representation of contents for a list (MESHSET_ORDERED)
2697 // set to expected contents.  Assumes expected contents are correctly
2698 // ordered.
check_list_meshset_internal(const EntityHandle * expected,int num_expected,const EntityHandle * contents,int length)2699 static ErrorCode check_list_meshset_internal(
2700                                               const EntityHandle* expected,
2701                                               int num_expected,
2702                                               const EntityHandle* contents,
2703                                               int length )
2704 {
2705   bool okay = true;
2706   for (int i = 0; i < std::min(num_expected, length); ++i) {
2707     if (expected[i] != contents[i]) {
2708       std::cerr << "List set contents differ at index " << i
2709                 << ": expected " << expected[i] << " but got "
2710                 << contents[i] << std::endl;
2711       okay = false;
2712     }
2713   }
2714   if (num_expected > length) {
2715     std::cerr << "List set is missing " << num_expected - length <<
2716                  "handles" << std::endl;
2717     okay = false;
2718   }
2719   else if (length > num_expected) {
2720     std::cerr << "List set has " << num_expected - length <<
2721                  " extra handles" << std::endl;
2722     okay = false;
2723   }
2724 
2725   if (okay)
2726     return MB_SUCCESS;
2727 
2728   std::cerr << "Expected contents: ";
2729   if (!num_expected)
2730     std::cerr << "(empty)";
2731   else
2732     std::cerr << expected[0];
2733   for (int i = 1; i < num_expected; ++i)
2734     std::cerr << ", " << expected[i];
2735   std::cerr << std::endl;
2736 
2737   std::cerr << "Actual contents: ";
2738   if (!length)
2739     std::cerr << "(empty)";
2740   else
2741     std::cerr << contents[0];
2742   for (int i = 1; i < length; ++i)
2743     std::cerr << ", " << contents[i];
2744   std::cerr << std::endl;
2745 
2746   return MB_FAILURE;
2747 }
2748 
2749 
2750 // Compare internal representation of contents for a ranged (MESHSET_SET)
2751 // set to expected contents.  Assumes expected contents are correctly
2752 // ordered.
check_ranged_meshset_internal(const EntityHandle * expected,int num_expected,const EntityHandle * contents,int length)2753 static ErrorCode check_ranged_meshset_internal(
2754                                                 const EntityHandle* expected,
2755                                                 int num_expected,
2756                                                 const EntityHandle* contents,
2757                                                 int length )
2758 {
2759   if (length % 2) {
2760     std::cerr << "Range set is corrupt.  Odd number of handles in content list" << std::endl;
2761     std::cerr << "Actual contents: " << contents[0];
2762     for (int i = 1; i < length; ++i)
2763       std::cerr << ", " << contents[i];
2764     std::cerr << std::endl;
2765     return MB_FAILURE;
2766   }
2767   bool okay = true;
2768     // check that all range pairs are valid (first handle less than or
2769     // equal to second)
2770   for (int i = 0; i < length; i += 2) {
2771     if (contents[i] > contents[i+1]) {
2772       std::cerr << "Range set has invalid range pair at index " << i
2773                 << ": [" << contents[i] << ',' << contents[i+1]
2774                 << ']' << std::endl;
2775       okay = false;
2776     }
2777   }
2778     // check that all range pairs are sorted and non-overlapping
2779     // (start of a range must be greater than end of previous range)
2780   for (int i = 2; i < length; i += 2) {
2781     if (contents[i] < contents[i-1]) {
2782       std::cerr << "Range set has incorrectly ordered ranges at index " << i
2783                 << ": [...," << contents[i-1] << "], [" << contents[i]
2784                 << ",...]" << std::endl;
2785       okay = false;
2786     }
2787     if (contents[i] == contents[i-1]+1) {
2788       std::cerr << "Range set has pairs that should have been merged at index " << i
2789                 << ": [...," << contents[i-1] << "], [" << contents[i]
2790                 << ",...]" << std::endl;
2791       okay = false;
2792     }
2793   }
2794   if (!okay) {
2795     std::cerr << "Actual contents: ";
2796     if (!length)
2797       std::cerr << "(empty)";
2798     else
2799       std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
2800     for (int i = 2; i < length; i += 2)
2801       std::cerr << ", [" << contents[i] << ',' << contents[i+1] << ']';
2802     std::cerr << std::endl;
2803     return MB_FAILURE;
2804   }
2805 
2806   int j = 0;
2807   for (int i = 0; i < length; i += 2) {
2808     for (; j < num_expected && expected[j] < contents[i]; ++j) {
2809       std::cerr << "Range set missing expected handle: " << expected[j] << std::endl;
2810       okay = false;
2811     }
2812     int k = j;
2813     while (k < num_expected && expected[k] <= contents[i+1])
2814       ++k;
2815     if ((EntityHandle)(k-j) <= (contents[i+1]-contents[i])) {
2816       std::cerr << "Handle range [" << contents[i] << ',' << contents[i+1]
2817                 << "] contains unexpected handles.  Expected handles: ";
2818       if (k == j)
2819         std::cerr << "(none)" << std::endl;
2820       else {
2821         std::cerr << expected[j];
2822         for (++j; j < k; ++j)
2823           std::cerr << ", " << expected[j];
2824         std::cerr << std::endl;
2825       }
2826       okay  = false;
2827     }
2828     j = k;
2829   }
2830 
2831   if (okay)
2832     return MB_SUCCESS;
2833 
2834   std::cerr << "Expected contents: ";
2835   if (!num_expected)
2836     std::cerr << "(empty)";
2837   else
2838     std::cerr << expected[0];
2839   for (int i = 1; i < num_expected; ++i)
2840     std::cerr << ", " << expected[i];
2841   std::cerr << std::endl;
2842 
2843   std::cerr << "Actual contents: ";
2844   if (!length)
2845     std::cerr << "(empty)";
2846   else
2847     std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
2848   for (int i = 2; i < length; i += 2)
2849     std::cerr << ", [" << contents[i] << ',' << contents[i+1] << ']';
2850   std::cerr << std::endl;
2851 
2852   return MB_FAILURE;
2853 }
2854 
2855 // Check the internal representation of a meshset
2856 // to verify that it is correct.
check_meshset_internal(Interface & mb,EntityHandle set,const EntityHandle * expected,int num_expected)2857 static ErrorCode check_meshset_internal( Interface& mb,
2858                                          EntityHandle set,
2859                                          const EntityHandle* expected,
2860                                          int num_expected )
2861 {
2862   ErrorCode rval;
2863   WriteUtilIface* tool = 0;
2864   rval = mb.query_interface( tool );
2865   MB_CHK_ERR(rval);
2866 
2867   const EntityHandle* contents;
2868   int length;
2869   unsigned char flags;
2870   rval = tool->get_entity_list_pointers( &set, 1, &contents,
2871                       WriteUtilIface::CONTENTS, &length, &flags );MB_CHK_ERR(rval);
2872   ErrorCode rval1 = mb.release_interface( tool );MB_CHK_ERR(rval1);
2873 
2874   if (flags & MESHSET_ORDERED)
2875     rval = check_list_meshset_internal( expected, num_expected, contents, length );
2876   else
2877     rval = check_ranged_meshset_internal( expected, num_expected, contents, length );
2878   MB_CHK_ERR(rval);
2879   return MB_SUCCESS;
2880 }
2881 
mb_mesh_set_set_add_remove_test()2882 ErrorCode mb_mesh_set_set_add_remove_test()
2883 {
2884   Core core;
2885   Interface& mb = core;
2886   EntityHandle set;
2887   ErrorCode rval = mb.create_meshset( MESHSET_SET, set );
2888   MB_CHK_ERR(rval);
2889 
2890   EntityHandle list1[] = {10, 16, 18, 20, 24, 27};
2891   size_t len1 = sizeof(list1)/sizeof(list1[0]);
2892   EntityHandle list2[] = {10, 16, 17, 18, 19, 20, 24, 27};
2893   size_t len2 = sizeof(list2)/sizeof(list2[0]);
2894   rval = mb.add_entities( set, list1, len1 );
2895   MB_CHK_ERR(rval);
2896   rval = check_meshset_internal( mb, set, list1, len1 );
2897   MB_CHK_ERR(rval);
2898   rval = mb.add_entities( set, list2, len2 );
2899   MB_CHK_ERR(rval);
2900   EntityHandle exp12[] = {10, 16, 17, 18, 19, 20, 24, 27};
2901   size_t len12 = sizeof(exp12)/sizeof(exp12[0]);
2902   rval = check_meshset_internal( mb, set, exp12, len12 );
2903   MB_CHK_ERR(rval);
2904 
2905   EntityHandle list3[] = { 15, 16, 18, 20, 21, 24, 28 };
2906   size_t len3 = sizeof(list3)/sizeof(list3[0]);
2907   rval = mb.remove_entities( set, list3, len3 );
2908   MB_CHK_ERR(rval);
2909   EntityHandle exp123[] = { 10, 17, 19, 27 };
2910   size_t len123 = sizeof(exp123)/sizeof(exp123[0]);
2911   rval = check_meshset_internal( mb, set, exp123, len123 );
2912   MB_CHK_ERR(rval);
2913 
2914   EntityHandle list4[] = { 18, 10, 11, 12, 13, 14, 15, 16 };
2915   size_t len4 = sizeof(list4)/sizeof(list4[0]);
2916   rval = mb.add_entities( set, list4, len4 );
2917   MB_CHK_ERR(rval);
2918   EntityHandle exp14[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27};
2919   size_t len14 = sizeof(exp14)/sizeof(exp14[0]);
2920   rval = check_meshset_internal( mb, set, exp14, len14 );
2921   MB_CHK_ERR(rval);
2922 
2923   EntityHandle list5[] = { 9, 10, 12, 13, 14, 15, 19, 20 };
2924   rval = mb.remove_entities( set, list5, sizeof(list5)/sizeof(list5[0]) );
2925   MB_CHK_ERR(rval);
2926   EntityHandle exp5[] = { 11, 16, 17, 18, 27 };
2927   rval = check_meshset_internal( mb, set, exp5, sizeof(exp5)/sizeof(exp5[0]) );
2928   MB_CHK_ERR(rval);
2929 
2930   EntityHandle list6[] = { 9, 10, 15, 16, 18, 19, 28 };
2931   rval = mb.add_entities( set, list6, sizeof(list6)/sizeof(list6[0]) );
2932   MB_CHK_ERR(rval);
2933   EntityHandle exp6[] = { 9, 10, 11, 15, 16, 17, 18, 19, 27, 28 };
2934   rval = check_meshset_internal( mb, set, exp6, sizeof(exp6)/sizeof(exp6[0]) );
2935   MB_CHK_ERR(rval);
2936 
2937   EntityHandle list7[] = { 13, 19, 27, 28 };
2938   rval = mb.add_entities( set, list7, sizeof(list7)/sizeof(list7[0]) );
2939   MB_CHK_ERR(rval);
2940   EntityHandle exp7[] = { 9, 10, 11, 13, 15, 16, 17, 18, 19, 27, 28 };
2941   rval = check_meshset_internal( mb, set, exp7, sizeof(exp7)/sizeof(exp7[0]) );
2942   MB_CHK_ERR(rval);
2943 
2944   EntityHandle list8[] = { 12, 14, 33 };
2945   rval = mb.add_entities( set, list8, sizeof(list8)/sizeof(list8[0]) );
2946   MB_CHK_ERR(rval);
2947   EntityHandle exp8[] = { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27, 28, 33 };
2948   rval = check_meshset_internal( mb, set, exp8, sizeof(exp8)/sizeof(exp8[0]) );
2949   MB_CHK_ERR(rval);
2950 
2951   EntityHandle list9[] = { 29, 30, 31, 32, 34 };
2952   rval = mb.remove_entities( set, list9, sizeof(list9)/sizeof(list9[0]) );
2953   MB_CHK_ERR(rval);
2954   rval = check_meshset_internal( mb, set, exp8, sizeof(exp8)/sizeof(exp8[0]) );
2955   MB_CHK_ERR(rval);
2956 
2957   EntityHandle list10[] = { 9, 11, 13, 17, 18, 19, 28, 33, 100 };
2958   rval = mb.remove_entities( set, list10, sizeof(list10)/sizeof(list10[0]) );
2959   MB_CHK_ERR(rval);
2960   EntityHandle exp10[] = { 10, 12, 14, 15, 16, 27 };
2961   rval = check_meshset_internal( mb, set, exp10, sizeof(exp10)/sizeof(exp10[0]) );
2962   MB_CHK_ERR(rval);
2963 
2964   EntityHandle list11[] = { 11, 12, 13, 14, 27, 28 };
2965   rval = mb.remove_entities( set, list11, sizeof(list11)/sizeof(list11[0]) );
2966   MB_CHK_ERR(rval);
2967   EntityHandle exp11[] = { 10, 15, 16 };
2968   rval = check_meshset_internal( mb, set, exp11, sizeof(exp11)/sizeof(exp11[0]) );
2969   MB_CHK_ERR(rval);
2970 
2971   EntityHandle list12[] = { 1, 10, 15, 16 };
2972   rval = mb.remove_entities( set, list12, sizeof(list12)/sizeof(list12[0]) );
2973   MB_CHK_ERR(rval);
2974   rval = check_meshset_internal( mb, set, 0, 0 );
2975   MB_CHK_ERR(rval);
2976 
2977   return MB_SUCCESS;
2978 }
2979 
2980 
mb_higher_order_test()2981 ErrorCode mb_higher_order_test()
2982 {
2983   Core moab;
2984   Interface *MB = &moab;
2985 
2986   double nodes_array [7][3];
2987 
2988   nodes_array[0][0] = 0;
2989   nodes_array[0][1] = 0;
2990   nodes_array[0][2] = 0;
2991   nodes_array[1][0] = 2;
2992   nodes_array[1][1] = 0;
2993   nodes_array[1][2] = 0;
2994   nodes_array[2][0] = 1;
2995   nodes_array[2][1] = 2;
2996   nodes_array[2][2] = 1;
2997   nodes_array[3][0] = 1;
2998   nodes_array[3][1] = 0;
2999   nodes_array[3][2] = 0;
3000   nodes_array[4][0] = 1.5;
3001   nodes_array[4][1] = 0.5;
3002   nodes_array[4][2] = 0.5;
3003   nodes_array[5][0] = 0.5;
3004   nodes_array[5][1] = 0.5;
3005   nodes_array[5][2] = 0.5;
3006   nodes_array[6][0] = 1;
3007   nodes_array[6][1] = 1;
3008   nodes_array[6][2] = 0.5;
3009 
3010 
3011     //create the nodes
3012   std::vector<EntityHandle> connectivity(8);
3013   EntityHandle node_handle;
3014   int i;
3015   for( i=0; i<7; i++)
3016   {
3017     if(MB->create_vertex( nodes_array[i], node_handle ) != MB_SUCCESS )
3018       return MB_FAILURE;
3019     connectivity[i] = node_handle;
3020   }
3021 
3022     //create the higher order tri
3023   EntityHandle tri_handle;
3024   ErrorCode result = MB->create_element(MBTRI, &connectivity[0], 6, tri_handle);
3025   if(result != MB_SUCCESS)
3026     return result;
3027 
3028     //create the higher order tri
3029   std::vector<EntityHandle> other_conn(3);
3030 
3031   double other_nodes[3][3];
3032   other_nodes[0][0] = 1.999;
3033   other_nodes[0][1] = 1.999;
3034   other_nodes[0][2] = 1.999;
3035   other_nodes[1][0] = 2.999;
3036   other_nodes[1][1] = 2.999;
3037   other_nodes[1][2] = 2.999;
3038   other_nodes[2][0] = 3.999;
3039   other_nodes[2][1] = 3.999;
3040   other_nodes[2][2] = 3.999;
3041 
3042   for( i=0; i<3; i++)
3043   {
3044     if(MB->create_vertex( other_nodes[i], node_handle ) != MB_SUCCESS )
3045       return MB_FAILURE;
3046     other_conn[i] = node_handle;
3047   }
3048 
3049   EntityHandle other_tri_handle;
3050   result = MB->create_element(MBTRI, &other_conn[0], 3, other_tri_handle);
3051   if(result != MB_SUCCESS)
3052     return result;
3053 
3054     //get the connectivity now
3055   std::vector<EntityHandle> retrieved_conn;
3056 
3057   result = MB->get_connectivity(&tri_handle, 1, retrieved_conn) ;
3058   if(result != MB_SUCCESS)
3059     return result;
3060 
3061   unsigned int k;
3062   for( k=0; k< retrieved_conn.size(); k++)
3063     if( connectivity[k] != retrieved_conn[k] )
3064       return MB_FAILURE;
3065 
3066   result = MB->get_connectivity(&other_tri_handle, 1, retrieved_conn) ;
3067   if(result != MB_SUCCESS)
3068     return result;
3069 
3070   for( k=0; k< other_conn.size(); k++)
3071     if( other_conn[k] != retrieved_conn[k] )
3072       return MB_FAILURE;
3073 
3074     // now let's just try getting the topological connectivity (the 3 corner vertices)
3075   std::vector<EntityHandle> topo_conn;
3076   result = MB->get_connectivity(&other_tri_handle, 1, topo_conn, true) ;
3077   if(result != MB_SUCCESS)
3078     return result;
3079 
3080   if (topo_conn.size() != 3)
3081     return MB_FAILURE;
3082 
3083   for ( k=0; k<3; k++)
3084     if (topo_conn[k] != retrieved_conn[k] )
3085       return MB_FAILURE;
3086 
3087     // short check to make sure that Core::handle_from_id() works
3088   unsigned long handle_id = MB->id_from_handle( node_handle);
3089 
3090   EntityHandle test_handle;
3091   result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
3092   if(result != MB_SUCCESS)
3093     return result;
3094 
3095   if( test_handle != node_handle )
3096     return MB_FAILURE;
3097 
3098 
3099   handle_id = MB->id_from_handle( tri_handle);
3100 
3101   result = MB->handle_from_id( MBTRI, handle_id, test_handle );
3102   if(result != MB_SUCCESS)
3103     return result;
3104 
3105   if( test_handle != tri_handle )
3106     return MB_FAILURE;
3107 
3108 
3109     //make up some bogus id
3110   handle_id = 2140824;
3111 
3112   result = MB->handle_from_id( MBTRI, handle_id, test_handle );
3113   if (result != MB_ENTITY_NOT_FOUND )
3114     return MB_FAILURE;
3115 
3116   result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
3117   if (result != MB_ENTITY_NOT_FOUND )
3118     return MB_FAILURE;
3119 
3120 
3121   return MB_SUCCESS;
3122 
3123 }
3124 
mb_bit_tags_test()3125 ErrorCode mb_bit_tags_test()
3126 {
3127   Core moab;
3128   Interface* MB = &moab;
3129   ErrorCode success = create_some_mesh( MB );
3130   if (MB_SUCCESS != success)
3131     return success;
3132 
3133   Tag bit_tag;
3134   Range entities;
3135   MB->get_entities_by_type(0, MBVERTEX, entities);
3136 
3137   if(MB->tag_get_handle("bit on vertex", 3, MB_TYPE_BIT, bit_tag, MB_TAG_CREAT) != MB_SUCCESS)
3138   {
3139     cout << "couldn't create bit tag" << endl;
3140     return MB_FAILURE;
3141   }
3142 
3143   Range::iterator iter;
3144   unsigned char bits;
3145   for(iter = entities.begin();
3146       iter != entities.end(); ++iter)
3147   {
3148       // tag each vertex with the low 3 bits of the entity handle
3149     bits = ((*iter) & 0x7);
3150     success = MB->tag_set_data(bit_tag, &(*iter), 1, &bits);
3151     if(success != MB_SUCCESS)
3152       return MB_FAILURE;
3153   }
3154 
3155   bits = 0;
3156   for(iter = entities.begin();
3157       iter != entities.end(); ++iter)
3158   {
3159       // tag each vertex with the low 3 bits of the entity handle
3160     success = MB->tag_get_data(bit_tag, &(*iter), 1, &bits);
3161     if(success != MB_SUCCESS)
3162       return MB_FAILURE;
3163 
3164     if(bits != ((*iter) & 0x7))
3165       return MB_FAILURE;
3166   }
3167 
3168   // test range-based query for all vertices
3169   std::vector<unsigned char> data(entities.size());
3170   success = MB->tag_get_data( bit_tag, entities, &data[0] );
3171   if (MB_SUCCESS != success) return success;
3172   std::vector<unsigned char>::iterator i = data.begin();
3173   for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
3174     if (*i != ((*iter) & 0x7))
3175       return MB_FAILURE;
3176 
3177   // test vector-based query for all vertices
3178   std::vector<EntityHandle> verts(entities.begin(), entities.end());
3179   success = MB->tag_get_data( bit_tag, &verts[0], verts.size(), &data[0] );
3180   if (MB_SUCCESS != success) return success;
3181   i = data.begin();
3182   for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
3183     if (*i != ((*iter) & 0x7))
3184       return MB_FAILURE;
3185 
3186   // test default value
3187   const unsigned char default_bits = '\005'; // 0000 0101
3188   Tag tag2;
3189   success = MB->tag_get_handle( "bit with default", 4, MB_TYPE_BIT, tag2, MB_TAG_CREAT, &default_bits );
3190   if (MB_SUCCESS != success) {
3191     cout << "Failed to create bit tag with default value" << std::endl;
3192     return success;
3193   }
3194 
3195   // set value to zero on a single vertex
3196   bits = 0;
3197   EntityHandle zh = verts[verts.size()/2];
3198   success = MB->tag_set_data( tag2, &zh, 1, &bits );
3199   if (MB_SUCCESS != success)
3200     return success;
3201 
3202   // get tag values for all entities
3203   data.clear();
3204   data.resize( verts.size(), 0x7A ); // initialize with 0111 1010
3205   success = MB->tag_get_data( tag2, entities, &data[0] );
3206   if (MB_SUCCESS != success)
3207     return success;
3208 
3209   // check values
3210   i = data.begin();
3211   for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
3212     if (*iter == zh && *i) // the one we set to zero
3213       return MB_FAILURE;
3214     else if (*iter != zh && *i != default_bits)
3215       return MB_FAILURE;
3216 
3217   return MB_SUCCESS;
3218 }
3219 
3220 #ifdef MOAB_HAVE_NETCDF
mb_tags_test()3221 ErrorCode mb_tags_test()
3222 {
3223   Core moab;
3224   Interface* MB = &moab;
3225   ErrorCode result = load_file_one( MB );
3226   if (MB_SUCCESS != result)
3227     return result;
3228 
3229   Tag stale_bits, stale_dense, stale_sparse;
3230   result = MB->tag_get_handle("stale data", 5, MB_TYPE_BIT, stale_bits, MB_TAG_CREAT);
3231   if (MB_SUCCESS != result)
3232     return result;
3233 
3234   int def_data = 9;
3235   result = MB->tag_get_handle("dense stale_data", 1, MB_TYPE_INTEGER, stale_dense, MB_TAG_DENSE|MB_TAG_EXCL, &def_data);
3236   if (MB_SUCCESS != result)
3237     return result;
3238   result = MB->tag_get_handle("sparse stale data", 1, MB_TYPE_INTEGER, stale_sparse, MB_TAG_SPARSE|MB_TAG_EXCL);
3239   if (MB_SUCCESS != result)
3240     return result;
3241 
3242   double coords[3] = { 0,0,0 };
3243   EntityHandle stale_handle1, stale_handle2;
3244   result = MB->create_vertex( coords, stale_handle1 );
3245   if (MB_SUCCESS != result)
3246     return result;
3247 
3248   unsigned char bits = 0x5;
3249   result = MB->tag_set_data(stale_bits, &stale_handle1, 1, &bits);
3250   if (MB_SUCCESS != result)
3251     return result;
3252   bits = 0;
3253   result = MB->tag_get_data(stale_bits, &stale_handle1, 1, &bits);
3254   if (MB_SUCCESS != result)
3255     return result;
3256   if (bits != 0x5)
3257     return MB_FAILURE;
3258 
3259   def_data = 1;
3260   result = MB->tag_set_data(stale_dense, &stale_handle1, 1, &def_data);
3261   if (MB_SUCCESS != result)
3262     return result;
3263   def_data = 0;
3264   result = MB->tag_get_data(stale_dense, &stale_handle1, 1, &def_data);
3265   if (MB_SUCCESS != result)
3266     return result;
3267   if (def_data != 1)
3268     return MB_FAILURE;
3269 
3270   def_data = 100;
3271   result = MB->tag_set_data(stale_sparse, &stale_handle1, 1, &def_data);
3272   if (MB_SUCCESS != result)
3273     return result;
3274   def_data = 0;
3275   result = MB->tag_get_data(stale_sparse, &stale_handle1, 1, &def_data);
3276   if (MB_SUCCESS != result)
3277     return result;
3278   if (def_data != 100)
3279     return MB_FAILURE;
3280 
3281   result = MB->delete_entities(&stale_handle1, 1);
3282   if (MB_SUCCESS != result)
3283     return result;
3284   result = MB->create_vertex(coords, stale_handle2);
3285   if (MB_SUCCESS != result)
3286     return result;
3287 
3288   if(stale_handle1 != stale_handle2)
3289     cout<< "Tag test could test stale data" << endl;
3290   else
3291   {
3292     bits=0;
3293     result = MB->tag_get_data(stale_bits, &stale_handle2, 1, &bits);
3294     if (MB_SUCCESS != result)
3295       return result;
3296     if(bits != 0)
3297       return MB_FAILURE;
3298 
3299     def_data = 3;
3300     result = MB->tag_get_data(stale_dense, &stale_handle2, 1, &def_data);
3301     if (MB_SUCCESS != result)
3302       return result;
3303     if(def_data != 9)
3304       return MB_FAILURE;
3305 
3306     def_data = 3;
3307     ErrorCode stale_result = MB->tag_get_data(stale_sparse, &stale_handle2, 1, &def_data);
3308       // we are supposed to fail here
3309     if(stale_result != MB_TAG_NOT_FOUND)
3310       return MB_FAILURE;
3311   }
3312 
3313   result = MB->tag_delete(stale_dense);
3314   if (MB_SUCCESS != result)
3315     return result;
3316 
3317   result = MB->delete_entities(&stale_handle2, 1);
3318   if (MB_SUCCESS != result)
3319     return result;
3320 
3321 
3322     //get all blocks with material tag and with tag_value of 1 (should only be 1)
3323   Range entities;
3324   int value = 1;
3325   const void *dum_ptr = &value;
3326   Tag material_tag;
3327   result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag);
3328   if (MB_SUCCESS != result)
3329     return result;
3330   if(MB->get_entities_by_type_and_tag( 0, MBENTITYSET, &material_tag,
3331                                        &dum_ptr,
3332                                        1, entities) != MB_SUCCESS)
3333     return MB_FAILURE;
3334 
3335   if( entities.size() != 1)
3336     return MB_FAILURE;
3337 
3338     //add a dense tag to hexes
3339   Tag junk_tag;
3340   if(MB->tag_get_handle( "junk_tag", 1, MB_TYPE_INTEGER, junk_tag, MB_TAG_DENSE|MB_TAG_EXCL)
3341      != MB_SUCCESS)
3342     return MB_FAILURE;
3343 
3344     //Set the dense tag on 5 hexes to 3489
3345   Range test_range;
3346   result = MB->get_entities_by_type(0,  MBHEX, test_range ) ;
3347   if(result != MB_SUCCESS)
3348     return result;
3349 
3350   Range::iterator iter, end_iter;
3351   iter = test_range.begin();
3352   end_iter = test_range.end();
3353 
3354   int data = 3489;
3355   const void *ptr_data = &data;
3356 
3357     //mark approxiamtely the first 20% of the hex entities; also put a bit tag on them
3358   unsigned int times = test_range.size()/5;
3359   bits = 0x5;
3360   const void *ptr_bits = &bits;
3361 
3362   for(unsigned int i=0; i<times; i++)
3363   {
3364     if(MB->tag_set_data( junk_tag, &(*iter), 1, &data ) != MB_SUCCESS )
3365       return MB_FAILURE;
3366     if(MB->tag_set_data( stale_bits, &(*iter), 1, &bits ) != MB_SUCCESS )
3367       return MB_FAILURE;
3368     ++iter;
3369   }
3370 
3371   entities.clear();
3372     //fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
3373   if(MB->get_entities_by_type_and_tag(0, MBHEX, &junk_tag,
3374                                       &ptr_data,
3375                                       1, entities ) != MB_SUCCESS)
3376     return MB_FAILURE;
3377 
3378   if( entities.size() != times)  //should get as many hexes as you perviously marked
3379     return MB_FAILURE;
3380 
3381     //fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
3382   entities.clear();
3383   if(MB->get_entities_by_type_and_tag(0, MBHEX, &stale_bits,
3384                                       &ptr_bits, 1, entities ) != MB_SUCCESS)
3385     return MB_FAILURE;
3386 
3387   if( entities.size() != times)  //should get as many hexes as you perviously marked
3388     return MB_FAILURE;
3389 
3390     // test fetch by tag value again, this time limiting the results
3391     // to the contents of an entity set
3392   EntityHandle meshset;
3393   result = MB->create_meshset( MESHSET_SET, meshset );
3394   if (MB_SUCCESS != result)
3395     return result;
3396   result = MB->add_entities( meshset, test_range );
3397   if (MB_SUCCESS != result)
3398     return result;
3399 
3400 
3401     //fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
3402   entities.clear();
3403   result = MB->get_entities_by_type_and_tag(meshset, MBHEX, &junk_tag,
3404                                       &ptr_data, 1, entities );
3405   if (MB_SUCCESS != result)
3406     return result;
3407 
3408   if( entities.size() != times)  //should get as many hexes as you perviously marked
3409     return MB_FAILURE;
3410 
3411     //fetch the hex entities of type--MBHEX, tag-"stale_bits", and tag value -- 0x5
3412   entities.clear();
3413   result = MB->get_entities_by_type_and_tag(meshset, MBHEX, &stale_bits,
3414                                       &ptr_bits, 1, entities );
3415   if (MB_SUCCESS != result)
3416     return result;
3417 
3418   if( entities.size() != times)  //should get as many hexes as you perviously marked
3419     return MB_FAILURE;
3420 
3421 
3422     // now try the query with an empty meshset, expecting to get back
3423     // an empty Range
3424 
3425   result = MB->create_meshset( MESHSET_SET, meshset );
3426   if (MB_SUCCESS != result)
3427     return result;
3428 
3429   entities.clear();
3430   result = MB->get_entities_by_type_and_tag(meshset, MBHEX, &junk_tag,
3431                                       &ptr_data, 1, entities );
3432   if (MB_SUCCESS != result)
3433     return result;
3434 
3435   if(!entities.empty())
3436     return MB_FAILURE;
3437 
3438 
3439 
3440   result = MB->tag_delete(stale_bits);
3441   if (MB_SUCCESS != result)
3442     return result;
3443 
3444   return MB_SUCCESS;
3445 }
3446 #endif
mb_common_tag_test(TagType storage)3447 ErrorCode mb_common_tag_test( TagType storage )
3448 {
3449   Core moab;
3450   Interface* mb = &moab;
3451   ErrorCode result = create_some_mesh( mb );
3452   if (MB_SUCCESS != result)
3453     return result;
3454 
3455   char tagname[64];
3456   sprintf( tagname, "t%d", rand() );
3457 
3458   Tag tag;
3459   const EntityHandle def_val = ~(EntityHandle)0;
3460   ErrorCode rval = mb->tag_get_handle( tagname,
3461                                        1, MB_TYPE_HANDLE,
3462                                        tag, storage|MB_TAG_EXCL,
3463                                        &def_val );
3464   if (MB_SUCCESS != rval)
3465     return rval;
3466 
3467 
3468   Range entities;
3469   mb->get_entities_by_handle( 0, entities );
3470   if (entities.empty())
3471     return MB_FAILURE;
3472 
3473     // set tag on every other entity to be the entities handle
3474   Range::const_iterator i;
3475   bool odd = true;
3476   for (i = entities.begin(); i != entities.end(); ++i, odd = !odd) {
3477     if (odd) {
3478       const EntityHandle h = *i;
3479       rval = mb->tag_set_data( tag, &h, 1, &h );
3480       if (MB_SUCCESS != rval)
3481         return rval;
3482     }
3483   }
3484 
3485     // check values on every entity -- expect default for every other entity
3486   odd = true;
3487   for (i = entities.begin(); i != entities.end(); ++i, odd = !odd) {
3488     EntityHandle val = 0;
3489     rval = mb->tag_get_data( tag, &*i, 1, &val );
3490     if (MB_SUCCESS != rval)
3491       return rval;
3492 
3493     if (odd) {
3494       if (val != *i)
3495         return MB_FAILURE;
3496     }
3497     else {
3498       if (val != def_val)
3499         return MB_FAILURE;
3500     }
3501   }
3502 
3503     // set tag values on all entities
3504   std::vector<EntityHandle> values( entities.size() );
3505   std::copy( entities.begin(), entities.end(), values.begin() );
3506   rval = mb->tag_set_data( tag, entities, &values[0] );
3507   if (MB_SUCCESS != rval)
3508     return rval;
3509 
3510     // check values on every entity -- expect default for every other entity
3511   for (i = entities.begin(); i != entities.end(); ++i) {
3512     EntityHandle val = 0;
3513     rval = mb->tag_get_data( tag, &*i, 1, &val );
3514     if (MB_SUCCESS != rval)
3515       return rval;
3516     if (val != *i)
3517       return MB_FAILURE;
3518   }
3519 
3520     // find each entity by tag value
3521   for (i = entities.begin(); i != entities.end(); ++i) {
3522     const EntityHandle h = *i;
3523     const EntityType type = mb->type_from_handle( h );
3524     const void* const tag_vals[] = { &h };
3525     Range range;
3526     rval = mb->get_entities_by_type_and_tag( 0, type, &tag, tag_vals, 1, range );
3527     if (MB_SUCCESS != rval)
3528       return rval;
3529     if (range.size() != 1)
3530       return MB_FAILURE;
3531     if (range.front() != h)
3532       return MB_FAILURE;
3533   }
3534 
3535   return MB_SUCCESS;
3536 }
3537 
3538 
mb_dense_tag_test()3539 ErrorCode mb_dense_tag_test()
3540 {
3541   return mb_common_tag_test( MB_TAG_DENSE );
3542 }
3543 
mb_sparse_tag_test()3544 ErrorCode mb_sparse_tag_test()
3545 {
3546   return mb_common_tag_test( MB_TAG_SPARSE );
3547 }
3548 
3549 // class to offset hex center nodes
3550 class OffsetHexCenterNodes : public Interface::HONodeAddedRemoved
3551 {
3552 public:
OffsetHexCenterNodes(Interface * mb,double x,double y,double z)3553   OffsetHexCenterNodes(Interface* mb, double x, double y, double z)
3554       : gMB(mb)
3555     {
3556       mCoords[0] = 0.0; mCoords[1] = 0.0; mCoords[2] = 0.0;
3557       mOffset[0] = x; mOffset[1] = y; mOffset[2] = z;
3558     }
3559 
~OffsetHexCenterNodes()3560   ~OffsetHexCenterNodes(){}
3561 
node_added(EntityHandle node,EntityHandle)3562   void node_added(EntityHandle node, EntityHandle)
3563     {
3564       gMB->get_coords(&node, 1, mCoords);
3565       mCoords[0] += mOffset[0];
3566       mCoords[1] += mOffset[1];
3567       mCoords[2] += mOffset[2];
3568       gMB->set_coords(&node, 1, mCoords);
3569     }
3570 
3571     //do nothing
node_removed(EntityHandle)3572   void node_removed( EntityHandle /*node*/) {}
3573 
3574 private:
3575   Interface* gMB;
3576   double mCoords[3];
3577   double mOffset[3];
3578 };
3579 #ifdef MOAB_HAVE_NETCDF
mb_entity_conversion_test()3580 ErrorCode mb_entity_conversion_test()
3581 {
3582   ErrorCode error;
3583   Core moab;
3584   Interface* MB = &moab;
3585 
3586     //read in a file so you have some data in the database
3587   std::string file_name = TestDir + "/mbtest3.g";
3588   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3589   if (error != MB_SUCCESS)
3590     return error;
3591 
3592   Range entities;
3593   EntityHandle meshset;
3594   MB->create_meshset(MESHSET_SET, meshset);
3595 
3596   MB->get_entities_by_type(0, MBHEX, entities);
3597   MB->add_entities(meshset, entities);
3598 
3599 
3600   OffsetHexCenterNodes function_object(MB,0.07, 0.15, 0);
3601 
3602   MB->convert_entities(meshset, false, false, true, &function_object);
3603   if (MB_SUCCESS != check_valid_connectivity( MB ))
3604     return MB_FAILURE;
3605 
3606   file_name = "hex_mid_volume_nodes.g";
3607   error = MB->write_mesh(file_name.c_str());
3608   if (error != MB_SUCCESS)
3609     return error;
3610 
3611   error = MB->delete_mesh();
3612   if (error != MB_SUCCESS)
3613     return error;
3614 
3615   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3616   if (error != MB_SUCCESS)
3617     return error;
3618 
3619   error = MB->delete_mesh();
3620   if (error != MB_SUCCESS)
3621     return error;
3622 
3623 
3624 
3625 
3626 
3627   file_name = TestDir + "/mbtest3.g";
3628   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3629   if (error != MB_SUCCESS)
3630     return error;
3631 
3632   entities.clear();
3633   MB->get_entities_by_type(0, MBHEX, entities);
3634 
3635   MB->create_meshset(MESHSET_SET, meshset);
3636   MB->add_entities(meshset, entities);
3637   MB->convert_entities(meshset, true, true, true);
3638   if (MB_SUCCESS != check_valid_connectivity( MB ))
3639     return MB_FAILURE;
3640 
3641   file_name = "hex_mid_edge_face_vol_nodes.g";
3642   error = MB->write_mesh(file_name.c_str());
3643   if (error != MB_SUCCESS)
3644     return error;
3645 
3646   error = MB->delete_mesh();
3647   if (error != MB_SUCCESS)
3648     return error;
3649 
3650   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3651   if (error != MB_SUCCESS)
3652     return error;
3653 
3654   error = MB->delete_mesh();
3655   if (error != MB_SUCCESS)
3656     return error;
3657 
3658 
3659 
3660 
3661 
3662   file_name = TestDir + "/mbtest3.g";
3663   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3664   if (error != MB_SUCCESS)
3665     return error;
3666 
3667   entities.clear();
3668   MB->get_entities_by_type(0, MBVERTEX, entities);
3669   unsigned int original_num_nodes = entities.size();
3670   entities.clear();
3671   MB->get_entities_by_type(0, MBHEX, entities);
3672 
3673   MB->create_meshset(MESHSET_SET, meshset);
3674   MB->add_entities(meshset, entities);
3675   MB->convert_entities(meshset, true, false, false);
3676   if (MB_SUCCESS != check_valid_connectivity( MB ))
3677     return MB_FAILURE;
3678 
3679   file_name = "hex_mid_edge_nodes.g";
3680   error = MB->write_mesh(file_name.c_str());
3681   if (error != MB_SUCCESS)
3682     return error;
3683 
3684     // convert them back to hex8's
3685   MB->convert_entities(meshset, false, false, false);
3686   if (MB_SUCCESS != check_valid_connectivity( MB ))
3687     return MB_FAILURE;
3688 
3689   entities.clear();
3690   MB->get_entities_by_type(0, MBVERTEX, entities);
3691     // make sure the higher order nodes really were deleted
3692   if(entities.size() != original_num_nodes)
3693     return MB_FAILURE;
3694 
3695   error = MB->delete_mesh();
3696   if (error != MB_SUCCESS)
3697     return error;
3698 
3699   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3700   if (error != MB_SUCCESS)
3701     return error;
3702 
3703   error = MB->delete_mesh();
3704   if (error != MB_SUCCESS)
3705     return error;
3706 
3707 
3708 
3709 
3710   file_name = TestDir + "/mbtest1.g";
3711   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3712   if (error != MB_SUCCESS)
3713     return error;
3714 
3715   entities.clear();
3716   MB->get_entities_by_type(0, MBTET, entities);
3717 
3718   MB->create_meshset(MESHSET_SET, meshset);
3719   MB->add_entities(meshset, entities);
3720   MB->convert_entities(meshset, true, false, false);
3721   if (MB_SUCCESS != check_valid_connectivity( MB ))
3722     return MB_FAILURE;
3723 
3724   file_name = "tet_mid_edge_nodes.g";
3725   error = MB->write_mesh(file_name.c_str());
3726   if (error != MB_SUCCESS)
3727     return error;
3728 
3729   error = MB->delete_mesh();
3730   if (error != MB_SUCCESS)
3731     return error;
3732 
3733   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3734   if (error != MB_SUCCESS)
3735     return error;
3736 
3737   error = MB->delete_mesh();
3738   if (error != MB_SUCCESS)
3739     return error;
3740 
3741 
3742 
3743   file_name = TestDir + "/mbtest1.g";
3744   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3745   if (error != MB_SUCCESS)
3746     return error;
3747 
3748   entities.clear();
3749   MB->get_entities_by_type(0, MBTET, entities);
3750 
3751   MB->create_meshset(MESHSET_SET, meshset);
3752   MB->add_entities(meshset, entities);
3753   MB->convert_entities(meshset, false, true, false);
3754   if (MB_SUCCESS != check_valid_connectivity( MB ))
3755     return MB_FAILURE;
3756 
3757   file_name = "tet_mid_face_nodes.g";
3758   error = MB->write_mesh(file_name.c_str());
3759   if (error != MB_SUCCESS)
3760     return error;
3761 
3762   error = MB->delete_mesh();
3763   if (error != MB_SUCCESS)
3764     return error;
3765 
3766   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3767   if (error != MB_SUCCESS)
3768     return error;
3769 
3770   error = MB->delete_mesh();
3771   if (error != MB_SUCCESS)
3772     return error;
3773 
3774 
3775 
3776 
3777 
3778 
3779 
3780   file_name = TestDir + "/mbtest1.g";
3781   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3782   if (error != MB_SUCCESS)
3783     return error;
3784 
3785   entities.clear();
3786   MB->get_entities_by_type(0, MBTET, entities);
3787 
3788   MB->create_meshset(MESHSET_SET, meshset);
3789   MB->add_entities(meshset, entities);
3790   MB->convert_entities(meshset, true, true, false);
3791   if (MB_SUCCESS != check_valid_connectivity( MB ))
3792     return MB_FAILURE;
3793 
3794   file_name = "tet_mid_edge_face_nodes.g";
3795   error = MB->write_mesh(file_name.c_str());
3796   if (error != MB_SUCCESS)
3797     return error;
3798 
3799   error = MB->delete_mesh();
3800   if (error != MB_SUCCESS)
3801     return error;
3802 
3803   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3804   if (error != MB_SUCCESS)
3805     return error;
3806 
3807   error = MB->delete_mesh();
3808   if (error != MB_SUCCESS)
3809     return error;
3810 
3811 
3812 
3813 
3814   file_name = TestDir + "/mbtest1.g";
3815   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3816   if (error != MB_SUCCESS)
3817     return error;
3818 
3819     // delete all MBTRI's
3820   entities.clear();
3821   error = MB->get_entities_by_type(0, MBTRI, entities);
3822   if (MB_SUCCESS != error)
3823     return error;
3824   error = MB->delete_entities(entities);
3825   if (MB_SUCCESS != error)
3826     return error;
3827 
3828   entities.clear();
3829   error = MB->get_entities_by_type(0, MBTET, entities);
3830   if (MB_SUCCESS != error)
3831     return error;
3832 
3833     // skin the model
3834   for(Range::iterator tet_iter = entities.begin(); tet_iter != entities.end(); ++tet_iter)
3835   {
3836     std::vector<EntityHandle> adj;
3837     error = MB->get_adjacencies(&(*tet_iter), 1, 2, true, adj);
3838     if (MB_SUCCESS != error)
3839       return error;
3840     for(std::vector<EntityHandle>::iterator tri_iter = adj.begin();
3841         tri_iter != adj.end(); ++tri_iter)
3842     {
3843       std::vector<EntityHandle> up_adj;
3844       MB->get_adjacencies(&(*tri_iter), 1, 3, false, up_adj);
3845       if(up_adj.size() > 1) {
3846         error = MB->delete_entities(&(*tri_iter), 1);
3847         if (MB_SUCCESS != error)
3848           return error;
3849       }
3850     }
3851   }
3852 
3853     // create a meshset of the skin
3854   EntityHandle export_meshset;
3855   MB->create_meshset( MESHSET_SET, export_meshset);
3856   Tag material_tag;
3857   MB->tag_get_handle(MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag);
3858   int block_id = 100;
3859   MB->tag_set_data(material_tag, &export_meshset, 1, &block_id);
3860   entities.clear();
3861   MB->get_entities_by_type(0, MBTRI, entities);
3862     // remove the first few tri's for fun
3863   Range tmp_ents;
3864   tmp_ents.insert(*entities.begin());
3865   entities.erase(entities.begin());
3866   tmp_ents.insert(*entities.begin());
3867   entities.erase(entities.begin());
3868   tmp_ents.insert(*entities.begin());
3869   entities.erase(entities.begin());
3870   tmp_ents.insert(*entities.begin());
3871   entities.erase(entities.begin());
3872 
3873   MB->add_entities(export_meshset, entities);
3874 
3875     // convert the skin
3876   MB->convert_entities(export_meshset, true, true, false);
3877   if (MB_SUCCESS != check_valid_connectivity( MB ))
3878     return MB_FAILURE;
3879 
3880     // make sure our first few tri's were untouched
3881   std::vector<EntityHandle> conn(3);
3882   for(Range::iterator kter=tmp_ents.begin(); kter != tmp_ents.end(); ++kter)
3883   {
3884     MB->get_connectivity(&(*kter), 1, conn);
3885     if(conn.size() != 3)
3886       return MB_FAILURE;
3887   }
3888 
3889     // output the skin
3890   file_name = "tri_mid_edge_face_nodes.g";
3891   error = MB->write_mesh(file_name.c_str(), &export_meshset, 1);
3892   if (error != MB_SUCCESS)
3893     return error;
3894 
3895   MB->delete_entities(&export_meshset, 1);
3896 
3897   error = MB->delete_mesh();
3898   if (error != MB_SUCCESS)
3899     return error;
3900 
3901     //read the skin back in
3902   error = MB->load_mesh(file_name.c_str(), NULL, 0);
3903   if (error != MB_SUCCESS)
3904     return error;
3905 
3906   entities.clear();
3907   MB->get_entities_by_type(0, MBVERTEX, entities);
3908     // must have 101 nodes
3909   if(entities.size() != 101)
3910     return MB_FAILURE;
3911 
3912   error = MB->delete_mesh();
3913   if (error != MB_SUCCESS)
3914     return error;
3915 
3916 
3917   return MB_SUCCESS;
3918 }
3919 #endif
3920 //! Build two Quads with two edges shared between them.  The
3921 //! edges share the same nodes.  We should be able to get
3922 //! adjacencies on the edges and get one (correct) quad.  We
3923 //! should be able to get the edge adjacencies of the quads
3924 //! and only get 4 (not 5) edges.
3925 //!
3926 
mb_forced_adjacencies_test()3927 ErrorCode mb_forced_adjacencies_test()
3928 {
3929     //! first clean up any existing mesh.
3930   ErrorCode error;
3931   Core moab;
3932   Interface* MB = &moab;
3933 
3934 
3935     //! create 6 nodes, 2 quads and 8 edges.  Edge 4 is adjacent
3936     //! to quad 1 and edge 5 is adjacent to quad 2.
3937     //!
3938     //!  4       5       6
3939     //!  o--e7---o--e8---o
3940     //!  |       |       |
3941     //!  e3 q1 e4 e5 q2  e6
3942     //!  |       |       |
3943     //!  o--e1---o--e2---o
3944     //!  1       2       3
3945     //!
3946   double node_coord1[3] = {0., 0., 0.};
3947   double node_coord2[3] = {1., 0., 0.};
3948   double node_coord3[3] = {2., 0., 0.};
3949   double node_coord4[3] = {0., 1., 0.};
3950   double node_coord5[3] = {1., 1., 0.};
3951   double node_coord6[3] = {2., 1., 0.};
3952 
3953   EntityHandle node1, node2, node3, node4, node5, node6;
3954   error = MB->create_vertex(node_coord1, node1);
3955   if (error != MB_SUCCESS)
3956     return error;
3957 
3958   error = MB->create_vertex(node_coord2, node2);
3959   if (error != MB_SUCCESS)
3960     return error;
3961 
3962   error = MB->create_vertex(node_coord3, node3);
3963   if (error != MB_SUCCESS)
3964     return error;
3965 
3966   error = MB->create_vertex(node_coord4, node4);
3967   if (error != MB_SUCCESS)
3968     return error;
3969 
3970   error = MB->create_vertex(node_coord5, node5);
3971   if (error != MB_SUCCESS)
3972     return error;
3973 
3974   error = MB->create_vertex(node_coord6, node6);
3975   if (error != MB_SUCCESS)
3976     return error;
3977 
3978   std::vector<EntityHandle> conn(4);
3979     //! create the first quad
3980   EntityHandle              quad1;
3981   conn[0] = node1;
3982   conn[1] = node2;
3983   conn[2] = node5;
3984   conn[3] = node4;
3985   error = MB->create_element(MBQUAD, &conn[0], 4, quad1);
3986   if (error != MB_SUCCESS)
3987     return error;
3988 
3989     //! create the second quad
3990   EntityHandle              quad2;
3991   conn[0] = node2;
3992   conn[1] = node3;
3993   conn[2] = node6;
3994   conn[3] = node5;
3995   error = MB->create_element(MBQUAD, &conn[0], 4, quad2);
3996   if (error != MB_SUCCESS)
3997     return error;
3998 
3999     //! create the edges
4000   EntityHandle edge1;
4001   conn.resize(2);
4002   conn[0] = node1;
4003   conn[1] = node2;
4004   error = MB->create_element(MBEDGE, &conn[0], 2, edge1);
4005   if (error != MB_SUCCESS)
4006     return error;
4007 
4008   EntityHandle edge2;
4009   conn[0] = node2;
4010   conn[1] = node3;
4011   error = MB->create_element(MBEDGE, &conn[0], 2, edge2);
4012   if (error != MB_SUCCESS)
4013     return error;
4014 
4015   EntityHandle edge3;
4016   conn[0] = node1;
4017   conn[1] = node4;
4018   error = MB->create_element(MBEDGE, &conn[0], 2, edge3);
4019   if (error != MB_SUCCESS)
4020     return error;
4021 
4022   EntityHandle edge4;
4023   conn[0] = node2;
4024   conn[1] = node5;
4025   error = MB->create_element(MBEDGE, &conn[0], 2, edge4);
4026   if (error != MB_SUCCESS)
4027     return error;
4028 
4029   EntityHandle edge5;
4030   conn[0] = node2;
4031   conn[1] = node5;
4032   error = MB->create_element(MBEDGE, &conn[0], 2, edge5);
4033   if (error != MB_SUCCESS)
4034     return error;
4035 
4036   EntityHandle edge6;
4037   conn[0] = node3;
4038   conn[1] = node6;
4039   error = MB->create_element(MBEDGE, &conn[0], 2, edge6);
4040   if (error != MB_SUCCESS)
4041     return error;
4042 
4043   EntityHandle edge7;
4044   conn[0] = node4;
4045   conn[1] = node5;
4046   error = MB->create_element(MBEDGE, &conn[0], 2, edge7);
4047   if (error != MB_SUCCESS)
4048     return error;
4049 
4050   EntityHandle edge8;
4051   conn[0] = node5;
4052   conn[1] = node6;
4053   error = MB->create_element(MBEDGE, &conn[0], 2, edge8);
4054   if (error != MB_SUCCESS)
4055     return error;
4056 
4057 
4058     //! Edge 4 and 5 share the same nodes, but should be different entities
4059   if (edge4 == edge5)
4060     return MB_FAILURE;
4061 
4062     //! Now that the geometry is created start adding the adjacency information
4063   std::vector<EntityHandle> edge_adjacencies1(4);
4064   edge_adjacencies1[0] = edge1;
4065   edge_adjacencies1[1] = edge4;
4066   edge_adjacencies1[2] = edge7;
4067   edge_adjacencies1[3] = edge3;
4068 
4069     //! does this (should this) say anything about order of the edges around the
4070     //! quad?  Also, does this also build the edge->quad adjacency, or is that
4071     //! does with a separate call?
4072   error = MB->add_adjacencies(quad1, &edge_adjacencies1[0], edge_adjacencies1.size(), true);
4073   if (error != MB_SUCCESS)
4074     return error;
4075 
4076   std::vector<EntityHandle> edge_adjacencies2(4);
4077   edge_adjacencies2[0] = edge2;
4078   edge_adjacencies2[1] = edge6;
4079   edge_adjacencies2[2] = edge8;
4080   edge_adjacencies2[3] = edge5;
4081   error = MB->add_adjacencies(quad2, &edge_adjacencies2[0], edge_adjacencies2.size(), true);
4082   if (error != MB_SUCCESS)
4083     return error;
4084 
4085     //! now get the adjacencies of each quad.
4086   std::vector<EntityHandle> quad1_adjacencies;
4087   error = MB->get_adjacencies(&(quad1), 1, 1, false, quad1_adjacencies);
4088   if (error != MB_SUCCESS)
4089     return error;
4090 
4091 
4092   std::sort(quad1_adjacencies.begin(), quad1_adjacencies.end());
4093   std::sort(edge_adjacencies1.begin(), edge_adjacencies1.end());
4094 
4095   if (quad1_adjacencies != edge_adjacencies1)
4096     return MB_FAILURE;
4097 
4098   std::vector<EntityHandle> quad2_adjacencies;
4099   error = MB->get_adjacencies(&(quad2), 1, 1, false, quad2_adjacencies);
4100   if (error != MB_SUCCESS)
4101     return error;
4102 
4103   std::sort(quad2_adjacencies.begin(), quad2_adjacencies.end());
4104   std::sort(edge_adjacencies2.begin(), edge_adjacencies2.end());
4105 
4106   if (quad2_adjacencies != edge_adjacencies2)
4107     return MB_FAILURE;
4108 
4109     //! try getting the adjacency of edge1 (should be quad1)
4110   std::vector<EntityHandle> edge1_adjacencies;
4111   error = MB->get_adjacencies(&(edge1), 1, 2, false, edge1_adjacencies);
4112   if (error != MB_SUCCESS)
4113     return error;
4114 
4115     //! there should be only 1 entity adjacent to edge1
4116   if (edge1_adjacencies.size() != 1)
4117     return MB_FAILURE;
4118 
4119     //! and that entity should be quad1
4120   if (edge1_adjacencies[0] != quad1)
4121     return MB_FAILURE;
4122 
4123     //! try getting the adjacency of edge6 (should be one)
4124   std::vector<EntityHandle> edge6_adjacencies;
4125   error = MB->get_adjacencies(&(edge6), 1, 2, false, edge6_adjacencies);
4126   if (error != MB_SUCCESS)
4127     return error;
4128 
4129     //! there should be only 1 entity adjacent to edge6
4130   if (edge6_adjacencies.size() != 1)
4131     return MB_FAILURE;
4132 
4133     //! Now seal up the "gap" caused by edges 4 and 5.  Remove edge5
4134     //! from the adjacencies of quad2 and add edge 4 to quad2.
4135 
4136   std::vector<EntityHandle> edge5_adjacencies(1, edge5);
4137   error = MB->remove_adjacencies(quad2, &edge5_adjacencies[0], edge5_adjacencies.size());
4138   if (error != MB_SUCCESS)
4139     return error;
4140 
4141 
4142   std::vector<EntityHandle> edge4_adjacencies(1, edge4);
4143   error = MB->add_adjacencies(quad2, &edge4_adjacencies[0], edge4_adjacencies.size(), true);
4144   if (error != MB_SUCCESS)
4145     return error;
4146 
4147     //! get the adjacencies of edge4 and it should return both quads.
4148   std::vector<EntityHandle> quad_adjacencies;
4149   error = MB->get_adjacencies(&(edge4), 1, 2, false, quad_adjacencies);
4150   if (error != MB_SUCCESS)
4151     return error;
4152 
4153     //! there should be 2 entities adjacent to edge4
4154   if (quad_adjacencies.size() != 2)
4155     return MB_FAILURE;
4156 
4157     //! and they should be quad1 and quad2.  Note that we are not saying anything
4158     //! about order in the array.
4159   if ( (quad_adjacencies[0] != quad1 || quad_adjacencies[1] != quad2) &&
4160        (quad_adjacencies[0] != quad2 || quad_adjacencies[1] != quad1) )
4161     return MB_FAILURE;
4162 
4163     //! clean up on exit
4164   error = MB->delete_mesh();
4165   if (error != MB_SUCCESS)
4166     return error;
4167 
4168 
4169   return MB_SUCCESS;
4170 }
4171 
4172 /*bool lessnodesZ(const EntityHandle entity_handle1, const EntityHandle entity_handle2)
4173   {
4174   double coords1[3], coords2[3];
4175   gMB->get_coords(entity_handle1, coords1);
4176   gMB->get_coords(entity_handle2, coords2);
4177 
4178   return coords2[2] < coords1[2];
4179   }*/
4180 
4181 /*void sort_verts(Range vertices)
4182   {
4183   std::vector<EntityHandle> vert_vec(vertices.size());
4184   Range::const_iterator iter;
4185   for (iter = vertices.begin(); iter != vertices.end(); ++iter)
4186   vert_vec.push_back(*iter);
4187   vert_vec.sort(lessnodesZ);
4188   }*/
points_are_coincident(const double * first,const double * second)4189 bool points_are_coincident(const double *first, const double *second)
4190 {
4191   double diff[3];
4192   diff[2] = first[2] - second[2];
4193     //  if (diff[2] > 0.001) return false;
4194 
4195   diff[0] = first[0] - second[0];
4196   diff[1] = first[1] - second[1];
4197 
4198   double length = diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2];
4199   if(fabs(length) < .001)
4200     return true;
4201 
4202   return false;
4203 }
find_coincident_nodes(Interface * gMB,Range vertices,std::vector<std::pair<EntityHandle,EntityHandle>> & coin_nodes)4204 ErrorCode find_coincident_nodes(Interface* gMB, Range vertices,
4205                                   std::vector< std::pair<EntityHandle,EntityHandle> > &coin_nodes)
4206 {
4207   double first_coords[3], second_coords[3];
4208   Range::const_iterator iter, jter;
4209   std::pair<EntityHandle, EntityHandle> coincident_pair;
4210   ErrorCode result;
4211 
4212   for (iter = vertices.begin(); iter != vertices.end(); ++iter)
4213   {
4214     result = gMB->get_coords(&(*iter),1, first_coords);
4215     if (result != MB_SUCCESS)
4216       return result;
4217 
4218     for (jter = iter; jter != vertices.end(); ++jter)
4219     {
4220       if (*iter != *jter)
4221       {
4222         result = gMB->get_coords(&(*jter), 1, second_coords);
4223         if (result != MB_SUCCESS)
4224           return result;
4225 
4226         if(points_are_coincident(first_coords, second_coords))
4227         {
4228           coincident_pair.first  = *iter;
4229           coincident_pair.second = *jter;
4230           coin_nodes.push_back(coincident_pair);
4231         }
4232       }
4233     }
4234   }
4235   return MB_SUCCESS;
4236 }
4237 
find_coincident_elements(Interface * gMB,Range entities,int num_nodes,std::vector<std::pair<EntityHandle,EntityHandle>> & coin)4238 ErrorCode find_coincident_elements(Interface* gMB, Range entities, int num_nodes,
4239                                      std::vector< std::pair<EntityHandle,EntityHandle> > &coin)
4240 {
4241   double coords1[8][3], coords2[8][3];
4242   Range::iterator iter, jter;
4243   std::vector<EntityHandle> conn(8);
4244   std::pair<EntityHandle, EntityHandle> coincident_pair;
4245   int i = 0,/* j = 0,*/ ii = 0;
4246 
4247   for(iter = entities.begin(); iter != entities.end(); ++iter)
4248   {
4249       // Get the coordinates for the element corners.
4250     if(gMB->get_connectivity(&(*iter), 1, conn) != MB_SUCCESS)
4251       return MB_FAILURE;
4252     for(ii=0; ii<num_nodes; ii++)
4253     {
4254       if(gMB->get_coords(&(conn[ii]), 1, coords1[ii]) != MB_SUCCESS)
4255         return MB_FAILURE;
4256     }
4257 
4258     for(jter = iter; jter != entities.end(); ++jter)
4259     {
4260       if(*iter != *jter)
4261       {
4262           // Elements should be the same sense to merge.
4263         if(gMB->get_connectivity(&(*jter), 1, conn) != MB_SUCCESS)
4264           return MB_FAILURE;
4265 
4266         for (int tq = 0; tq < num_nodes; tq++)
4267           if(gMB->get_coords(&(conn[tq]), 1,  coords2[tq]) != MB_SUCCESS)
4268             return MB_FAILURE;
4269           //        if(gMB->get_coords(&(conn[0]), 1,  coords2[0]) != MB_SUCCESS)
4270           //          return MB_FAILURE;
4271 
4272           // Find if first node is coincident before testing the rest.
4273         bool first = false;
4274         for(i=0; i<num_nodes; i++)
4275         {
4276           if(points_are_coincident(coords1[i], coords2[0])) {
4277 	    /*	    cout <<"first("<<i<<",0) - ";
4278                         cout <<" coords1["<<i<<"] = ("
4279                         <<coords1[i][0]<<","
4280                         <<coords1[i][1]<<","
4281                         <<coords1[i][2]<<") ";
4282                         cout <<" coords2["<<0<<"] = ("
4283                         <<coords2[0][0]<<","
4284                         <<coords2[0][1]<<","
4285                         <<coords2[0][2]<<")\n";*/
4286             first = true;
4287             break;
4288           }
4289         }
4290           // TEST -- Find if second node is coincident before testing the rest.
4291         bool second = false;
4292         for(int t2=0; t2<num_nodes; t2++)
4293         {
4294           if(points_are_coincident(coords1[t2], coords2[1])) {
4295 	    /*	    cout <<"second("<<t2<<",1) - ";
4296                         cout <<" coords1["<<t2<<"] = ("
4297                         <<coords1[t2][0]<<","
4298                         <<coords1[t2][1]<<","
4299                         <<coords1[t2][2]<<") ";
4300                         cout <<" coords2["<<1<<"] = ("
4301                         <<coords2[1][0]<<","
4302                         <<coords2[1][1]<<","
4303                         <<coords2[1][2]<<")\n";*/
4304             second = true;
4305             break;
4306           }
4307         }
4308           // TEST -- Find if second node is coincident before testing the rest.
4309         bool third = false;
4310         for(int ti=0; ti<num_nodes; ti++)
4311         {
4312           if(points_are_coincident(coords1[ti], coords2[2])) {
4313 	    /*	    cout <<"third("<<ti<<",2) - ";
4314                         cout <<" coords1["<<ti<<"] = ("
4315                         <<coords1[ti][0]<<","
4316                         <<coords1[ti][1]<<","
4317                         <<coords1[ti][2]<<") ";
4318                         cout <<" coords2["<<1<<"] = ("
4319                         <<coords2[2][0]<<","
4320                         <<coords2[2][1]<<","
4321                         <<coords2[2][2]<<")\n";*/
4322             third = true;
4323             break;
4324           }
4325         }
4326         if ((first)&&(second)&&(third)) {
4327           cout <<"i = "<<i<<"\n";
4328           for (int tii = 0; tii < num_nodes; tii++) {
4329             cout <<" coords1["<<tii<<"] = ("
4330                  <<coords1[tii][0]<<","
4331                  <<coords1[tii][1]<<","
4332                  <<coords1[tii][2]<<") ";
4333             cout <<" coords2["<<tii<<"] = ("
4334                  <<coords2[tii][0]<<","
4335                  <<coords2[tii][1]<<","
4336                  <<coords2[tii][2]<<")\n";
4337           }
4338         }
4339 
4340         if(i < num_nodes)
4341         {
4342           for(ii=1; ii<num_nodes; ii++)
4343           {
4344             if(gMB->get_coords(&(conn[ii]), 1,  coords2[ii]) != MB_SUCCESS)
4345               return MB_FAILURE;
4346           }
4347 	  /*
4348               for(j=1; j<num_nodes; j++)
4349               {
4350 
4351               if(!points_are_coincident(coords1[j], coords2[(j+i)%num_nodes]))
4352               break;
4353               }
4354               if(j == num_nodes)*/
4355           if ((first)&&(second)&&(third))
4356           {
4357             coincident_pair.first  = *iter;
4358             coincident_pair.second = *jter;
4359             coin.push_back(coincident_pair);
4360           }
4361         }
4362       }
4363     }
4364   }
4365 
4366   return MB_SUCCESS;
4367 }
4368 
4369 #ifdef MOAB_HAVE_NETCDF
mb_merge_test()4370 ErrorCode mb_merge_test()
4371 {
4372   Core moab;
4373   Interface* MB = &moab;
4374 
4375   time_t begin_time = clock();
4376   unsigned int i;
4377   ErrorCode result;
4378   Skinner Skinner_Obj(MB);
4379 
4380   std::string test_files[] = {std::string("cell1.gen"),
4381                               std::string("cell2.gen")};
4382     /*  			      std::string("cell3.gen"),
4383     			      std::string("cell4.gen"),
4384 			      std::string("cell5.gen"),
4385 			      std::string("cell6.gen"),
4386 			      std::string("cell7.gen"),
4387 			      std::string("cell8.gen"),
4388 			      std::string("cell9.gen"),
4389 			      std::string("cell10.gen"),
4390 			      std::string("cell11.gen"),
4391 			      std::string("cell12.gen"),
4392 			      std::string("cell13.gen"),
4393 			      std::string("cell14.gen"),
4394 			      std::string("cell15.gen"),
4395 			      std::string("cell16.gen"),
4396 			      std::string("cell17.gen"),
4397 			      std::string("cell18.gen"),
4398 			      std::string("cell19.gen"),
4399 			      std::string("cell20.gen"),
4400 			      std::string("cell21.gen"),
4401 			      std::string("cell22.gen"),
4402 			      std::string("cell23.gen"),
4403 			      std::string("cell24.gen")};*/
4404 
4405     /*std::vector<Range> entities(sizeof(test_files));
4406       std::vector<Range> forward_lower(sizeof(test_files));
4407       std::vector<Range> reverse_lower(sizeof(test_files));
4408       std::vector<Range> nodes(sizeof(test_files));*/
4409   Range entities;
4410   Range forward_lower;
4411   Range reverse_lower;
4412   Range faces;
4413   Range nodes;
4414 
4415   cout << "---Starting Merge Tests---" << endl << endl;
4416   for(i=0; i<(sizeof(test_files)/sizeof(std::string)); i++)
4417   {
4418 
4419     cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
4420     result = MB->load_mesh(test_files[i].c_str(), NULL, 0);
4421     if (result == MB_SUCCESS)
4422       cout <<"Loaded "<<test_files[i]<<"\n";
4423       //get Hexes from model
4424   }
4425   result = MB->get_entities_by_type(0, MBHEX, entities);
4426   if (MB_SUCCESS != result)
4427     return result;
4428   Skinner_Obj.find_skin(0,entities,false,forward_lower,&reverse_lower);
4429   // cout <<"num hexes = "<<entities.size()<<"\n";
4430   // cout <<"fl = "<<forward_lower.size()<<" rl = "<<reverse_lower.size()<<"\n";
4431 
4432   //  Range::const_iterator iter;
4433   int dim = 0;
4434   //  int num_ents = 1;
4435   result = MB->get_adjacencies(forward_lower, dim, true, nodes, Interface::UNION);
4436   // cout <<"nodes.size() = "<<nodes.size() <<"\n";
4437 
4438   //  result = MB->get_entities_by_type(0, MBQUAD, faces);
4439   //  cout <<"num faces = "<<faces.size() <<"\n";
4440 
4441   std::vector<std::pair<EntityHandle, EntityHandle> > coin_nodes;
4442     //  cout <<"Begining sort...\n";
4443     //  std::sort(nodes.begin(),nodes.end(),lessnodesZ);
4444     //  cout <<"Ending sort...\n";
4445   result = find_coincident_nodes(MB,nodes, coin_nodes);
4446   cout <<"coin_nodes.size() = "<<coin_nodes.size() <<"\n";
4447   std::vector< std::pair<EntityHandle, EntityHandle> >::iterator n_iter;
4448   for (n_iter=coin_nodes.begin(); n_iter != coin_nodes.end(); ++n_iter) {
4449     result = MB->merge_entities((*n_iter).first, (*n_iter).second, false, true);
4450     if (MB_SUCCESS != result)
4451       return result;
4452   }
4453     /*  std::vector<std::pair<EntityHandle, EntityHandle> > coin_faces;
4454         int nodes_per_elt = 4;
4455         result = find_coincident_elements(forward_lower, nodes_per_elt, coin_faces);
4456         if (result != MB_SUCCESS) cout <<"find_coincident_elements fail!\n";
4457         cout <<"coin_faces.size() = "<<coin_faces.size() <<"\n";
4458         std::vector< std::pair<EntityHandle, EntityHandle> >::iterator f_iter;
4459         for (f_iter=coin_faces.begin(); f_iter != coin_faces.end(); ++f_iter)
4460         MB->merge_entities((*f_iter).first, (*f_iter).second, true, true);*/
4461     /*
4462       std::vector<std::pair<EntityHandle, EntityHandle> > coin_fl;
4463       nodes_per_elt = 4;
4464       result = find_coincident_elements(entities, nodes_per_elt, coin_fl);
4465       cout <<"coin_fl.size() = "<<coin_fl.size() <<"\n";
4466     */
4467   int num_ents;
4468   if ((MB_SUCCESS == MB->get_number_entities_by_dimension(0, 3, num_ents) &&
4469        0 != num_ents) ||
4470       (MB_SUCCESS == MB->get_number_entities_by_dimension(0, 2, num_ents) &&
4471        0 != num_ents))
4472     result = MB->write_mesh("merge_test.g");
4473   ;
4474 
4475 
4476   double clocks_per_sec = (double) CLOCKS_PER_SEC;
4477   double real_time =  difftime(time(NULL), begin_time);
4478   cout <<"TIME: "<<(real_time/clocks_per_sec)<<" seconds.\n";
4479   return result;
4480 }
4481 #endif
4482 
mb_merge_update_test()4483 ErrorCode mb_merge_update_test()
4484 {
4485   Core moab;
4486   Interface* mb = &moab;
4487   ErrorCode rval;
4488 
4489     // create two quads with a coincident edge pair
4490   double coords[] = { 0, 0, 0,
4491                       1, 0, 0,
4492                       1, 1, 0,
4493                       0, 1, 0,
4494                       1, 1, 0,
4495                       1, 0, 0,
4496                       2, 0, 0,
4497                       2, 1, 0 };
4498   EntityHandle verts[8];
4499   for (int i = 0; i < 8; ++i)
4500     mb->create_vertex( coords + 3*i, verts[i] );
4501   EntityHandle quad1, quad2, edge1, edge2;
4502   mb->create_element( MBQUAD, verts, 4, quad1 );
4503   mb->create_element( MBQUAD, verts+4, 4, quad2 );
4504   mb->create_element( MBEDGE, verts+1, 2, edge1 );
4505   mb->create_element( MBEDGE, verts+4, 2, edge2 );
4506 
4507     // create two tracking sets containing the vertices
4508     // and edge of each quad
4509   EntityHandle set1, set2;
4510   mb->create_meshset( MESHSET_TRACK_OWNER|MESHSET_SET, set1 );
4511   mb->create_meshset( MESHSET_TRACK_OWNER|MESHSET_ORDERED, set2 );
4512   mb->add_entities( set1, verts, 4 );
4513   mb->add_entities( set2, verts+4, 4 );
4514   mb->add_entities( set1, &edge1, 1 );
4515   mb->add_entities( set2, &edge2, 1 );
4516 
4517     // now merge the coincident edges
4518   rval = mb->merge_entities( verts[1], verts[5], false, true );
4519   if (MB_SUCCESS != rval) {
4520     std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
4521     return rval;
4522   }
4523   rval = mb->merge_entities( verts[2], verts[4], false, true );
4524   if (MB_SUCCESS != rval) {
4525     std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
4526     return rval;
4527   }
4528   rval = mb->merge_entities( edge1, edge2, false, true );
4529   if (MB_SUCCESS != rval) {
4530     std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
4531     return rval;
4532   }
4533 
4534     // check that there is only one edge and that it has the correct connectivity
4535   Range r;
4536   mb->get_entities_by_type( 0, MBEDGE, r );
4537   if (r.size() != 1 || r.front() != edge1) {
4538     std::cerr << "Edge merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
4539     return MB_FAILURE;
4540   }
4541   std::vector<EntityHandle> exp(verts+1, verts+3), act;
4542   mb->get_connectivity( &edge1, 1, act );
4543   if (exp != act) {
4544     std::cerr << "Incorrect conn for edge at " << __FILE__ << ":" << __LINE__ << std::endl;
4545     return MB_FAILURE;
4546   }
4547 
4548     // check that quad connectivity is as expected
4549   exp = std::vector<EntityHandle>(verts, verts+4);
4550   act.clear();
4551   mb->get_connectivity( &quad1, 1, act );
4552   if (exp != act) {
4553     std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
4554     return MB_FAILURE;
4555   }
4556   exp.resize(4);
4557   exp[0] = verts[2];
4558   exp[1] = verts[1];
4559   exp[2] = verts[6];
4560   exp[3] = verts[7];
4561   act.clear();
4562   mb->get_connectivity( &quad2, 1, act );
4563   if (exp != act) {
4564     std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
4565     return MB_FAILURE;
4566   }
4567 
4568     // check that set contents are correctly updated
4569   exp = std::vector<EntityHandle>(verts, verts+4);
4570   exp.push_back( edge1 );
4571   act.clear();
4572   mb->get_entities_by_handle( set1, act );
4573   std::sort( exp.begin(), exp.end() );
4574   std::sort( act.begin(), act.end() );
4575   if (exp != act) {
4576     std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
4577     std::cerr << "  Expected: ";
4578     std::copy( exp.begin(), exp.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
4579     std::cerr << std::endl << "  Actual  : ";
4580     std::copy( act.begin(), act.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
4581     std::cerr << std::endl;
4582     return MB_FAILURE;
4583   }
4584 
4585   exp.resize(5);
4586   exp[0] = verts[2];
4587   exp[1] = verts[1];
4588   exp[2] = verts[6];
4589   exp[3] = verts[7];
4590   exp[4] = edge1;
4591   act.clear();
4592   mb->get_entities_by_handle( set2, act );
4593   if (exp != act) {
4594     std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
4595     std::cerr << "  Expected: ";
4596     std::copy( exp.begin(), exp.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
4597     std::cerr << std::endl << "  Actual  : ";
4598     std::copy( act.begin(), act.end(), std::ostream_iterator<EntityHandle>(std::cerr, " ") );
4599     std::cerr << std::endl;
4600     return MB_FAILURE;
4601   }
4602 
4603   return MB_SUCCESS;
4604 }
4605 #ifdef MOAB_HAVE_NETCDF
mb_stress_test()4606 ErrorCode mb_stress_test()
4607 {
4608   ErrorCode error;
4609   Core moab;
4610   Interface* MB = &moab;
4611 
4612   cout << "    Beginning Stress Test . . ." << endl;
4613   cout << "\n        Reading elements" << endl;
4614   clock_t start = clock();
4615   clock_t total_start = clock();
4616 
4617     //read in a file so you have some data in the database
4618   std::string file_name = "mb_big_test.g";
4619   error = MB->load_mesh(file_name.c_str(), NULL, 0);
4620   if (error != MB_SUCCESS)
4621     return error;
4622 
4623   clock_t stop = clock();
4624 
4625   int num_entities_local;
4626   error = MB->get_number_entities_by_type(0, MBHEX, num_entities_local);
4627   if (error != MB_SUCCESS)
4628     return error;
4629 
4630   if (num_entities_local != 256000)
4631     return error;
4632 
4633   float time = static_cast<float>(stop - start)/CLOCKS_PER_SEC;
4634   float speed = num_entities_local/time;
4635   cout << "        Read " << num_entities_local << " entities"
4636        << " in "   << time << " seconds" << endl;
4637   cout << "        at " << speed << " elements per second." << endl;
4638 
4639 
4640   cout << "\n        Transforming and copying elements" << endl;
4641   start = clock();
4642 
4643   Range hexes;
4644   error = MB->get_entities_by_type(0, MBHEX, hexes);
4645   if (error != MB_SUCCESS)
4646     return error;
4647 
4648 
4649   std::vector<EntityHandle> conn;
4650   Range::iterator iter;
4651   for (iter = hexes.begin(); iter != hexes.end(); ++iter)
4652   {
4653     error = MB->get_connectivity(&(*iter), 1, conn);
4654     if (error != MB_SUCCESS)
4655       return error;
4656 
4657     double coords[3];
4658     int i = 0;
4659     std::vector<EntityHandle> vertex_handle(8);
4660     EntityHandle element_handle;
4661     std::vector<EntityHandle>::iterator jter;
4662 
4663     for (jter = conn.begin(); jter != conn.end(); ++jter)
4664     {
4665       error = MB->get_coords(&(*jter), 1, coords);
4666       if (error != MB_SUCCESS)
4667         return error;
4668       coords[2] += 20.0;
4669       error = MB->create_vertex(coords, vertex_handle[i++]);
4670       if (error != MB_SUCCESS)
4671         return error;
4672     }
4673     error = MB->create_element(MBHEX, &vertex_handle[0], 8, element_handle);
4674     if (error != MB_SUCCESS)
4675       return error;
4676   }
4677 
4678 
4679   stop = clock();
4680   time = static_cast<float>(stop - start)/CLOCKS_PER_SEC;
4681 
4682   cout << "        Transformed and created " << num_entities_local << " entities"
4683        << " in "   << time << " seconds" << endl;
4684 
4685     // Create mesh set
4686   cout << "\n        Creating meshset" << endl;
4687   start = clock();
4688   error = MB->get_entities_by_type(0, MBHEX, hexes);
4689   if (error != MB_SUCCESS)
4690     return error;
4691 
4692   if (hexes.size() != 512000)
4693     return MB_FAILURE;
4694 
4695   EntityHandle mesh_set;
4696   error = MB->create_meshset( MESHSET_SET, mesh_set );
4697   if (error != MB_SUCCESS)
4698     return error;
4699 
4700   error = MB->add_entities(mesh_set, hexes);
4701   if (error != MB_SUCCESS)
4702     return error;
4703 
4704   stop = clock();
4705   time = static_cast<float>(stop - start)/CLOCKS_PER_SEC;
4706 
4707   cout << "        Created meshset with " << hexes.size() << " entities"
4708        << " in "   << time << " seconds" << endl;
4709 
4710   cout << "\n        Writing 512K element file . . ." << endl;
4711   start = clock();
4712 
4713     // set the block tag
4714   Tag tag_handle;
4715   ErrorCode result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle ) ;
4716   if(result != MB_SUCCESS)
4717     return result;
4718 
4719   int id = 1;
4720   result = MB->tag_set_data( tag_handle, &mesh_set, 1, &id ) ;
4721   if(result != MB_SUCCESS)
4722     return result;
4723 
4724   std::vector<EntityHandle> output_list;
4725   output_list.push_back(mesh_set);
4726 
4727   file_name = "mb_stress_out.g";
4728   error = MB->write_mesh(file_name.c_str(), &output_list[0], output_list.size());
4729   if (error != MB_SUCCESS)
4730     return error;
4731 
4732   stop = clock();
4733   time = static_cast<float>(stop - start)/CLOCKS_PER_SEC;
4734 
4735   cout << "        Wrote file with " << hexes.size() << " entities"
4736        << " in "   << time << " seconds" << endl;
4737 
4738   clock_t total_stop = clock();
4739   time = static_cast<float>(total_stop - total_start)/CLOCKS_PER_SEC;
4740 
4741   cout << "        Total time: " << time << " seconds." << endl;
4742 
4743   MB->delete_mesh();
4744 
4745   return MB_SUCCESS;
4746 }
4747 #endif
4748 
mb_canon_number_test()4749 ErrorCode mb_canon_number_test()
4750 {
4751   Core moab;
4752   Interface* MB = &moab;
4753 
4754     // various tests for canonical ordering
4755 
4756     // CN::AdjacentSubEntities
4757   std::vector<int> vec1, vec2;
4758   ErrorCode result;
4759 
4760   EntityType this_type;
4761 
4762   for (this_type = MBEDGE; this_type != MBKNIFE; this_type++) {
4763 
4764     for (int i = 0; i < CN::VerticesPerEntity(this_type); i++) {
4765         // test for edges and faces
4766       for (int dim = 1; dim <= CN::Dimension(this_type); dim++) {
4767           // get the sides adjacent to this vertex
4768         vec1.clear();
4769         int temp_result = CN::AdjacentSubEntities(this_type, &i, 1, 0, dim, vec1);
4770 
4771         if (0 != temp_result ||
4772             vec1.size() > (unsigned int) CN::NumSubEntities(this_type, dim)) {
4773           cout << "failed getting sides for type " << CN::EntityTypeName(this_type)
4774                << " dimension" << dim << endl;
4775           return MB_FAILURE;
4776         }
4777 
4778 
4779           // now get the vertices shared by these sides
4780         vec2.clear();
4781         temp_result =
4782           CN::AdjacentSubEntities(this_type, &vec1[0], vec1.size(), dim, 0,
4783                                     vec2);
4784 
4785           // vertex side recovered should be i
4786         if (0 != temp_result ||
4787               // if dimension is same as DIMENSION(this_type), will get back all the
4788               // vertices in the entity
4789             (dim == CN::Dimension(this_type) &&
4790              vec2.size() != (unsigned int) CN::VerticesPerEntity(this_type)) ||
4791               // otherwise, we should get back only one vertex, and it should be the one
4792               // we started with
4793             (dim != CN::Dimension(this_type) &&
4794              (vec2.size() != 1 || vec2[0] != i))) {
4795           cout << "traversal from verts to sides to verts failed for " << endl
4796                << "vertex " << i << " type " << CN::EntityTypeName(this_type)
4797                << " dimension " << dim << endl;
4798           return MB_FAILURE;
4799         }
4800       }
4801     }
4802   }
4803 
4804     // CN::side_number
4805 
4806     // create vertices to use later
4807   double xyz[3] = {0.0, 0.0, 0.0};
4808   EntityHandle vertex_handles[8];
4809   for (int i = 0; i < 8; i++) {
4810     result = MB->create_vertex(xyz, vertex_handles[i]);
4811     assert(result == MB_SUCCESS);
4812   }
4813   int side, sense, offset;
4814 
4815   EntityHandle this_entity;
4816 
4817   for (this_type = MBEDGE; this_type != MBKNIFE; this_type++) {
4818 
4819       // skip remainder of the loop for MBPOLYGONS and POLYHEDRA, which don't follow
4820       // the standard canonical ordering
4821     if (this_type == MBPOLYGON || this_type == MBPOLYHEDRON)
4822       continue;
4823 
4824       // make an entity of this type
4825     result = MB->create_element(this_type, vertex_handles,
4826                                 CN::VerticesPerEntity(this_type),
4827                                 this_entity);
4828     if (MB_SUCCESS != result || 0 == this_entity) {
4829       cout << "failed to create entity of type "
4830            << CN::EntityTypeName(this_type) << endl;
4831       return MB_FAILURE;
4832     }
4833 
4834       // now get the connectivity vector *
4835     const EntityHandle *entity_vertices;
4836     int num_verts;
4837     result = MB->get_connectivity(this_entity, entity_vertices, num_verts);
4838     if (MB_SUCCESS != result ||
4839         num_verts != CN::VerticesPerEntity(this_type)) {
4840       cout << "failed to get connectivity for entity type "
4841            << CN::EntityTypeName(this_type) << endl;
4842       return MB_FAILURE;
4843     }
4844 
4845       // for each dimension
4846     for (int dim = 1; dim <= CN::Dimension(this_type); dim++) {
4847         // for each side of this dimension
4848       const CN::ConnMap &cm = CN::mConnectivityMap[this_type][dim-1];
4849       int tmp_conn[moab::MAX_SUB_ENTITY_VERTICES];
4850 
4851       for (int side_no = 0; side_no < CN::NumSubEntities(this_type, dim); side_no++) {
4852 
4853         for (int j = 0; j < moab::MAX_SUB_ENTITY_VERTICES; j++) tmp_conn[j] = cm.conn[side_no][j];
4854         int temp_result =
4855           CN::SideNumber(this_type,
4856                            tmp_conn,
4857                            CN::VerticesPerEntity(CN::SubEntityType(this_type, dim, side_no)),
4858                            dim, side, sense, offset);
4859         if (0 != temp_result) {
4860           cout << "call to CN::side_number failed with non-success result"
4861                << " for type "
4862                << CN::EntityTypeName(this_type) << " dimension " << dim
4863                << " side no " << side_no << endl;
4864           return MB_FAILURE;
4865         }
4866 
4867           // side number should be the same as side_no, sense should be forward, offset should
4868           // be zero
4869         if (side != side_no || sense != 1 || offset != 0) {
4870           cout << "call to CN::side_number failed for type "
4871                << CN::EntityTypeName(this_type) << " dimension " << dim << " side no "
4872                << side_no << endl
4873                << "side, sense, offset = " << side << " " << sense << " " << offset << endl;
4874           return MB_FAILURE;
4875         }
4876       }
4877     }
4878 
4879       // destroy the entity of this_type
4880     result = MB->delete_entities(&this_entity, 1);
4881     if (MB_SUCCESS != result)
4882       return result;
4883   }
4884 
4885   return MB_SUCCESS;
4886 }
mb_side_number_test()4887 ErrorCode mb_side_number_test()
4888 {
4889   ErrorCode rval;
4890   Core moab;
4891   Interface *mb = &moab;
4892 
4893     /* Create faces of a wedge: */
4894     /*
4895             4
4896            /|\
4897           / | \
4898          /  |  \
4899         /   2   \
4900        3.../.\...5
4901        |  /   \  |
4902        | /     \ |
4903        |/       \|      6 // off vertex
4904        0_________1
4905      */
4906 
4907   const double coords[][3] = { { 0, 0, 0 },
4908                                { 2, 0, 0 },
4909                                { 1, 0, 1 },
4910                                { 0, 2, 0 },
4911                                { 2, 2, 0 },
4912                                { 1, 2, 1 },
4913                                { 3, 1, 0 },
4914                                 };
4915   EntityHandle verts[7];
4916   for (unsigned i = 0; i < 7; ++i)
4917     mb->create_vertex( coords[i], verts[i] );
4918 
4919   EntityHandle faces[6];
4920   EntityHandle tri[] = { verts[0], verts[1], verts[2] };
4921   EntityHandle tri2[] = { verts[3], verts[4], verts[5] };
4922   EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
4923   EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
4924   EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
4925   rval = mb->create_element( MBTRI, tri, 3, faces[0] );MB_CHK_ERR(rval);
4926   rval = mb->create_element( MBQUAD, quad1, 4, faces[1] );MB_CHK_ERR(rval);
4927   rval = mb->create_element( MBQUAD, quad2, 4, faces[2] );MB_CHK_ERR(rval);
4928   rval = mb->create_element( MBQUAD, quad3, 4, faces[3] );MB_CHK_ERR(rval);
4929   rval = mb->create_element( MBTRI, tri2, 3, faces[4] );MB_CHK_ERR(rval);
4930 
4931   EntityHandle prism;
4932   rval = mb->create_element( MBPRISM, verts, 6, prism);MB_CHK_ERR(rval);
4933 
4934   /*
4935    * side_number(const EntityHandle parent,
4936                                   const EntityHandle child,
4937                                   int &side_number,
4938                                   int &sense,
4939                                   int &offset)
4940    */
4941   int side_n, sen, ofs;
4942   rval = mb->side_number(prism, faces[0], side_n, sen, ofs);MB_CHK_ERR(rval);
4943   CHECK_EQUAL(side_n, 3);
4944   CHECK_EQUAL(sen, -1);
4945   CHECK_EQUAL(ofs, 0);
4946 
4947   // this diagonal should not be on the prism (not an edge of the prism)
4948   EntityHandle diagonal1;
4949   EntityHandle diag[] = {  verts[2], verts[3] };
4950   rval = mb->create_element( MBEDGE, diag, 2, diagonal1);MB_CHK_ERR(rval);
4951   rval = mb->side_number(prism, diagonal1, side_n, sen, ofs);
4952   // expected fail
4953   if (rval != MB_FAILURE)
4954     return MB_FAILURE;
4955 
4956   // create another triangle, connected to the  prism, but not on the side
4957   EntityHandle tri3[] = { verts[3], verts[4], verts[6] };
4958   rval = mb->create_element( MBTRI, tri3, 3, faces[5] );MB_CHK_ERR(rval);
4959   rval = mb->side_number(prism, faces[5], side_n, sen, ofs);
4960   // expected fail
4961   if (rval != MB_FAILURE)
4962     return MB_FAILURE;
4963 
4964   return MB_SUCCESS;
4965 }
4966 
mb_poly_test()4967 ErrorCode mb_poly_test()
4968 {
4969   Core moab;
4970   Interface* mb = &moab;
4971 
4972     // test polygon and polyhedron representation
4973     // create a couple of polygons; vertices first
4974   const double vert_pos[48] = {
4975     -1, 0, 0,
4976     1, 0, 0,
4977     2, 0, 0,
4978     2, 1, 0,
4979     1, 1, 0,
4980     0, 2, 0,
4981     -1, 1, 0,
4982     -2, 1, 0,
4983     -2, 0, 0,
4984     -2, -1, 0,
4985     -1, -1, 0,
4986     -1, -2, 0,
4987     1, -2, 0,
4988     1, -1, 0,
4989     2, -1, 0,
4990     1.5, .5, 1};
4991 
4992   EntityHandle verts[16];
4993   ErrorCode result;
4994   int i;
4995   for (i = 0; i < 16; i++) {
4996     result = mb->create_vertex(&vert_pos[3*i], verts[i]);
4997     if (MB_SUCCESS != result) {
4998       std::cout << "Failed to create vertex " << i << " in mb_poly_test." << std::endl;
4999       return result;
5000     }
5001   }
5002 
5003     // then polygons
5004   const int connect_idx[] =
5005     {
5006       1, 2, 5, 6, 7,
5007       2, 3, 4, 5,
5008       5, 4, 6,
5009       7, 6, 8,
5010       0, 1, 7, 8,
5011       0, 1, 2, 3, 14, 13, 12, 11, 10, 9,
5012       0, 9, 10, 11, 12, 13, 14, 3, 4, 6, 8,
5013       2, 3, 15, 5,
5014       3, 4, 5, 15
5015     };
5016 
5017   int num_connect_idx[] = {5, 4, 3, 3, 4, 10, 11, 4, 4};
5018 
5019   EntityHandle polygons[9], temp_connect[12];
5020   int idx = 0, nump = 0;
5021   ErrorCode tmp_result;
5022   while (nump < 9) {
5023     for (i = 0; i < num_connect_idx[nump]; i++)
5024       temp_connect[i] = verts[connect_idx[idx+i]];
5025 
5026     tmp_result = mb->create_element(MBPOLYGON, temp_connect, num_connect_idx[nump],
5027                                     polygons[nump]);
5028     if (MB_SUCCESS != tmp_result) {
5029       std::cout << "mb_poly_test: create_element failed for polygon " << i << "." << std::endl;
5030       result = tmp_result;
5031       nump++;
5032       continue;
5033     }
5034 
5035     idx += num_connect_idx[nump];
5036     nump++;
5037   }
5038 
5039   if (MB_SUCCESS != result) return result;
5040 
5041     // ok, made 'em; now get all the vertices and make sure they're the same
5042   const EntityHandle *connect;
5043   int num_connect;
5044   idx = 0;
5045   int j;
5046   for (i = 0; i < 9; i++) {
5047     tmp_result = mb->get_connectivity(polygons[i], connect, num_connect);
5048     if (MB_SUCCESS != tmp_result || num_connect != num_connect_idx[i]) {
5049       std::cout << "mb_poly_test: get_connectivity test failed for polygon " << i << "." << std::endl;
5050       result = (tmp_result != MB_SUCCESS ? tmp_result : MB_FAILURE);
5051       continue;
5052     }
5053 
5054     for (j = 0; j < num_connect; j++) {
5055       if (connect[j] != verts[connect_idx[idx+j]]) {
5056         std::cout << "mb_poly_test: get_connectivity test returned wrong vertices for polygon "
5057                   << i << "." << std::endl;
5058         result = MB_FAILURE;
5059         continue;
5060       }
5061     }
5062 
5063     idx += num_connect;
5064   }
5065 
5066   if (MB_SUCCESS != result) return result;
5067 
5068     // check a different way, with ranges
5069   Range vert_range, poly_range;
5070   for (i = 0; i < 9; i++) poly_range.insert(polygons[i]);
5071   result = mb->get_adjacencies(poly_range, 0, false, vert_range,
5072                                Interface::UNION);
5073   if (MB_SUCCESS != result) {
5074     std::cout << "mb_poly_test: get_adjacencies failed for polygon "
5075               << i << "." << std::endl;
5076     return result;
5077   }
5078 
5079   else if (vert_range.size() != 16) {
5080     std::cout << "mb_poly_test: get_adjacencies returned wrong # of vertices for polygon "
5081               << i << "." << std::endl;
5082     return MB_FAILURE;
5083   }
5084 
5085     // make a couple polyhedra
5086   EntityHandle polyhedra[2];
5087   result = mb->create_element(MBPOLYHEDRON, polygons, 7, polyhedra[0]);
5088   if (MB_SUCCESS != result) {
5089     std::cout << "mb_poly_test: create_element failed for polyhedron 1." << std::endl;
5090     return result;
5091   }
5092 
5093   temp_connect[0] = polygons[1];
5094   temp_connect[1] = polygons[7];
5095   temp_connect[2] = polygons[8];
5096   result = mb->create_element(MBPOLYHEDRON, temp_connect, 3, polyhedra[1]);
5097   if (MB_SUCCESS != result) {
5098     std::cout << "mb_poly_test: create_element failed for polyhedron 2." << std::endl;
5099     return result;
5100   }
5101 
5102     // now look for vertices common to both
5103   std::vector<EntityHandle> temp_verts;
5104   result = mb->get_adjacencies(polyhedra, 2, 0, false, temp_verts);
5105   if (MB_SUCCESS != result) {
5106     std::cout << "mb_poly_test: get_adjacencies failed for polyhedra." << std::endl;
5107     return result;
5108   }
5109 
5110   if (4 != temp_verts.size()) {
5111     std::cout << "mb_poly_test: get_adjacencies for polyhedra returned " << temp_verts.size()
5112               << " vertices, should be 4." << std::endl;
5113     return MB_FAILURE;
5114   }
5115 
5116     // ok, we're probably fine
5117   return MB_SUCCESS;
5118 }
5119 
mb_topo_util_test()5120 ErrorCode mb_topo_util_test()
5121 {
5122   Core moab;
5123   Interface* gMB = &moab;
5124   MeshTopoUtil mtu(gMB);
5125 
5126     // construct a four-hex mesh for testing purposes
5127   double grid_vert_pos[] =
5128     {
5129       0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0,
5130       0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 2.0, 1.0, 0.0,
5131       0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
5132 //
5133       0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 2.0, 0.0, 1.0,
5134       0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0,
5135       0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0
5136     };
5137 
5138   EntityHandle grid_verts[18], grid_elems[4];
5139   ErrorCode result;
5140 #define RR if (result != MB_SUCCESS) return result
5141   int init_edges, init_faces;
5142   result = gMB->get_number_entities_by_dimension(0, 1, init_edges); RR;
5143   result = gMB->get_number_entities_by_dimension(0, 2, init_faces); RR;
5144 
5145     // make vertices
5146   for (int i = 0; i < 18; i++) {
5147     result = gMB->create_vertex(&grid_vert_pos[3*i], grid_verts[i]); RR;
5148   }
5149 
5150     // make hexes
5151   int numv = 3, numv_sq = 9;
5152 #define VINDEX(i,j,k) (i + (j*numv) + (k*numv_sq))
5153   EntityHandle connect[8];
5154   for (int j = 0; j < 2; j++) {
5155     for (int i = 0; i < 2; i++) {
5156       int vijk = VINDEX(i,j,0);
5157       connect[0] = grid_verts[vijk];
5158       connect[1] = grid_verts[vijk+1];
5159       connect[2] = grid_verts[vijk+1+numv];
5160       connect[3] = grid_verts[vijk+numv];
5161       connect[4] = grid_verts[vijk+numv*numv];
5162       connect[5] = grid_verts[vijk+1+numv*numv];
5163       connect[6] = grid_verts[vijk+1+numv+numv*numv];
5164       connect[7] = grid_verts[vijk+numv+numv*numv];
5165       result = gMB->create_element(MBHEX, connect, 8, grid_elems[2*j+i]); RR;
5166     }
5167   }
5168 
5169   Range vert_range;
5170   std::copy(grid_verts, grid_verts+18, range_inserter(vert_range));
5171 
5172     // generate aentities
5173   result = mtu.construct_aentities(vert_range); RR;
5174 
5175   int this_edges, this_faces;
5176   result = gMB->get_number_entities_by_dimension(0, 1, this_edges); RR;
5177   result = gMB->get_number_entities_by_dimension(0, 2, this_faces); RR;
5178 
5179   if (this_edges != init_edges+33 || this_faces != init_faces+20) {
5180     std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
5181 //    return MB_FAILURE;
5182   }
5183 
5184     // get average position
5185   double pos[3];
5186   for (int j = 0; j < 2; j++) {
5187     for (int i = 0; i < 2; i++) {
5188       result = mtu.get_average_position(grid_elems[2*j+i], pos);
5189       RR;
5190       if (pos[0] != .5+i || pos[1] != .5+j || pos[2] != .5) {
5191         std::cout << "Wrong position at i = " << i << ", j = " << j << std::endl;
5192         result = MB_FAILURE;
5193       }
5194     }
5195   }
5196   RR;
5197 
5198     // get star faces
5199   Range all_hexes, middle_edge;
5200   std::copy(grid_elems, grid_elems+4, range_inserter(all_hexes));
5201     // get the shared edge
5202   result = gMB->get_adjacencies(all_hexes, 1, false, middle_edge);
5203   if (MB_SUCCESS != result || 1 != middle_edge.size()) {
5204     std::cout << "Bad result getting single shared edge." << std::endl;
5205     return MB_FAILURE;
5206   }
5207 
5208   std::vector<EntityHandle> star_faces, star_hexes;
5209   bool bdy_edge;
5210   result = mtu.star_entities(*middle_edge.begin(), star_faces, bdy_edge, 0, &star_hexes);
5211   if (MB_SUCCESS != result || bdy_edge || star_faces.size() != 4 || star_hexes.size() != 4) {
5212     std::cout << "Bad result from star_faces for non-bdy edge." << std::endl;
5213     return MB_FAILURE;
5214   }
5215 
5216     // now try for a different edge, which has to be on the bdy
5217   Range other_edges;
5218   all_hexes.clear(); all_hexes.insert(grid_elems[0]);
5219   result = gMB->get_adjacencies(all_hexes, 1, false, other_edges); RR;
5220   other_edges.erase(*middle_edge.begin());
5221   if (11 != other_edges.size()) {
5222     std::cout << "Wrong number of edges in hex." << std::endl;
5223     return MB_FAILURE;
5224   }
5225   star_faces.clear();
5226   star_hexes.clear();
5227   result = mtu.star_entities(*other_edges.begin(), star_faces, bdy_edge, 0, &star_hexes);
5228   if (MB_SUCCESS != result || !bdy_edge ||
5229       (star_faces.size() != 2 && star_faces.size() != 3) ||
5230       (star_hexes.size() != 1 && star_hexes.size() != 2)) {
5231     std::cout << "Bad result from star_faces for bdy edge." << std::endl;
5232     return MB_FAILURE;
5233   }
5234 
5235   return MB_SUCCESS;
5236 }
5237 
mb_split_test()5238 ErrorCode mb_split_test()
5239 {
5240   Core moab;
5241   Interface* gMB = &moab;
5242   MeshTopoUtil mtu(gMB);
5243 
5244     // construct a four-hex mesh for testing purposes
5245   double grid_vert_pos[] =
5246     {
5247       0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0,
5248       0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 2.0, 1.0, 0.0,
5249       0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
5250 //
5251       0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 2.0, 0.0, 1.0,
5252       0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0,
5253       0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0,
5254 //
5255       0.0, 0.0, 2.0, 1.0, 0.0, 2.0, 2.0, 0.0, 2.0,
5256       0.0, 1.0, 2.0, 1.0, 1.0, 2.0, 2.0, 1.0, 2.0,
5257       0.0, 2.0, 2.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0
5258     };
5259 
5260   EntityHandle grid_verts[27], grid_elems[8];
5261   ErrorCode result;
5262 #define RR if (result != MB_SUCCESS) return result
5263   int init_edges, init_faces, init_regions;
5264   result = gMB->get_number_entities_by_dimension(0, 1, init_edges); RR;
5265   result = gMB->get_number_entities_by_dimension(0, 2, init_faces); RR;
5266   result = gMB->get_number_entities_by_dimension(0, 3, init_regions); RR;
5267 
5268     // make vertices
5269   for (int i = 0; i < 27; i++) {
5270     result = gMB->create_vertex(&grid_vert_pos[3*i], grid_verts[i]); RR;
5271   }
5272 
5273     // make hexes
5274   int numv = 3, numv_sq = 9;
5275 #define VINDEX(i,j,k) (i + (j*numv) + (k*numv_sq))
5276   EntityHandle connect[8];
5277   for (int k = 0; k < 2; k++) {
5278     for (int j = 0; j < 2; j++) {
5279       for (int i = 0; i < 2; i++) {
5280         int vijk = VINDEX(i,j,k);
5281         connect[0] = grid_verts[vijk];
5282         connect[1] = grid_verts[vijk+1];
5283         connect[2] = grid_verts[vijk+1+numv];
5284         connect[3] = grid_verts[vijk+numv];
5285         connect[4] = grid_verts[vijk+numv*numv];
5286         connect[5] = grid_verts[vijk+1+numv*numv];
5287         connect[6] = grid_verts[vijk+1+numv+numv*numv];
5288         connect[7] = grid_verts[vijk+numv+numv*numv];
5289         result = gMB->create_element(MBHEX, connect, 8, grid_elems[4*k+2*j+i]); RR;
5290       }
5291     }
5292   }
5293 
5294   Range vert_range;
5295   std::copy(grid_verts, grid_verts+27, range_inserter(vert_range));
5296 
5297     // generate aentities
5298   result = mtu.construct_aentities(vert_range); RR;
5299 
5300   int this_edges, this_faces;
5301   result = gMB->get_number_entities_by_dimension(0, 1, this_edges); RR;
5302   result = gMB->get_number_entities_by_dimension(0, 2, this_faces); RR;
5303 
5304   if (this_edges != init_edges+54 || this_faces != init_faces+36) {
5305     std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
5306     return MB_FAILURE;
5307   }
5308 
5309     // split the faces between the 2 layers
5310     // first get the faces
5311   Range split_faces, tmp_ents, tmp_faces;
5312   for (int i = 0; i < 4; i++) {
5313     tmp_ents.clear();
5314     tmp_ents.insert(grid_elems[i]);
5315     tmp_ents.insert(grid_elems[i+4]);
5316     tmp_faces.clear();
5317     result = gMB->get_adjacencies(tmp_ents, 2, false, tmp_faces);
5318     if (MB_SUCCESS != result || tmp_faces.size() != 1) {
5319       std::cout << "mb_split_test failed to get shared quad." << std::endl;
5320       return MB_FAILURE;
5321     }
5322     split_faces.insert(*tmp_faces.begin());
5323   }
5324 
5325   Range new_faces, new_regions;
5326 
5327     // NOTE: passing in non-NULL pointer for new_regions requests that region between the
5328     // split entities be filled with an element; in this case, since we're splitting faces,
5329     // the new entities are polyhedra
5330   result = mtu.split_entities_manifold(split_faces, new_faces, &new_regions);
5331   if (MB_SUCCESS != result || new_faces.size() != 4 ||
5332       new_regions.size() != 4) {
5333     std::cout << "mb_split_test failed to split quads." << std::endl;
5334     return MB_FAILURE;
5335   }
5336 
5337   int this_regions;
5338   result = gMB->get_number_entities_by_dimension(0, 1, this_edges); RR;
5339   result = gMB->get_number_entities_by_dimension(0, 2, this_faces); RR;
5340   result = gMB->get_number_entities_by_dimension(0, 3, this_regions); RR;
5341 
5342   if (this_edges != init_edges+54 || this_faces != init_faces+40 ||
5343       this_regions != init_regions+12) {
5344     std::cout << "Wrong number of edges or faces or regions after splitting in mb_topo_util test."
5345               << std::endl;
5346     return MB_FAILURE;
5347   }
5348 
5349   return MB_SUCCESS;
5350 }
5351 
mb_range_seq_intersect_test()5352 ErrorCode mb_range_seq_intersect_test()
5353 {
5354   ErrorCode rval;
5355   SequenceManager sequences;
5356   RangeSeqIntersectIter iter( &sequences );
5357   Range range;
5358 
5359     // create some entity sequences
5360   EntitySequence *ts1, *ts2, *ts3, *qs1;
5361   EntityHandle th1, th2, th3, qh1;
5362   const int nt1 = 100, nt2 = 10, nt3 = 1, nq1 = 20;
5363   rval = sequences.create_entity_sequence( MBTRI, nt1, 3, 5, th1, ts1, -1 );
5364   if (MB_SUCCESS != rval) return rval;
5365   rval = sequences.create_entity_sequence( MBTRI, nt2, 6, 0, th2, ts2, -1 );
5366   if (MB_SUCCESS != rval) return rval;
5367   rval = sequences.create_entity_sequence( MBTRI, nt3, 3, MB_END_ID, th3, ts3, -1 );
5368   if (MB_SUCCESS != rval) return rval;
5369   rval = sequences.create_entity_sequence( MBQUAD, nq1, 4, 0, qh1, qs1, -1 );
5370   if (MB_SUCCESS != rval) return rval;
5371 
5372     // we're going to assume this below, so verify it now
5373   if (th1 > th2 || th2 > th3 || th3 > qh1)
5374     return MB_FAILURE;
5375 
5376     // construct an Range containing all valid handles;
5377   range.clear();
5378   range.insert( ts1->start_handle(), ts1->end_handle() );
5379   range.insert( ts2->start_handle(), ts2->end_handle() );
5380   range.insert( ts3->start_handle(), ts3->end_handle() );
5381   range.insert( qs1->start_handle(), qs1->end_handle() );
5382 
5383     // iterate over all and check results
5384 
5385   rval = iter.init( range.begin(), range.end() );
5386   if (MB_SUCCESS != rval)
5387     return rval;
5388   if (ts1 != iter.get_sequence())
5389     return MB_FAILURE;
5390   if (iter.get_start_handle() != ts1->start_handle())
5391     return MB_FAILURE;
5392   if (iter.get_end_handle() != ts1->end_handle())
5393     return MB_FAILURE;
5394 
5395   rval = iter.step();
5396   if (MB_SUCCESS != rval)
5397     return rval;
5398   if (ts2 != iter.get_sequence())
5399     return MB_FAILURE;
5400   if (iter.get_start_handle() != ts2->start_handle())
5401     return MB_FAILURE;
5402   if (iter.get_end_handle() != ts2->end_handle())
5403     return MB_FAILURE;
5404 
5405   rval = iter.step();
5406   if (MB_SUCCESS != rval)
5407     return rval;
5408   if (ts3 != iter.get_sequence())
5409     return MB_FAILURE;
5410   if (iter.get_start_handle() != ts3->start_handle())
5411     return MB_FAILURE;
5412   if (iter.get_end_handle() != ts3->end_handle())
5413     return MB_FAILURE;
5414 
5415   rval = iter.step();
5416   if (MB_SUCCESS != rval)
5417     return rval;
5418   if (qs1 != iter.get_sequence())
5419     return MB_FAILURE;
5420   if (iter.get_start_handle() != qs1->start_handle())
5421     return MB_FAILURE;
5422   if (iter.get_end_handle() != qs1->end_handle())
5423     return MB_FAILURE;
5424 
5425   if (!iter.is_at_end())
5426     return MB_FAILURE;
5427   rval = iter.step();
5428   if (MB_FAILURE != rval)
5429     return MB_FAILURE;
5430 
5431     // iterate over just the quads
5432 
5433   rval = iter.init( range.lower_bound(MBQUAD), range.end() );
5434   if (MB_SUCCESS != rval)
5435     return rval;
5436   if (qs1 != iter.get_sequence())
5437     return MB_FAILURE;
5438   if (iter.get_start_handle() != qs1->start_handle())
5439     return MB_FAILURE;
5440   if (iter.get_end_handle() != qs1->end_handle())
5441     return MB_FAILURE;
5442 
5443   if (!iter.is_at_end())
5444     return MB_FAILURE;
5445   rval = iter.step();
5446   if (MB_FAILURE != rval)
5447     return MB_FAILURE;
5448 
5449     // iterate starting one past the beginning of the
5450     // triangles and stopping one before the end.  The last
5451     // sequence contains only one tri, so should stop and end
5452     // of second-to-last sequence
5453 
5454   rval = iter.init( ++(range.begin()), --(range.lower_bound(MBQUAD)) );
5455   if (MB_SUCCESS != rval)
5456     return rval;
5457   if (ts1 != iter.get_sequence())
5458     return MB_FAILURE;
5459   if (iter.get_start_handle() != ts1->start_handle() + 1)
5460     return MB_FAILURE;
5461   if (iter.get_end_handle() != ts1->end_handle())
5462     return MB_FAILURE;
5463 
5464   rval = iter.step();
5465   if (MB_SUCCESS != rval)
5466     return rval;
5467   if (ts2 != iter.get_sequence())
5468     return MB_FAILURE;
5469   if (iter.get_start_handle() != ts2->start_handle())
5470     return MB_FAILURE;
5471   if (iter.get_end_handle() != ts2->end_handle())
5472     return MB_FAILURE;
5473 
5474   if (!iter.is_at_end())
5475     return MB_FAILURE;
5476   rval = iter.step();
5477   if (MB_FAILURE != rval)
5478     return MB_FAILURE;
5479 
5480     // Iterate over the quad sequence, starting two past the
5481     // beginning and stopping one before the end
5482 
5483   rval = iter.init( ++(range.lower_bound(MBQUAD)), --(range.end()));
5484   if (MB_SUCCESS != rval)
5485     return rval;
5486   if (qs1 != iter.get_sequence())
5487     return MB_FAILURE;
5488   if (iter.get_start_handle() != qs1->start_handle() + 1)
5489     return MB_FAILURE;
5490   if (iter.get_end_handle() != qs1->end_handle() - 1)
5491     return MB_FAILURE;
5492 
5493   if (!iter.is_at_end())
5494     return MB_FAILURE;
5495   rval = iter.step();
5496   if (MB_FAILURE != rval)
5497     return MB_FAILURE;
5498 
5499     // Iterate over two subsets of the quad sequence
5500 
5501   Range quads = range.subset_by_type( MBQUAD );
5502   EntityHandle removed = qs1->start_handle() + nq1/2;
5503   if (quads.erase( removed ) == quads.end())
5504     return MB_FAILURE;
5505 
5506   rval = iter.init( quads.begin(), quads.end());
5507   if (MB_SUCCESS != rval)
5508     return rval;
5509   if (qs1 != iter.get_sequence())
5510     return MB_FAILURE;
5511   if (iter.get_start_handle() != qs1->start_handle())
5512     return MB_FAILURE;
5513   if (iter.get_end_handle() != removed - 1)
5514     return MB_FAILURE;
5515 
5516   rval = iter.step();
5517   if (MB_SUCCESS != rval)
5518     return rval;
5519   if (qs1 != iter.get_sequence())
5520     return MB_FAILURE;
5521   if (iter.get_start_handle() != removed + 1)
5522     return MB_FAILURE;
5523   if (iter.get_end_handle() != qs1->end_handle())
5524     return MB_FAILURE;
5525 
5526   if (!iter.is_at_end())
5527     return MB_FAILURE;
5528   rval = iter.step();
5529   if (MB_FAILURE != rval)
5530     return MB_FAILURE;
5531 
5532     // Iterate over everything, including a bunch of
5533     // invalid handles
5534 
5535   Range big;
5536   int junk;
5537   EntityHandle last = CREATE_HANDLE(MBQUAD+1, 0, junk);
5538   big.insert( ts1->start_handle() - 1, last );
5539 
5540     // first some invalid handles in the beginning of the range
5541   rval = iter.init( big.begin(), big.end() );
5542   if (MB_ENTITY_NOT_FOUND != rval)
5543     return MB_FAILURE;
5544   if (NULL != iter.get_sequence())
5545     return MB_FAILURE;
5546   if (iter.get_start_handle() != *big.begin())
5547     return MB_FAILURE;
5548   if (iter.get_end_handle() != ts1->start_handle() - 1)
5549     return MB_FAILURE;
5550 
5551     // next the first triangle sequence
5552   rval = iter.step();
5553   if (MB_SUCCESS != rval)
5554     return rval;
5555   if (ts1 != iter.get_sequence())
5556     return MB_FAILURE;
5557   if (iter.get_start_handle() != ts1->start_handle())
5558     return MB_FAILURE;
5559   if (iter.get_end_handle() != ts1->end_handle())
5560     return MB_FAILURE;
5561 
5562     // next the the invalid handles between the first two tri sequences
5563   if (ts1->end_handle() + 1 != ts2->start_handle()) {
5564     rval = iter.step();
5565     if (MB_ENTITY_NOT_FOUND != rval)
5566       return MB_FAILURE;
5567     if (NULL != iter.get_sequence())
5568       return MB_FAILURE;
5569     if (iter.get_start_handle() != ts1->end_handle()+1)
5570       return MB_FAILURE;
5571     if (iter.get_end_handle() != ts2->start_handle()-1)
5572       return MB_FAILURE;
5573   }
5574 
5575     // next the second triangle sequence
5576   rval = iter.step();
5577   if (MB_SUCCESS != rval)
5578     return rval;
5579   if (ts2 != iter.get_sequence())
5580     return MB_FAILURE;
5581   if (iter.get_start_handle() != ts2->start_handle())
5582     return MB_FAILURE;
5583   if (iter.get_end_handle() != ts2->end_handle())
5584     return MB_FAILURE;
5585 
5586     // next the the invalid handles between the 2nd and 3rd tri sequences
5587   if (ts2->end_handle() + 1 != ts3->start_handle()) {
5588     rval = iter.step();
5589     if (MB_ENTITY_NOT_FOUND != rval)
5590       return MB_FAILURE;
5591     if (NULL != iter.get_sequence())
5592       return MB_FAILURE;
5593     if (iter.get_start_handle() != ts2->end_handle()+1)
5594       return MB_FAILURE;
5595     if (iter.get_end_handle() != ts3->start_handle()-1)
5596       return MB_FAILURE;
5597   }
5598 
5599     // next the third triangle sequence
5600   rval = iter.step();
5601   if (MB_SUCCESS != rval)
5602     return rval;
5603   if (ts3 != iter.get_sequence())
5604     return MB_FAILURE;
5605   if (iter.get_start_handle() != ts3->start_handle())
5606     return MB_FAILURE;
5607   if (iter.get_end_handle() != ts3->end_handle())
5608     return MB_FAILURE;
5609 
5610     // third tri sequence contains the MAX tri handle, so no more
5611     // invalid triangles.
5612     // next 1 invalid quad at the before MB_START_ID
5613   if (ts3->end_handle() + 1 != qs1->start_handle()) {
5614     rval = iter.step();
5615     if (MB_ENTITY_NOT_FOUND != rval)
5616       return MB_FAILURE;
5617     if (NULL != iter.get_sequence())
5618       return MB_FAILURE;
5619     if (iter.get_start_handle() != ts3->end_handle()+1)
5620       return MB_FAILURE;
5621     if (iter.get_end_handle() != qs1->start_handle()-1)
5622       return MB_FAILURE;
5623   }
5624 
5625     // next the quad sequence
5626   rval = iter.step();
5627   if (MB_SUCCESS != rval)
5628     return rval;
5629   if (qs1 != iter.get_sequence())
5630     return MB_FAILURE;
5631   if (iter.get_start_handle() != qs1->start_handle())
5632     return MB_FAILURE;
5633   if (iter.get_end_handle() != qs1->end_handle())
5634     return MB_FAILURE;
5635 
5636     // next remaining invalid quad handles in the range
5637   rval = iter.step();
5638   if (MB_ENTITY_NOT_FOUND != rval)
5639     return MB_FAILURE;
5640   if (0 != iter.get_sequence())
5641     return MB_FAILURE;
5642   if (iter.get_start_handle() != qs1->end_handle() + 1)
5643     return MB_FAILURE;
5644   if (iter.get_end_handle() != last - 1)
5645     return MB_FAILURE;
5646 
5647     // next invalid entity after the last quad in the range
5648   rval = iter.step();
5649   if (MB_ENTITY_NOT_FOUND != rval)
5650     return MB_FAILURE;
5651   if (0 != iter.get_sequence())
5652     return MB_FAILURE;
5653   if (iter.get_start_handle() != last)
5654     return MB_FAILURE;
5655   if (iter.get_end_handle() != last)
5656     return MB_FAILURE;
5657 
5658     // now at the end
5659   if (!iter.is_at_end())
5660     return MB_FAILURE;
5661   rval = iter.step();
5662   if (MB_FAILURE != rval)
5663     return MB_FAILURE;
5664 
5665 
5666 
5667     // Create some holes
5668   Error eh;
5669   EntityHandle ts1s  = ts1->start_handle();
5670   EntityHandle dead1 = ts1->start_handle() + 1;
5671   EntityHandle dead2 = ts1->start_handle() + 2;
5672   EntityHandle ts1e  = ts1->end_handle();
5673   EntityHandle dead3 = ts2->start_handle();
5674   EntityHandle dead4 = ts2->end_handle();
5675   EntityHandle qs1s  = qs1->start_handle();
5676   EntityHandle qs1e  = qs1->end_handle();
5677   EntityHandle dead5 = qs1->start_handle() + nq1/2;
5678   EntityHandle dead6 = dead5+1;
5679   rval = sequences.delete_entity( &eh, dead1 );
5680   if (MB_SUCCESS != rval) return rval;
5681   rval = sequences.delete_entity( &eh, dead2 );
5682   if (MB_SUCCESS != rval) return rval;
5683   rval = sequences.delete_entity( &eh, dead3 );
5684   if (MB_SUCCESS != rval) return rval;
5685   rval = sequences.delete_entity( &eh, dead4 );
5686   if (MB_SUCCESS != rval) return rval;
5687   rval = sequences.delete_entity( &eh, dead5 );
5688   if (MB_SUCCESS != rval) return rval;
5689   rval = sequences.delete_entity( &eh, dead6 );
5690   if (MB_SUCCESS != rval) return rval;
5691 
5692     // Iterate over sequences w/out removing deleted entities
5693     // from range.
5694 
5695     // first sequence should have one valid handle at beginning
5696   rval = iter.init( range.begin(), range.end() );
5697   if (MB_SUCCESS != rval)
5698     return rval;
5699   if (0 == iter.get_sequence() ||
5700       ts1s != iter.get_sequence()->start_handle() ||
5701       dead1-1 != iter.get_sequence()->end_handle())
5702     return MB_FAILURE;
5703   if (iter.get_start_handle() != ts1->start_handle())
5704     return MB_FAILURE;
5705   if (iter.get_end_handle() != dead1 - 1)
5706     return MB_FAILURE;
5707 
5708     // next two invalid handles in sequence in first sequence
5709   rval = iter.step( );
5710   if (MB_ENTITY_NOT_FOUND != rval)
5711     return MB_FAILURE;
5712   if (0 != iter.get_sequence())
5713     return MB_FAILURE;
5714   if (iter.get_start_handle() != dead1)
5715     return MB_FAILURE;
5716   if (iter.get_end_handle() != dead2)
5717     return MB_FAILURE;
5718 
5719     // next the remainder of the fist sequence
5720   rval = iter.step();
5721   if (MB_SUCCESS != rval)
5722     return rval;
5723   if (0 == iter.get_sequence() ||
5724       dead2+1 != iter.get_sequence()->start_handle() ||
5725       ts1e != iter.get_sequence()->end_handle())
5726     return MB_FAILURE;
5727   if (iter.get_start_handle() != dead2+1)
5728     return MB_FAILURE;
5729   if (iter.get_end_handle() != ts1e)
5730     return MB_FAILURE;
5731 
5732     // next an invalid handle at the start of the second sequence
5733   rval = iter.step();
5734   if (MB_ENTITY_NOT_FOUND != rval)
5735     return MB_FAILURE;
5736   if (0 != iter.get_sequence())
5737     return MB_FAILURE;
5738   if (iter.get_start_handle() != dead3)
5739     return MB_FAILURE;
5740   if (iter.get_end_handle() != dead3)
5741     return MB_FAILURE;
5742 
5743     // next the second sequence up to the invalid handle at the end
5744   rval = iter.step();
5745   if (MB_SUCCESS != rval)
5746     return rval;
5747   if (0 == iter.get_sequence() ||
5748       dead3+1 != iter.get_sequence()->start_handle() ||
5749       dead4-1 != iter.get_sequence()->end_handle())
5750     return MB_FAILURE;
5751   if (ts2 != iter.get_sequence())
5752     return MB_FAILURE;
5753   if (iter.get_start_handle() != dead3+1)
5754     return MB_FAILURE;
5755   if (iter.get_end_handle() != dead4-1)
5756     return MB_FAILURE;
5757 
5758     // next invaild handle at the end of the second sequence
5759   rval = iter.step();
5760   if (MB_ENTITY_NOT_FOUND != rval)
5761     return MB_FAILURE;
5762   if (0 != iter.get_sequence())
5763     return MB_FAILURE;
5764   if (iter.get_start_handle() != dead4)
5765     return MB_FAILURE;
5766   if (iter.get_end_handle() != dead4)
5767     return MB_FAILURE;
5768 
5769     // next the third sequence
5770   rval = iter.step();
5771   if (MB_SUCCESS != rval)
5772     return rval;
5773   if (ts3 != iter.get_sequence())
5774     return MB_FAILURE;
5775   if (iter.get_start_handle() != ts3->start_handle())
5776     return MB_FAILURE;
5777   if (iter.get_end_handle() != ts3->end_handle())
5778     return MB_FAILURE;
5779 
5780     // next the quad sequence up to the invalid handle in the middle
5781   rval = iter.step();
5782   if (MB_SUCCESS != rval)
5783     return rval;
5784   if (0 == iter.get_sequence() ||
5785       qs1s != iter.get_sequence()->start_handle() ||
5786       dead5-1 != iter.get_sequence()->end_handle())
5787     return MB_FAILURE;
5788   if (qs1 != iter.get_sequence())
5789     return MB_FAILURE;
5790   if (iter.get_start_handle() != qs1s)
5791     return MB_FAILURE;
5792   if (iter.get_end_handle() != dead5-1)
5793     return MB_FAILURE;
5794 
5795     // next the two invalid handles in the middle
5796   rval = iter.step();
5797   if (MB_ENTITY_NOT_FOUND != rval)
5798     return MB_FAILURE;
5799   if (0 != iter.get_sequence())
5800     return MB_FAILURE;
5801   if (iter.get_start_handle() != dead5)
5802     return MB_FAILURE;
5803   if (iter.get_end_handle() != dead6)
5804     return MB_FAILURE;
5805 
5806     // next the remainder of the quad sequence
5807   rval = iter.step();
5808   if (MB_SUCCESS != rval)
5809     return rval;
5810   if (0 == iter.get_sequence() ||
5811       dead6+1 != iter.get_sequence()->start_handle() ||
5812       qs1e != iter.get_sequence()->end_handle())
5813     return MB_FAILURE;
5814   if (iter.get_start_handle() != dead6+1)
5815     return MB_FAILURE;
5816   if (iter.get_end_handle() != qs1e)
5817     return MB_FAILURE;
5818 
5819     // now at the end
5820   if (!iter.is_at_end())
5821     return MB_FAILURE;
5822   rval = iter.step();
5823   if (MB_FAILURE != rval)
5824     return MB_FAILURE;
5825 
5826 
5827     // now remove the dead entities from the range and iterate again
5828 
5829   if (range.erase( dead1 ) == quads.end())
5830     return MB_FAILURE;
5831   if (range.erase( dead2 ) == quads.end())
5832     return MB_FAILURE;
5833   if (range.erase( dead3 ) == quads.end())
5834     return MB_FAILURE;
5835   if (range.erase( dead4 ) == quads.end())
5836     return MB_FAILURE;
5837   if (range.erase( dead5 ) == quads.end())
5838     return MB_FAILURE;
5839   if (range.erase( dead6 ) == quads.end())
5840     return MB_FAILURE;
5841 
5842 
5843     // first sequence should have one valid handle at beginning
5844   rval = iter.init( range.begin(), range.end() );
5845   if (MB_SUCCESS != rval)
5846     return rval;
5847   if (0 == iter.get_sequence() ||
5848       ts1s != iter.get_sequence()->start_handle() ||
5849       dead1-1 != iter.get_sequence()->end_handle())
5850     return MB_FAILURE;
5851   if (iter.get_start_handle() != ts1s)
5852     return MB_FAILURE;
5853   if (iter.get_end_handle() != dead1 - 1)
5854     return MB_FAILURE;
5855 
5856     // next the remainder of the fist sequence after the hole
5857   rval = iter.step();
5858   if (MB_SUCCESS != rval)
5859     return rval;
5860   if (0 == iter.get_sequence() ||
5861       dead2+1 != iter.get_sequence()->start_handle() ||
5862       ts1e != iter.get_sequence()->end_handle())
5863     return MB_FAILURE;
5864   if (iter.get_start_handle() != dead2+1)
5865     return MB_FAILURE;
5866   if (iter.get_end_handle() != ts1e)
5867     return MB_FAILURE;
5868 
5869     // next the second sequence between deleted start and end handles
5870   rval = iter.step();
5871   if (MB_SUCCESS != rval)
5872     return rval;
5873   if (0 == iter.get_sequence() ||
5874       dead3+1 != iter.get_sequence()->start_handle() ||
5875       dead4-1 != iter.get_sequence()->end_handle())
5876     return MB_FAILURE;
5877   if (iter.get_start_handle() != dead3+1)
5878     return MB_FAILURE;
5879   if (iter.get_end_handle() != dead4-1)
5880     return MB_FAILURE;
5881 
5882     // next the third sequence
5883   rval = iter.step();
5884   if (MB_SUCCESS != rval)
5885     return rval;
5886   if (ts3 != iter.get_sequence())
5887     return MB_FAILURE;
5888   if (iter.get_start_handle() != ts3->start_handle())
5889     return MB_FAILURE;
5890   if (iter.get_end_handle() != ts3->end_handle())
5891     return MB_FAILURE;
5892 
5893     // next the quad sequence up to the hole in the middle
5894   rval = iter.step();
5895   if (MB_SUCCESS != rval)
5896     return rval;
5897   if (0 == iter.get_sequence() ||
5898       qs1s != iter.get_sequence()->start_handle() ||
5899       dead5-1 != iter.get_sequence()->end_handle())
5900     return MB_FAILURE;
5901   if (iter.get_start_handle() != qs1s)
5902     return MB_FAILURE;
5903   if (iter.get_end_handle() != dead5-1)
5904     return MB_FAILURE;
5905 
5906     // next the remainder of the quad sequence after the hole
5907   rval = iter.step();
5908   if (MB_SUCCESS != rval)
5909     return rval;
5910   if (0 == iter.get_sequence() ||
5911       dead6+1 != iter.get_sequence()->start_handle() ||
5912       qs1e != iter.get_sequence()->end_handle())
5913     return MB_FAILURE;
5914   if (iter.get_start_handle() != dead6+1)
5915     return MB_FAILURE;
5916   if (iter.get_end_handle() != qs1e)
5917     return MB_FAILURE;
5918 
5919     // now at the end
5920   if (!iter.is_at_end())
5921     return MB_FAILURE;
5922   rval = iter.step();
5923   if (MB_FAILURE != rval)
5924     return MB_FAILURE;
5925 
5926   return MB_SUCCESS;
5927 }
5928 
5929 #define ASSERT_EQUAL( A, B ) \
5930   do { if (!_assert_equal( (A), (B), #A, #B, __LINE__)) \
5931     return MB_FAILURE; } while(false)
5932 
5933 #define ASSERT_NOT_EQUAL( A, B ) \
5934   do { if (!_assert_not_equal( (A), (B), #A, #B, __LINE__)) \
5935     return MB_FAILURE; } while(false)
5936 
5937 template <typename T1, typename T2>
_assert_equal(T1 a,T2 b,const char * as,const char * bs,int line)5938 bool _assert_equal( T1 a, T2 b, const char* as, const char* bs, int line )
5939 {
5940   if (a == b)
5941     return true;
5942 
5943   std::cout << "Assertion failed at line " << line << std::endl
5944             << "\t" << as << " == " << bs << std::endl
5945             << "\t" << as << " = " << a << std::endl
5946             << "\t" << bs << " = " << b << std::endl;
5947   return false;
5948 }
5949 
5950 template <typename T1, typename T2>
_assert_not_equal(T1 a,T2 b,const char * as,const char * bs,int line)5951 bool _assert_not_equal( T1 a, T2 b, const char* as, const char* bs, int line )
5952 {
5953   if (a != b)
5954     return true;
5955 
5956   std::cout << "Assertion failed at line " << line << std::endl
5957             << "\t" << as << " != " << bs << std::endl
5958             << "\t" << as << " = " << a << std::endl
5959             << "\t" << bs << " = " << b << std::endl;
5960   return false;
5961 }
5962 
operator <<(std::ostream & s,Range::const_iterator i)5963 std::ostream& operator<<( std::ostream& s, Range::const_iterator i ) {
5964   return s << *i;
5965 }
5966 
mb_poly_adjacency_test()5967 ErrorCode mb_poly_adjacency_test()
5968 {
5969   ErrorCode rval;
5970   Core moab;
5971   Interface *mbImpl = &moab;
5972 
5973     // make a couple polygons and a polyhedron
5974   double coords[3] = {0,1,2};
5975   EntityHandle verts[10], polygons[2], polyhedron;
5976 
5977   for (int i = 0; i < 10; i++) {
5978     rval = mbImpl->create_vertex(coords, verts[i]);
5979     if (MB_SUCCESS != rval)
5980       return rval;
5981   }
5982 
5983   for (int i = 0; i < 2; i++) {
5984     rval = mbImpl->create_element(MBPOLYGON, verts, 5, polygons[i]);
5985     if (MB_SUCCESS != rval)
5986       return rval;
5987   }
5988   rval = mbImpl->create_element(MBPOLYHEDRON, polygons, 2, polyhedron);
5989   if (MB_SUCCESS != rval)
5990     return rval;
5991 
5992     // create the aentities
5993   Range dum_range;
5994   for (int dim = 0; dim < 3; dim++) {
5995     dum_range.clear();
5996     rval = mbImpl->get_adjacencies(&polyhedron, 1, dim, true, dum_range);
5997     if (MB_SUCCESS != rval)
5998       return rval;
5999   }
6000 
6001     // delete the polyhedron
6002   rval = mbImpl->delete_entities(&polyhedron, 1);
6003   if (MB_SUCCESS != rval)
6004     return rval;
6005 
6006     // check adjacencies
6007   return moab.check_adjacencies();
6008 }
6009 
mb_poly_adjacency_test2()6010 ErrorCode mb_poly_adjacency_test2()
6011 {
6012   ErrorCode rval;
6013   Core moab;
6014   Interface *mbImpl = &moab;
6015 
6016     // make a polyhedra in shape of a cube with a corner cut
6017 
6018   /*
6019    *
6020    *             7   -------------   8
6021    *          .  |               .   |
6022    *       .                  .      |  initial cube had 8 vertices; box [000 - 222]
6023    *    5   -------------   6        |   cut a triangle 123 on lower corner
6024    *    |        |          |        |
6025    *    |                   |        |   faces of the polyhedra (pointing outward)
6026    *    |        |          |        |   (123) (24653) (4 10 8 6)
6027    *    3                   |        |   (9 10 4 2 1) (7 8 10 9)  (5687)
6028    *     \       |          |        |   (1 3 5 7 9)
6029    *             9   -  -  -|  -    10
6030    *       \  .             |     .
6031    *        1,              |  .
6032    *  (000)      '2 ----    4
6033    *
6034    */
6035   double coords[] = {0, 1, 0,   // vertex 1
6036                      1, 0, 0,   // vertex 2
6037                      0, 0 ,1,   // vertex 3
6038                      2, 0, 0,
6039                      0, 0, 2,
6040                      2, 0, 2,   // vertex 6
6041                      0, 2, 2,
6042                      2, 2, 2,   // vertex 8
6043                      0, 2, 0,   // vertex 9
6044                      2, 2, 0    // vertex 9
6045 
6046   };
6047   EntityHandle verts[10], polygons[7], polyhedron;
6048 
6049   for (int i = 0; i < 10; i++) {
6050     rval = mbImpl->create_vertex(&coords[3*i], verts[i]);
6051     if (MB_SUCCESS != rval)
6052       return rval;
6053   }
6054 
6055   EntityHandle connect[]= {1, 2, 3,       // poly 1
6056                            2, 4, 6, 5, 3,  // poly 2
6057                            4, 10, 8, 6,    // polygon 3...
6058                            9, 10, 4, 2, 1,
6059                            7, 8, 10, 9,
6060                            5, 6, 8, 7,
6061                            1, 3, 5, 7, 9   // polygon 7
6062                            }; // we know the handles directly
6063 
6064   int num_verts[7]={3, 5, 4, 5, 4, 4, 5};
6065   int start_indx[7];
6066   start_indx[0]= 0;
6067   for (int i=0; i<6; i++)
6068     start_indx[i+1]=start_indx[i]+num_verts[i];
6069   for (int j = 0; j < 7; j++) {
6070     rval = mbImpl->create_element(MBPOLYGON, &connect[start_indx[j]],
6071         num_verts[j], polygons[j]);
6072     if (MB_SUCCESS != rval)
6073       return rval;
6074   }
6075   rval = mbImpl->create_element(MBPOLYHEDRON, polygons, 7, polyhedron);
6076   if (MB_SUCCESS != rval)
6077     return rval;
6078 
6079     // create the aentities
6080   Range dum_range;
6081   for (int dim = 0; dim < 3; dim++) {
6082     dum_range.clear();
6083     rval = mbImpl->get_adjacencies(&polyhedron, 1, dim, true, dum_range, Interface::UNION);
6084     if (MB_SUCCESS != rval)
6085       return rval;
6086     // std::cout << "\n dimension:" << dim << " " << dum_range.size() << " entities";
6087   }
6088   // std::cout << "\n";
6089   /*rval=mbImpl->write_mesh("polyhedra.vtk");
6090   if (MB_SUCCESS != rval)
6091     return rval;*/
6092     // delete the polyhedron
6093   rval = mbImpl->delete_entities(&polyhedron, 1);
6094   if (MB_SUCCESS != rval)
6095     return rval;
6096 
6097     // check adjacencies
6098   return moab.check_adjacencies();
6099 }
6100 
mb_memory_use_test()6101 ErrorCode mb_memory_use_test()
6102 {
6103   Core mb;
6104   unsigned long long init_total, total_with_elem, total_with_tag, total_with_tag_data;
6105   mb.estimated_memory_use(0,0,0,&init_total);
6106 
6107   double coords[12] = { 1, 2, 0, 3, 4, 0, 5, 6, 0, 7, 8, 0 };
6108   EntityHandle verts[4];
6109   for (int i = 0; i < 4; ++i)
6110     if (MB_SUCCESS != mb.create_vertex( coords + 3*i, verts[i] ))
6111       return MB_FAILURE;
6112 
6113   EntityHandle elem;
6114   mb.create_element( MBQUAD, verts, 4, elem );
6115 
6116   mb.estimated_memory_use(0,0,0,&total_with_elem);
6117   if (total_with_elem <= init_total)
6118     return MB_FAILURE;
6119 
6120   unsigned long long min, am;
6121   Range r;
6122   r.insert( elem );
6123   mb.estimated_memory_use( r, &min, &am );
6124   if (min != 4*sizeof(EntityHandle))
6125     return MB_FAILURE;
6126 
6127   r.clear();
6128   r.insert( verts[0] );
6129   r.insert( verts[1] );
6130   mb.estimated_memory_use( r, &min, &am );
6131   if (min != 6*sizeof(double))
6132     return MB_FAILURE;
6133 
6134   Tag tag;
6135   if (MB_SUCCESS != mb.tag_get_handle( "TMP_TAG", 1, MB_TYPE_INTEGER, tag, MB_TAG_SPARSE|MB_TAG_EXCL ))
6136     return MB_FAILURE;
6137   mb.estimated_memory_use( r, &min, &am );
6138   if (min != 6*sizeof(double))
6139     return MB_FAILURE;
6140 
6141   mb.estimated_memory_use(0,0,0,&total_with_tag);
6142   if (total_with_tag <= total_with_elem)
6143     return MB_FAILURE;
6144 
6145   int tag_data[] = { 0xA, 0xB };
6146   if (MB_SUCCESS != mb.tag_set_data( tag, r, &tag_data ))
6147     return MB_FAILURE;
6148   mb.estimated_memory_use( r, &min, &am );
6149   if (min <= 6*sizeof(double))
6150     return MB_FAILURE;
6151 
6152   mb.estimated_memory_use(0,0,0,&total_with_tag_data);
6153   if (total_with_tag_data <= total_with_tag)
6154     return MB_FAILURE;
6155 
6156   return MB_SUCCESS;
6157 }
6158 
6159 ErrorCode mb_skin_curve_test_common( bool use_adj );
6160 
mb_skin_curve_test()6161 ErrorCode mb_skin_curve_test()
6162   { return mb_skin_curve_test_common( false ); }
6163 
mb_skin_curve_adj_test()6164 ErrorCode mb_skin_curve_adj_test()
6165   { return mb_skin_curve_test_common( true ); }
6166 
6167 ErrorCode mb_skin_surface_test_common( bool use_adj );
6168 
mb_skin_surface_test()6169 ErrorCode mb_skin_surface_test()
6170   { return mb_skin_surface_test_common( false ); }
6171 
mb_skin_surface_adj_test()6172 ErrorCode mb_skin_surface_adj_test()
6173   { return mb_skin_surface_test_common( true ); }
6174 
6175 ErrorCode mb_skin_volume_test_common( bool use_adj );
6176 
mb_skin_volume_test()6177 ErrorCode mb_skin_volume_test()
6178   { return mb_skin_volume_test_common( false ); }
6179 
mb_skin_volume_adj_test()6180 ErrorCode mb_skin_volume_adj_test()
6181   { return mb_skin_volume_test_common( true ); }
6182 
mb_skin_curve_test_common(bool use_adj)6183 ErrorCode mb_skin_curve_test_common( bool use_adj )
6184 {
6185   ErrorCode rval;
6186   Core moab;
6187   Interface *mb = &moab;
6188 
6189   std::vector<EntityHandle> verts;
6190   for (unsigned i = 0; i < 10; ++i) {
6191     double coords[] = { static_cast<double>(i), 0, 0 };
6192     EntityHandle h;
6193     mb->create_vertex( coords, h );
6194     verts.push_back(h);
6195   }
6196   Range edges;
6197   for (unsigned i = 1; i < verts.size(); ++i) {
6198     EntityHandle conn[] = { verts[i-1], verts[i] };
6199     EntityHandle h;
6200     mb->create_element( MBEDGE, conn, 2, h );
6201     edges.insert(h);
6202   }
6203 
6204   Range skin;
6205   Skinner tool(mb);
6206   rval = tool.find_skin( 0, edges, 0, skin, use_adj );
6207   if (MB_SUCCESS != rval) {
6208     std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
6209     return MB_FAILURE;
6210   }
6211   if (skin.size() != 2) {
6212     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6213     return MB_FAILURE;
6214   }
6215 
6216   if (verts.front() > verts.back())
6217     std::swap( verts.front(), verts.back() );
6218   if (skin.front() != verts.front() ||
6219       skin.back()  != verts.back()) {
6220     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6221     return MB_FAILURE;
6222   }
6223 
6224 
6225     // now test again with only one edge
6226   EntityHandle edge = edges.front();
6227   Range range(edge,edge);
6228   skin.clear();
6229   rval = tool.find_skin( 0, range, 0, skin, use_adj );
6230   if (MB_SUCCESS != rval) {
6231     std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
6232     return MB_FAILURE;
6233   }
6234   if (skin.size() != 2) {
6235     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6236     return MB_FAILURE;
6237   }
6238 
6239   Range verts2;
6240   mb->get_connectivity( &edge, 1, verts2 );
6241   if (skin.front() != verts2.front() ||
6242       skin.back()  != verts2.back()) {
6243     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6244     return MB_FAILURE;
6245   }
6246 
6247   return MB_SUCCESS;
6248 }
6249 
mb_skin_surface_test_common(bool use_adj)6250 ErrorCode mb_skin_surface_test_common( bool use_adj )
6251 {
6252   ErrorCode rval;
6253   Core moab;
6254   Interface *mb = &moab;
6255 
6256     /* Create 4 of 5 faces of a wedge: */
6257     /*
6258             4
6259            /|\
6260           / | \
6261          /  |  \
6262         /   2   \
6263        3.../.\...5
6264        |  /   \  |
6265        | /     \ |
6266        |/       \|
6267        0_________1
6268      */
6269 
6270   const double coords[][3] = { { 0, 0, 0 },
6271                                { 2, 0, 0 },
6272                                { 1, 0, 1 },
6273                                { 0, 2, 0 },
6274                                { 2, 2, 0 },
6275                                { 1, 2, 1 } };
6276   EntityHandle verts[6];
6277   for (unsigned i = 0; i < 6; ++i)
6278     mb->create_vertex( coords[i], verts[i] );
6279 
6280   EntityHandle faces[4];
6281   EntityHandle tri[] = { verts[0], verts[1], verts[2] };
6282   EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
6283   EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
6284   EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
6285   mb->create_element( MBTRI, tri, 3, faces[0] );
6286   mb->create_element( MBQUAD, quad1, 4, faces[1] );
6287   mb->create_element( MBQUAD, quad2, 4, faces[2] );
6288   mb->create_element( MBQUAD, quad3, 4, faces[3] );
6289   Range source;
6290   std::copy( faces, faces+4, range_inserter(source) );
6291 
6292     // Now skin the mesh.  The only missing face is the
6293     // back triangle (verts 3, 4, & 5) so the skin should
6294     // be the edges bordering that face.
6295 
6296   Range skin;
6297   Skinner tool(mb);
6298   rval = tool.find_skin( 0, source, 1, skin, use_adj );
6299   if (MB_SUCCESS != rval) {
6300     std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
6301     return MB_FAILURE;
6302   }
6303   if (skin.size() != 3 || !skin.all_of_type(MBEDGE)) {
6304     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6305     return MB_FAILURE;
6306   }
6307 
6308     // Check each edge
6309   std::vector<EntityHandle> conn[3];
6310   rval = mb->get_connectivity( &skin.front(), 1, conn[0] );
6311   if (MB_SUCCESS != rval)
6312     return rval;
6313   rval = mb->get_connectivity( &*++skin.begin(), 1, conn[1] );
6314   if (MB_SUCCESS != rval)
6315     return rval;
6316   rval = mb->get_connectivity( &skin.back(), 1, conn[2] );
6317   if (MB_SUCCESS != rval)
6318     return rval;
6319   for (int i = 0; i < 3; ++i)
6320     if (conn[i][0] > conn[i][1])
6321       std::swap(conn[i][0], conn[i][1]);
6322 
6323   for (int i = 0; i < 3; ++i) {
6324     EntityHandle s = verts[i+3], e = verts[(i+1)%3 + 3];
6325     if (s > e)
6326       std::swap(s,e);
6327     int j = 0;
6328     for (j = 0; j < 3; ++j)
6329       if (conn[j][0] == s && conn[j][1] == e)
6330         break;
6331 
6332     if (j == 3) {
6333       std::cerr << "Skin does not contain edge [" << s << "," << e << "] at "
6334                 << __FILE__ ":" << __LINE__ << std::endl;
6335       return MB_FAILURE;
6336     }
6337   }
6338 
6339   return MB_SUCCESS;
6340 }
6341 
mb_skin_volume_test_common(bool use_adj)6342 ErrorCode mb_skin_volume_test_common( bool use_adj )
6343 {
6344   ErrorCode rval;
6345   Core moab;
6346   Interface *mb = &moab;
6347 
6348     /* A 2 adjacent hexes hexes */
6349     /*
6350           9-----10----11
6351          /     /     /|
6352         /     /     / |
6353        6-----7-----8..5
6354        | .   | .   | /
6355        |.    |.    |/
6356        0-----1-----2
6357      */
6358 
6359   const double coords[][3] = { { 0, 0, 0 },
6360                                { 1, 0, 0 },
6361                                { 2, 0, 0 },
6362                                { 0, 1, 0 },
6363                                { 1, 1, 0 },
6364                                { 2, 1, 0 },
6365                                { 0, 0, 1 },
6366                                { 1, 0, 1 },
6367                                { 2, 0, 1 },
6368                                { 0, 1, 1 },
6369                                { 1, 1, 1 },
6370                                { 2, 1, 1 } };
6371   EntityHandle verts[12];
6372   for (unsigned i = 0; i < 12; ++i)
6373     mb->create_vertex( coords[i], verts[i] );
6374 
6375   EntityHandle hex1c[] = { verts[0], verts[1], verts[4], verts[3],
6376                           verts[6], verts[7], verts[10], verts[9] };
6377   EntityHandle hex2c[] = { verts[1], verts[2], verts[5], verts[4],
6378                           verts[7], verts[8], verts[11], verts[10] };
6379   EntityHandle hex1, hex2;
6380   mb->create_element( MBHEX, hex1c, 8, hex1 );
6381   mb->create_element( MBHEX, hex2c, 8, hex2 );
6382   Range source;
6383   source.insert( hex1 );
6384   source.insert( hex2 );
6385 
6386     // get all quads and shared face
6387   Range tmp, all_faces;
6388   mb->get_adjacencies( source, 2, true, all_faces, Interface::UNION );
6389   mb->get_adjacencies( source, 2, true, tmp, Interface::INTERSECT );
6390   assert(tmp.size() == 1);
6391   Range non_shared = subtract( all_faces, tmp );
6392 
6393     // Now skin the mesh.
6394 
6395   Range skin;
6396   Skinner tool(mb);
6397   rval = tool.find_skin( 0, source, 2, skin, use_adj );
6398   if (MB_SUCCESS != rval) {
6399     std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
6400     return MB_FAILURE;
6401   }
6402   if (skin != non_shared) {
6403     std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
6404     return MB_FAILURE;
6405   }
6406 
6407   return MB_SUCCESS;
6408 }
6409 
mb_skin_scd_test()6410 ErrorCode mb_skin_scd_test()
6411 {
6412     // make a 10x10x5 scd mesh
6413   Core moab;
6414   Interface *mb = &moab;
6415   ScdInterface *scdi;
6416   ErrorCode rval = mb->query_interface(scdi);
6417   if (MB_SUCCESS != rval) return rval;
6418   HomCoord low(0, 0, 0), high(10, 10, 5);
6419   ScdBox *this_box;
6420   rval = scdi->construct_box(low, high, NULL, 0, this_box);
6421   if (MB_SUCCESS != rval) return rval;
6422 
6423     // now skin it with the structured and original method, and compare results
6424   Skinner tool(mb);
6425   Range ents(this_box->start_element(), this_box->start_element()+this_box->num_elements()-1),
6426       scd_skin_ents, skin_ents;
6427   rval = tool.find_skin(0, ents, false, scd_skin_ents, NULL, true, true, true);
6428   if (MB_SUCCESS != rval) return rval;
6429 
6430   rval = tool.find_skin(0, ents, false, skin_ents, NULL, true, true, false);
6431   if (MB_SUCCESS != rval) return rval;
6432 
6433     // should be same number of entities
6434   if (scd_skin_ents.size() != skin_ents.size()) return MB_FAILURE;
6435 
6436   skin_ents.clear();
6437   scd_skin_ents.clear();
6438 
6439     // now test getting faces and vertices, also with existing faces now
6440   rval = tool.find_skin(0, ents, true, scd_skin_ents, NULL, true, true, true);
6441   if (MB_SUCCESS != rval) return rval;
6442 
6443   rval = tool.find_skin(0, ents, true, skin_ents, NULL, true, true, false);
6444   if (MB_SUCCESS != rval) return rval;
6445 
6446     // again, should have same numbers
6447   if (skin_ents.subset_by_type(MBVERTEX).size() != scd_skin_ents.subset_by_type(MBVERTEX).size())
6448     return MB_FAILURE;
6449 
6450   return MB_SUCCESS;
6451 }
6452 
mb_skin_fileset_test()6453 ErrorCode mb_skin_fileset_test()
6454 {
6455   Core moab;
6456   Interface *mb = &moab;
6457   ErrorCode error;
6458   const double coords[] = {0,0,0,
6459                            1,0,0,
6460                            2,0,0,
6461                            2,1,0,
6462                            1,1,0,
6463                            0,1,0,
6464                            0,0,1,
6465                            1,0,1,
6466                            2,0,1,
6467                            2,1,1,
6468                            1,1,1,
6469                            0,1,1,
6470                            0,0,2,
6471                            1,0,2,
6472                            2,0,2,
6473                            2,1,2,
6474                            1,1,2,
6475                            0,1,2 };
6476      const size_t num_vtx = sizeof(coords)/sizeof(double)/3;
6477 
6478      const int conn[] = {0,1,4,5,6,7,10,11,
6479                         1,2,3,4,7,8,9,10,
6480                         6,7,10,11,12,13,16,17,
6481                         7,8,9,10,13,14,15,16};
6482      const size_t num_elems = sizeof(conn)/sizeof(int)/8;
6483 
6484      EntityHandle verts[num_vtx], cells[num_elems];
6485      for (size_t i=0; i< num_vtx; ++i)
6486        {
6487          error = mb->create_vertex(coords+3*i, verts[i]); MB_CHK_ERR(error);
6488        }
6489 
6490      for (size_t i=0; i< num_elems; ++i)
6491        {
6492          EntityHandle c[8];
6493          for (int j=0; j<8; j++)
6494            c[j] = verts[conn[8*i+j]];
6495 
6496          error = mb->create_element(MBHEX, c, 8, cells[i]);MB_CHK_ERR(error);
6497        }
6498 
6499      EntityHandle fileset;
6500      error = mb->create_meshset(MESHSET_SET, fileset);MB_CHK_ERR(error);
6501      error = mb->add_entities(fileset, &verts[0], num_vtx);MB_CHK_ERR(error);
6502      error = mb->add_entities(fileset, &cells[0], num_elems);MB_CHK_ERR(error);
6503 
6504      Range fverts, fedges, ffaces, fcells;
6505      error = mb->get_entities_by_dimension(fileset, 0, fverts);MB_CHK_ERR(error);
6506      error = mb->get_entities_by_dimension(fileset, 1, fedges);MB_CHK_ERR(error);
6507      error = mb->get_entities_by_dimension(fileset, 2, ffaces);MB_CHK_ERR(error);
6508      error = mb->get_entities_by_dimension(fileset, 3, fcells);MB_CHK_ERR(error);
6509 
6510      assert(fverts.size()==18 && fedges.size()==0 && ffaces.size()==0 && fcells.size()==4);
6511 
6512      Skinner sk(mb);
6513      Range skin_ents;
6514      error = sk.find_skin(fileset, fcells, 2, skin_ents, false, true);MB_CHK_ERR(error);
6515      error = mb->get_entities_by_dimension(fileset, 2, ffaces);MB_CHK_ERR(error);
6516      assert(ffaces.size() == 16);
6517      error = sk.find_skin(fileset, fcells, 1, skin_ents, false, true);MB_CHK_ERR(error);
6518      error = mb->get_entities_by_dimension(fileset, 1, fedges);MB_CHK_ERR(error);
6519      assert(fedges.size() == 32);
6520 
6521      const double fcoords[] = {  0,0,3,
6522                                  1,0,3,
6523                                  2,0,3,
6524                                  2,1,3,
6525                                  1,1,3,
6526                                  0,1,3 };
6527         const size_t num_fvtx = sizeof(fcoords)/sizeof(double)/3;
6528 
6529         const int fconn[] = {0,1,4,5,
6530                            1,2,3,4};
6531         const size_t num_faces = sizeof(fconn)/sizeof(int)/4;
6532         EntityHandle nwverts[num_fvtx], faces[num_faces];
6533         for (size_t i=0; i< num_fvtx; ++i)
6534           {
6535             error = mb->create_vertex(fcoords+3*i, nwverts[i]); MB_CHK_ERR(error);
6536           }
6537 
6538         for (size_t i=0; i< num_faces; ++i)
6539           {
6540             EntityHandle c[4];
6541             for (int j=0; j<4; j++)
6542               c[j] = nwverts[fconn[4*i+j]];
6543 
6544             error = mb->create_element(MBQUAD, c, 4, faces[i]);MB_CHK_ERR(error);
6545           }
6546         EntityHandle fileset1;
6547         error = mb->create_meshset(MESHSET_SET, fileset1);MB_CHK_ERR(error);
6548         error = mb->add_entities(fileset1, &nwverts[0], num_fvtx);MB_CHK_ERR(error);
6549         error = mb->add_entities(fileset1, &faces[0], num_faces);MB_CHK_ERR(error);
6550 
6551         Range verts1, edges1, faces1;
6552         error = mb->get_entities_by_dimension(fileset1, 0, verts1);MB_CHK_ERR(error);
6553         error = mb->get_entities_by_dimension(fileset1, 1, edges1);MB_CHK_ERR(error);
6554         error = mb->get_entities_by_dimension(fileset1, 2, faces1);MB_CHK_ERR(error);
6555 
6556         assert(verts1.size()==6 && edges1.size()==0 && faces1.size()==2);
6557 
6558       //  error = sk.find_skin(fileset1, faces1, 1, skin_ents, false, true);MB_CHK_ERR(error);
6559         error = sk.find_skin(fileset1, faces1, false, skin_ents, NULL, true, true, false);MB_CHK_ERR(error);
6560         error = mb->get_entities_by_dimension(fileset1, 1, edges1);MB_CHK_ERR(error);
6561         assert(edges1.size() == 6);
6562 
6563 
6564         return MB_SUCCESS;
6565 }
6566 
6567 // It is a common problem for readers to incorrectly
6568 // handle invalid/unknown file types and non-existant
6569 // files.  For either case, MOAB will try all readers
6570 // (assuming it doesn't recongnize the file extension),
6571 // so we can test all the readers w/out knowing which
6572 // readers we have.
6573 const char* argv0 = 0;
mb_read_fail_test()6574 ErrorCode mb_read_fail_test()
6575 {
6576   Core moab;
6577   Interface* mb = &moab;
6578 
6579   const char BAD_FILE_NAME[] = "non-existant-file.txt";
6580   ErrorCode rval;
6581 
6582   FILE* fptr = fopen(BAD_FILE_NAME,"r");
6583   if (fptr) {
6584     fclose(fptr);
6585     std::cout << "Test cannot proceed while file exists: " << BAD_FILE_NAME << std::endl;
6586     return MB_FAILURE;
6587   }
6588 
6589     // try reading a non-existant file
6590 
6591   rval = mb->load_file( BAD_FILE_NAME );
6592   if (MB_FILE_DOES_NOT_EXIST != rval)
6593     return MB_FAILURE;
6594 
6595     // try reading an invalid file
6596   if (!argv0)  // not set by main, oops!
6597     return MB_FAILURE;
6598   rval = mb->load_file( argv0 );
6599   if (MB_SUCCESS == rval)
6600     return MB_FAILURE;
6601 
6602   return MB_SUCCESS;
6603 }
6604 
6605 #define TEST_ERROR_CODE(E) \
6606   if (mb->get_error_string(E) != #E) { \
6607     std::cerr << "Invalid error string from get_error_string for " \
6608               << #E << ": " << mb->get_error_string(E) << std::endl;\
6609     return MB_FAILURE; \
6610   }
6611 
mb_enum_string_test()6612 ErrorCode mb_enum_string_test()
6613 {
6614   Core moab;
6615   Interface* mb = &moab;
6616 
6617   TEST_ERROR_CODE( MB_SUCCESS );
6618   TEST_ERROR_CODE( MB_INDEX_OUT_OF_RANGE );
6619   TEST_ERROR_CODE( MB_TYPE_OUT_OF_RANGE );
6620   TEST_ERROR_CODE( MB_MEMORY_ALLOCATION_FAILED );
6621   TEST_ERROR_CODE( MB_ENTITY_NOT_FOUND );
6622   TEST_ERROR_CODE( MB_MULTIPLE_ENTITIES_FOUND );
6623   TEST_ERROR_CODE( MB_TAG_NOT_FOUND );
6624   TEST_ERROR_CODE( MB_FILE_DOES_NOT_EXIST );
6625   TEST_ERROR_CODE( MB_FILE_WRITE_ERROR );
6626   TEST_ERROR_CODE( MB_NOT_IMPLEMENTED );
6627   TEST_ERROR_CODE( MB_ALREADY_ALLOCATED );
6628   TEST_ERROR_CODE( MB_VARIABLE_DATA_LENGTH );
6629   TEST_ERROR_CODE( MB_INVALID_SIZE );
6630   TEST_ERROR_CODE( MB_UNSUPPORTED_OPERATION );
6631   TEST_ERROR_CODE( MB_UNHANDLED_OPTION );
6632   TEST_ERROR_CODE( MB_STRUCTURED_MESH );
6633   TEST_ERROR_CODE( MB_FAILURE );
6634 
6635   return MB_SUCCESS;
6636 }
6637 
6638 // Test basic skinning using vert-to-elem adjacencies
6639 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems );
6640 
mb_skin_surf_verts_test()6641 ErrorCode mb_skin_surf_verts_test()
6642   { return mb_skin_verts_common( 2, false ); }
6643 
mb_skin_vol_verts_test()6644 ErrorCode mb_skin_vol_verts_test()
6645   { return mb_skin_verts_common( 3, false ); }
6646 
mb_skin_surf_verts_elems_test()6647 ErrorCode mb_skin_surf_verts_elems_test()
6648   { return mb_skin_verts_common( 2, true ); }
6649 
mb_skin_vol_verts_elems_test()6650 ErrorCode mb_skin_vol_verts_elems_test()
6651   { return mb_skin_verts_common( 3, true ); }
6652 
mb_skin_verts_common(unsigned dim,bool skin_elems)6653 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems )
6654 {
6655   const int INT = 10; // intervals+1
6656   const char* tmp_file = "structured.vtk";
6657   std::ofstream str(tmp_file);
6658   if (!str) {
6659     std::cerr << tmp_file << ": filed to create temp file" << std::endl;
6660     return MB_FAILURE;
6661   }
6662   str << "#vtk DataFile Version 2.0" << std::endl
6663       << "mb_skin_verts_common temp file" << std::endl
6664       << "ASCII" << std::endl
6665       << "DATASET STRUCTURED_POINTS" << std::endl
6666       << "DIMENSIONS " << INT << " " << (dim > 1 ? INT : 1) << " "  << (dim > 2 ? INT : 1) << std::endl
6667       << "ORIGIN 0 0 0" << std::endl
6668       << "SPACING 1 1 1" << std::endl;
6669   str.close();
6670 
6671   Core moab;
6672   Interface& mb = moab;
6673   ErrorCode rval;
6674 
6675   rval = mb.load_file( tmp_file );
6676   remove( tmp_file );
6677   if (MB_SUCCESS != rval)
6678     return rval;
6679 
6680   Range ents;
6681   rval = mb.get_entities_by_dimension( 0, dim, ents );
6682   if (MB_SUCCESS != rval)
6683     return rval;
6684   if (ents.empty())
6685     return MB_FAILURE;
6686 
6687   Skinner tool( &mb );
6688 
6689    // mesh is a structured quad/hex mesh, so we can
6690    // determine skin vertices from the number of
6691    // adjacent elements.
6692   unsigned interior_adj = 1;
6693   for (unsigned i = 0; i < dim; ++i)
6694     interior_adj *= 2;
6695   Range expected, verts;
6696   rval = mb.get_entities_by_dimension( 0, 0, verts );
6697   if (MB_SUCCESS != rval)
6698     return rval;
6699   Range::iterator h = expected.begin();
6700   std::vector<EntityHandle> adj;
6701   for (Range::iterator v = verts.begin(); v != verts.end(); ++v) {
6702     adj.clear();
6703     rval = mb.get_adjacencies( &*v, 1, dim, false, adj );
6704     if (MB_SUCCESS != rval)
6705       return rval;
6706     if (adj.size() < interior_adj)
6707       h = expected.insert( h, *v );
6708   }
6709 
6710     // Get skin vertices using skinner
6711   Range actual;
6712   rval = tool.find_skin( 0, ents, !skin_elems, actual );
6713   if (MB_SUCCESS != rval)
6714     return rval;
6715 
6716   Range extra, missing;
6717   if (!skin_elems) {
6718       // Check that we got expected result
6719     extra = subtract( actual, expected );
6720     missing = subtract( expected, actual );
6721     if (!extra.empty() || !missing.empty()) {
6722       std::cout << "Extra vertices returned: " << extra << std::endl
6723                 << "Missing vertices: " << missing << std::endl;
6724       return MB_FAILURE;
6725     }
6726     return MB_SUCCESS;
6727   }
6728 
6729     // test that no extra elements we're created
6730   extra.clear();
6731   rval = mb.get_entities_by_dimension( 0, dim-1, extra );
6732   if (MB_SUCCESS != rval)
6733     return rval;
6734   extra = subtract( extra, actual );
6735   if (!extra.empty()) {
6736     std::cout << "Extra/non-returned elements created: " << extra << std::endl;
6737     return MB_FAILURE;
6738   }
6739 
6740     // check that each skin vertex has the correct number of adjacent quads
6741   missing.clear(); extra.clear();
6742   for (Range::iterator i = expected.begin(); i != expected.end(); ++i) {
6743     std::vector<EntityHandle> elem, side;
6744     rval = mb.get_adjacencies( &*i, 1, dim, false, elem );
6745     if (MB_SUCCESS != rval) return rval;
6746     rval = mb.get_adjacencies( &*i, 1, dim-1, false, side );
6747     if (MB_SUCCESS != rval) return rval;
6748     if (elem.size() == 1) {
6749       if (side.size() < dim)
6750         missing.insert( *i );
6751       else if(side.size() > dim)
6752         extra.insert( *i );
6753     }
6754     else if (elem.size() == interior_adj) {
6755       if (!side.empty())
6756         extra.insert( *i );
6757     }
6758     else {
6759       if (side.size() < interior_adj/2)
6760         missing.insert( *i );
6761       else if (side.size() > interior_adj/2)
6762         extra.insert( *i );
6763     }
6764   }
6765   if (!missing.empty() || !extra.empty()) {
6766     std::cout << "Skin elements missing at vertices: " << missing << std::endl
6767               << "Extra skin elements at vertices: " << extra << std::endl;
6768     return MB_FAILURE;
6769   }
6770 
6771     // check that all returned elements are actually on the skin
6772   extra.clear();
6773   for (Range::iterator i = actual.begin(); i != actual.end(); ++i) {
6774     Range verts2;
6775     rval = mb.get_adjacencies( &*i, 1, 0, false, verts2 );
6776     if (MB_SUCCESS != rval)
6777       return rval;
6778     verts2 = subtract( verts2, expected );
6779     if (!verts2.empty())
6780       extra.insert( *i );
6781   }
6782   if (!extra.empty()) {
6783     std::cout << "Skinner returned elements not on skin: " << extra << std::endl;
6784     return MB_FAILURE;
6785   }
6786 
6787   return MB_SUCCESS;
6788 }
6789 
6790 // Test that skinning of polyhedra works
mb_skin_poly_test()6791 ErrorCode mb_skin_poly_test()
6792 {
6793   /* Create a mesh composed of 8 hexagonal prisms and
6794      two hexahedra by extruding the following cross section
6795      two steps in the Z direction.
6796 
6797              0-----1
6798             /  (0)  \
6799        (11)/         \(1)
6800           /           \
6801         11             2
6802         / \     Y     / \
6803    (10)/   \(12)^(13)/   \(2)
6804       /     \   |   /     \
6805     10      12-----13      3
6806      |       |  |  |       |
6807   (9)|       |  +--|-->X   |(3)
6808      |       |     |       |
6809      9      15-----14      4
6810       \     /       \     /
6811     (8)\   /(15) (14)\   /(4)
6812         \ /           \ /
6813          8             5
6814           \           /
6815         (7)\         /(5)
6816             \  (6)  /
6817              7-----6
6818   */
6819 
6820   const double coords2D[][2] = { {-1, 5}, // 0
6821                                  { 1, 5},
6822                                  { 3, 3},
6823                                  { 5, 1},
6824                                  { 5,-1},
6825                                  { 3,-3}, // 5
6826                                  { 1,-5},
6827                                  {-1,-5},
6828                                  {-3,-3},
6829                                  {-5,-1},
6830                                  {-5, 1}, // 10
6831                                  {-3, 3},
6832                                  {-1, 1},
6833                                  { 1, 1},
6834                                  { 1,-1},
6835                                  {-1,-1}  // 15
6836                                  };
6837   const int polyconn[4][6] = { { 0,  1,  2, 13, 12, 11 },
6838                                { 2,  3,  4,  5, 14, 13 },
6839                                { 5,  6,  7,  8, 15, 14 },
6840                                { 8,  9, 10, 11, 12, 15 } };
6841   const int polyside[4][6] = { { 0,  1, 13, 16, 12, 11 },
6842                                { 2,  3,  4, 14, 17, 13 },
6843                                { 5,  6,  7, 15, 18, 14 },
6844                                { 8,  9, 10, 12, 19, 15 } };
6845 
6846   ErrorCode rval;
6847   Core moab;
6848   Interface& mb = moab;
6849   Range regions, faces, interior_faces;
6850 
6851     // create 48 vertices
6852   EntityHandle verts[3][16];
6853   for (int i = 0; i < 3; ++i) {
6854     for (int j = 0; j < 16; ++j) {
6855       double coords[3] = { coords2D[j][0], coords2D[j][1], static_cast<double>(2*i) };
6856       rval = mb.create_vertex( coords, verts[i][j] );
6857       if (MB_SUCCESS != rval) return rval;
6858     }
6859   }
6860 
6861     // create two hexahedra
6862   EntityHandle hexes[2];
6863   for (int i = 0; i < 2; ++i) {
6864     EntityHandle conn[8] = { verts[i  ][15],
6865                                verts[i  ][14],
6866                                verts[i  ][13],
6867                                verts[i  ][12],
6868                                verts[i+1][15],
6869                                verts[i+1][14],
6870                                verts[i+1][13],
6871                                verts[i+1][12] };
6872     rval = mb.create_element( MBHEX, conn, 8, hexes[i] );
6873     if (MB_SUCCESS != rval) return rval;
6874     regions.insert(hexes[i]);
6875   }
6876 
6877     // create hexagonal faces
6878   EntityHandle hexagons[3][4];
6879   for (int i = 0; i < 3; ++i) {
6880     for (int j = 0; j < 4; ++j) {
6881       EntityHandle conn[6];
6882       for (int k = 0; k < 6; ++k)
6883         conn[k] = verts[i][polyconn[j][k]];
6884       rval = mb.create_element( MBPOLYGON, conn, 6, hexagons[i][j] );
6885       if (MB_SUCCESS != rval) return rval;
6886       faces.insert( hexagons[i][j] );
6887       if (i == 1)
6888         interior_faces.insert( hexagons[i][j] );
6889     }
6890   }
6891 
6892     // create quadrilateral faces
6893   EntityHandle quads[2][20];
6894   for (int i = 0; i < 2; ++i) {
6895     for (int j = 0; j < 20; ++j) {
6896       int c1, c2;
6897       if (j < 12) {
6898         c1 = j; c2 = (j+1)%12;
6899       }
6900       else if (j < 16) {
6901         c1 = j; c2 = 2 + 3*((j-9)%4);
6902       }
6903       else {
6904         c1 = j-4; c2 = 12 + (j-15)%4;
6905       }
6906       EntityHandle conn[4] = { verts[i  ][c1],
6907                                  verts[i  ][c2],
6908                                  verts[i+1][c2],
6909                                  verts[i+1][c1] };
6910       rval = mb.create_element( MBQUAD, conn, 4, quads[i][j] );
6911       if (MB_SUCCESS != rval) return rval;
6912       faces.insert( quads[i][j] );
6913       if (j > 11)
6914         interior_faces.insert( quads[i][j] );
6915     }
6916   }
6917 
6918     // create polyhedra
6919   EntityHandle poly[2][4];
6920   for (int i = 0; i < 2; ++i) {
6921     for (int j = 0; j < 4; ++j) {
6922       EntityHandle conn[8];
6923       for (int k = 0; k < 6; ++k)
6924         conn[k] = quads[i][polyside[j][k]];
6925       conn[6] = hexagons[  i][j];
6926       conn[7] = hexagons[i+1][j];
6927       rval = mb.create_element( MBPOLYHEDRON, conn, 8, poly[i][j] );
6928       if (MB_SUCCESS != rval) return rval;
6929       regions.insert( poly[i][j] );
6930     }
6931   }
6932 
6933   Range interior_verts;
6934   interior_verts.insert( verts[1][12] );
6935   interior_verts.insert( verts[1][13] );
6936   interior_verts.insert( verts[1][14] );
6937   interior_verts.insert( verts[1][15] );
6938 
6939   Skinner tool(&mb);
6940   Range skin;
6941   rval = tool.find_skin( 0, regions, true, skin, 0, true, false );
6942   if (MB_SUCCESS != rval) {
6943     std::cout << "Vertex skinning failed with: " << mb.get_error_string(rval) << std::endl;
6944     return rval;
6945   }
6946 
6947   Range all_verts, all_faces;
6948   rval = mb.get_entities_by_dimension( 0, 0, all_verts );
6949   if (MB_SUCCESS != rval) return rval;
6950   rval = mb.get_entities_by_dimension( 0, 2, all_faces );
6951   if (MB_SUCCESS != rval) return rval;
6952 
6953   Range expected = subtract( all_verts, interior_verts );
6954   if (expected != skin) {
6955     std::cout << "Skinner returned incorrect vertices." << std::endl;
6956     return MB_FAILURE;
6957   }
6958   if (all_faces != faces) {
6959     std::cout << "Skinner created/deleted faces for vertex-only skinning" << std::endl;
6960     return MB_FAILURE;
6961   }
6962 
6963   skin.clear();
6964   rval = tool.find_skin( 0, regions, false, skin, 0, true, false );
6965   if (MB_SUCCESS != rval) {
6966     std::cout << "Non-create face skinning failed with: " << mb.get_error_string(rval) << std::endl;
6967     return rval;
6968   }
6969   expected = subtract( all_faces, interior_faces );
6970   if (expected != skin) {
6971     std::cout << "Skinner returned incorrect faces." << std::endl;
6972     return MB_FAILURE;
6973   }
6974   if (all_faces != faces) {
6975     std::cout << "Skinner created/deleted faces for no-create skinning" << std::endl;
6976     return MB_FAILURE;
6977   }
6978 
6979   skin.clear();
6980   rval = tool.find_skin( 0, regions, false, skin, 0, true, true );
6981   if (MB_SUCCESS != rval) {
6982     std::cout << "Create face skinning failed with: " << mb.get_error_string(rval) << std::endl;
6983     return rval;
6984   }
6985   Range all_faces2;
6986   rval = mb.get_entities_by_dimension( 0, 2, all_faces2 );
6987   if (MB_SUCCESS != rval) return rval;
6988   Range difference = subtract( all_faces2, all_faces );
6989   if (difference.size() != 2) { // should have created two quads for hex top/bottom
6990     std::cout << "Skinner failed to create new quads or created to many." << std::endl;
6991     return MB_FAILURE;
6992   }
6993   expected.merge(difference);
6994   if (expected != skin) {
6995     std::cout << "Skinner returned incorrect faces." << std::endl;
6996     return MB_FAILURE;
6997   }
6998     // check that new faces are correct
6999   EntityHandle expected_conn[2][4] = {
7000     { verts[0][12],verts[0][13],verts[0][14],verts[0][15] },
7001     { verts[2][12],verts[2][13],verts[2][14],verts[2][15] } };
7002   EntityHandle nq[2] = { difference.front(), difference.back() };
7003   for (int i = 0; i < 2; ++i) {
7004     const EntityHandle* conn;
7005     int len;
7006     bool found = false;
7007     for (int j = 0; !found && j < 2; ++j) {
7008       rval = mb.get_connectivity( nq[j], conn, len );
7009       if (MB_SUCCESS != rval) return rval;
7010       int idx1 = std::find(conn,conn+len,expected_conn[i][0])-conn;
7011       if (idx1 == len) continue;
7012       found = true;
7013       for (int k = 1; k < 4; ++k)
7014         if (conn[(idx1+k)%4] != expected_conn[i][k])
7015           found = false;
7016       if (!found) {
7017         found = true;
7018         for (int k = 1; k < 4; ++k)
7019           if (conn[(idx1+4-k)%4] != expected_conn[i][k])
7020             found = false;
7021       }
7022     }
7023     if (!found) {
7024       std::cerr << "Skinner did not create & return expected quad " << i << std::endl;
7025       return MB_FAILURE;
7026     }
7027   }
7028 
7029   return MB_SUCCESS;
7030 }
7031 
7032 // Test that skinning of higher-order elements works
mb_skin_higher_order_faces_common(bool use_adj)7033 ErrorCode mb_skin_higher_order_faces_common( bool use_adj )
7034 {
7035   /* Create mesh:
7036 
7037      0---1---2---3---4
7038      |       |      /
7039      |       |     /
7040      5   6   7  8 9
7041      |       |   /
7042      |       |  /
7043      10--11--12
7044   */
7045 
7046   ErrorCode rval;
7047   Core moab;
7048   Interface& mb = moab;
7049 
7050   double coords[13][3] = {
7051    {0,4,0}, {2,4,0}, {4,4,0}, {6,4,0}, {8,4,0},
7052    {0,2,0}, {2,2,0}, {4,2,0}, {5,2,0}, {6,2,0},
7053    {0,0,0}, {2,0,0}, {4,0,0} };
7054   EntityHandle verts[13];
7055   for (int i = 0; i < 13; ++i) {
7056     rval = mb.create_vertex( coords[i], verts[i] );
7057     if (MB_SUCCESS != rval) return rval;
7058   }
7059 
7060   EntityHandle qconn[9] = {
7061     verts[0], verts[2], verts[12], verts[10],
7062     verts[1], verts[7], verts[11], verts[5],
7063     verts[6] };
7064   EntityHandle tconn[7] = {
7065     verts[2], verts[4], verts[12],
7066     verts[3], verts[9], verts[7],
7067     verts[8] };
7068   EntityHandle quad, tri;
7069   rval = mb.create_element( MBQUAD, qconn, 9, quad );
7070   if (MB_SUCCESS != rval) return rval;
7071   rval = mb.create_element( MBTRI, tconn, 7, tri );
7072   if (MB_SUCCESS != rval) return rval;
7073 
7074   Range faces;
7075   faces.insert(quad);
7076   faces.insert(tri);
7077 
7078   Range skin_verts;
7079   const int skin_vert_idx[] = { 0, 1, 2, 3, 4, 5, 9, 10, 11, 12 };
7080   for (size_t i = 0; i < sizeof(skin_vert_idx)/sizeof(skin_vert_idx[0]); ++i)
7081     skin_verts.insert( verts[skin_vert_idx[i]] );
7082 
7083   Skinner tool(&mb);
7084   Range skin;
7085 
7086   rval = tool.find_skin( 0, faces, true, skin, 0, use_adj, false );
7087   if (MB_SUCCESS != rval) {
7088     std::cout << "Vertex skinning failed with: " << mb.get_error_string(rval) << std::endl;
7089     return rval;
7090   }
7091   if (skin != skin_verts) {
7092     std::cout << "Skinner returned incorrect vertices." << std::endl;
7093     return MB_FAILURE;
7094   }
7095 
7096   const int skin_edges[5][3] = {
7097     {0,1,2}, {2,3,4}, {4,9,12}, {12,11,10}, {10,5,0} };
7098   skin.clear();
7099   rval = tool.find_skin( 0, faces, false, skin, 0, use_adj, true );
7100   if (MB_SUCCESS != rval) {
7101     std::cout << "Edge skinning failed with: " << mb.get_error_string(rval) << std::endl;
7102     return rval;
7103   }
7104   if (skin.size() != 5u) {
7105     std::cout << "Skinner returned " << skin.size() << " vertices.  Expected 5" << std::endl;
7106     return MB_FAILURE;
7107   }
7108   int num_quadratic = 0;
7109   const EntityHandle* conn;
7110   int len;
7111   for (Range::iterator i = skin.begin(); i != skin.end(); ++i) {
7112     rval = mb.get_connectivity( *i, conn, len, false );
7113     if (MB_SUCCESS != rval) return rval;
7114     if (len == 3)
7115       num_quadratic++;
7116     else if(len != 2) {
7117       std::cerr << "Skinner created edge with " << len << " vertices" << std::endl;
7118       return MB_FAILURE;
7119     }
7120   }
7121   if (num_quadratic != 5) {
7122     std::cerr << num_quadratic << " of 5 created edges were quadratic" << std::endl;
7123     return MB_FAILURE;
7124   }
7125 
7126   for (int i = 0; i < 5; ++i) {
7127     bool found = false;
7128     for (Range::iterator j = skin.begin(); j != skin.end(); ++j) {
7129       mb.get_connectivity( *j, conn, len, false );
7130       if (conn[2] == verts[skin_edges[i][1]]) {
7131         found = true;
7132         break;
7133       }
7134     }
7135     if (!found) {
7136       std::cerr << "One or more skin edges is incorrect" << std::endl;
7137       return MB_FAILURE;
7138     }
7139     if ((conn[0] != verts[skin_edges[i][0]] || conn[1] != verts[skin_edges[i][2]])
7140      && (conn[0] != verts[skin_edges[i][2]] || conn[1] != verts[skin_edges[i][0]])) {
7141       std::cerr << "Invalid skin edge connectivity" << std::endl;
7142       return MB_FAILURE;
7143     }
7144   }
7145 
7146   return MB_SUCCESS;
7147 }
mb_skin_higher_order_faces_test()7148 ErrorCode mb_skin_higher_order_faces_test()
7149   { return mb_skin_higher_order_faces_common( false ); }
mb_skin_adj_higher_order_faces_test()7150 ErrorCode mb_skin_adj_higher_order_faces_test()
7151   { return mb_skin_higher_order_faces_common( true ); }
7152 
7153 // Test that skinning of higher-order elements works
mb_skin_higher_order_regions_common(bool use_adj)7154 ErrorCode mb_skin_higher_order_regions_common( bool use_adj )
7155 {
7156   // create mesh containing two 27-node hexes
7157   /*
7158      0,2---1,2---2,2---3,2---4,2
7159       |           |           |
7160       |           |           |
7161      0,1   1,1   2,1   3,1   4,1
7162       |           |           |
7163       |           |           |
7164      0,0---1,0---2,0---3,0---4,0
7165   */
7166 
7167   ErrorCode rval;
7168   Core moab;
7169   Interface& mb = moab;
7170   Range hexes;
7171 
7172 
7173   EntityHandle verts[5][3][3];
7174   for (int i = 0; i < 5; ++i)
7175     for (int j = 0; j < 3; ++j)
7176       for (int k = 0; k < 3; ++k) {
7177         double coords[] = { static_cast<double>(i), static_cast<double>(j), static_cast<double>(k) };
7178         rval = mb.create_vertex( coords, verts[i][j][k] );
7179         if (MB_SUCCESS != rval) return rval;
7180       }
7181 
7182   int hex_conn[][3] = {  // corners
7183                         {0,0,0}, {2,0,0}, {2,2,0}, {0,2,0},
7184                         {0,0,2}, {2,0,2}, {2,2,2}, {0,2,2},
7185                          // mid-edge
7186                         {1,0,0}, {2,1,0}, {1,2,0}, {0,1,0},
7187                         {0,0,1}, {2,0,1}, {2,2,1}, {0,2,1},
7188                         {1,0,2}, {2,1,2}, {1,2,2}, {0,1,2},
7189                         // mid-face
7190                         {1,0,1}, {2,1,1}, {1,2,1}, {0,1,1},
7191                         {1,1,0}, {1,1,2},
7192                         // mid-volume
7193                         {1,1,1} };
7194 
7195   EntityHandle hexverts[2][27];
7196   for (int i = 0; i < 2; ++i) {
7197     EntityHandle h;
7198     for (int j = 0; j < 27; ++j)
7199       hexverts[i][j] = verts[ 2*i+hex_conn[j][0] ][ hex_conn[j][1] ][ hex_conn[j][2] ];
7200     rval = mb.create_element( MBHEX, hexverts[i], 27, h );
7201     if (MB_SUCCESS != rval)
7202       return rval;
7203     hexes.insert( h );
7204   }
7205 
7206   Range interior_verts;
7207   interior_verts.insert( verts[1][1][1] ); // mid-node of hex 1
7208   interior_verts.insert( verts[3][1][1] ); // mid-node of hex 2
7209   interior_verts.insert( verts[2][1][1] ); // mid-node of shared face
7210 
7211   Skinner tool(&mb);
7212   Range skin;
7213 
7214   rval = tool.find_skin( 0, hexes, true, skin, 0, use_adj, false );
7215   if (MB_SUCCESS != rval) {
7216     std::cout << "Vertex skinning failed with: " << mb.get_error_string(rval)
7217               << std::endl;
7218     return rval;
7219   }
7220   Range extra = intersect( skin, interior_verts );
7221   if (!extra.empty()) {
7222     std::cout << "Skinner returned " << extra.size() << " interior vertices"
7223               << std::endl;
7224     std::cout << extra << std::endl;
7225     return MB_FAILURE;
7226   }
7227   int num_vtx;
7228   mb.get_number_entities_by_dimension( 0, 0, num_vtx );
7229   size_t num_skin = num_vtx - interior_verts.size();
7230   if (skin.size() != num_skin) {
7231     std::cout << "Skinner returned " << skin.size() << " of "
7232               << num_skin << " skin vertices" <<std::endl;
7233     return MB_FAILURE;
7234   }
7235 
7236   skin.clear();
7237   rval = tool.find_skin( 0, hexes, false, skin, 0, use_adj, true );
7238   if (MB_SUCCESS != rval) {
7239     std::cout << "Element skinning failed with: " << mb.get_error_string(rval) << std::endl;
7240     return rval;
7241   }
7242 
7243   if (skin.size() > 10u) {
7244     std::cout << "Skinner created too many faces" << std::endl;
7245     return MB_FAILURE;
7246   }
7247 
7248   bool all_okay = true;
7249   bool faces[2][6] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
7250   const EntityHandle *conn;
7251   int len;
7252   for (Range::iterator it = skin.begin(); it != skin.end(); ++it) {
7253     rval = mb.get_connectivity( *it, conn, len );
7254     if (MB_SUCCESS != rval) return rval;
7255     if (len != 9) {
7256       std::cout << "Skinner created face with " << len << " nodes" << std::endl;
7257       all_okay = false;
7258       continue;
7259     }
7260 
7261     int valid, side, sense, offset;
7262     for (int h = 0; h < 2; ++h) {
7263       valid = CN::SideNumber( MBHEX, hexverts[h], conn, 4, 2, side, sense, offset );
7264       if (valid != 0)
7265         continue;
7266       if (sense != 1) {
7267         std::cout << "Skinner created reversed face for hex "
7268                   << h << " side " << side << std::endl;
7269         all_okay = false;
7270         continue;
7271       }
7272 
7273       int idx[9], len2;
7274       EntityType sidetype;
7275       CN::SubEntityNodeIndices( MBHEX, 27, 2, side, sidetype, len2, idx );
7276       assert(sidetype == MBQUAD);
7277       assert(len2 == 9);
7278       if ( conn[   offset     ] != hexverts[h][idx[0]] ||
7279            conn[  (offset+1)%4] != hexverts[h][idx[1]] ||
7280            conn[  (offset+2)%4] != hexverts[h][idx[2]] ||
7281            conn[  (offset+3)%4] != hexverts[h][idx[3]] ||
7282            conn[4+ offset     ] != hexverts[h][idx[4]] ||
7283            conn[4+(offset+1)%4] != hexverts[h][idx[5]] ||
7284            conn[4+(offset+2)%4] != hexverts[h][idx[6]] ||
7285            conn[4+(offset+3)%4] != hexverts[h][idx[7]] ||
7286            conn[ 8            ] != hexverts[h][idx[8]]) {
7287         std::cout << "Side " << side << " of hex " << h
7288                   << " has invalid connectivity" << std::endl;
7289         all_okay = false;
7290       }
7291 
7292 
7293       faces[h][side] = true;
7294     }
7295   }
7296 
7297   for (int h = 0; h < 2; ++h) {
7298     for (int i = 0; i < 6; ++i) {
7299       if ((h == 0 && i == 1) || (h == 1 && i == 3)) {
7300         if (faces[h][i]) {
7301           std::cout << "Skinner created interior face for side "
7302                     << i << " of hex " << h << std::endl;
7303           all_okay = false;
7304         }
7305       }
7306       else if (!faces[h][i]) {
7307         std::cout << "Skinner failed to create side "
7308                   << i << " of hex " << h << std::endl;
7309         all_okay = false;
7310       }
7311     }
7312   }
7313 
7314   return all_okay ? MB_SUCCESS : MB_FAILURE;
7315 }
7316 
7317 // Test that skinning of higher-order elements works
mb_skin_higher_order_pyramids()7318 ErrorCode mb_skin_higher_order_pyramids( )
7319 {
7320   // create mesh containing 13-node pyramid
7321   /*
7322 
7323   */
7324 
7325   ErrorCode rval;
7326   Core moab;
7327   Interface& mb = moab;
7328   Range pyramids;
7329 
7330 
7331   // easier to create a 27 node grid, and then pick a 13-node pyramid
7332   EntityHandle verts[3][3][3];
7333   for (int i = 0; i < 3; ++i)
7334     for (int j = 0; j < 3; ++j)
7335       for (int k = 0; k < 3; ++k) {
7336         double coords[] = { static_cast<double>(i), static_cast<double>(j), static_cast<double>(k) };
7337         rval = mb.create_vertex( coords, verts[i][j][k] );
7338         if (MB_SUCCESS != rval) return rval;
7339       }
7340 
7341 
7342   EntityHandle piramid1[13]={19, 25, 27, 21, 1, 22, 26, 24, 20, 10, 13, 14, 11};
7343 
7344   EntityHandle h;
7345 
7346   rval = mb.create_element( MBPYRAMID, piramid1, 13, h );
7347   if (MB_SUCCESS != rval)
7348     return rval;
7349   pyramids.insert( h );
7350 
7351   Range faces;
7352   rval = mb.get_adjacencies(pyramids,2, true, faces , Interface::UNION);
7353   // triangles should have 6 nodes, quads 8 nodes
7354 
7355   if (MB_SUCCESS != rval)
7356     return rval;
7357 
7358   Range tris=faces.subset_by_type(MBTRI);
7359   Range quads = faces.subset_by_type(MBQUAD);
7360 
7361   for (Range::iterator tit=tris.begin(); tit!=tris.end(); tit++)
7362   {
7363     EntityHandle triangle = *tit;
7364     const EntityHandle * conn;
7365     int num_verts;
7366     rval = mb.get_connectivity(triangle, conn, num_verts);
7367     if (MB_SUCCESS != rval)
7368       return rval;
7369     if (6!=num_verts)
7370       return MB_FAILURE;
7371   }
7372   for (Range::iterator qit=quads.begin(); qit!=quads.end(); qit++)
7373   {
7374     EntityHandle quad = *qit;
7375     const EntityHandle * conn;
7376     int num_verts;
7377     rval = mb.get_connectivity(quad, conn, num_verts);
7378     if (MB_SUCCESS != rval)
7379       return rval;
7380     if (8!=num_verts)
7381       return MB_FAILURE;
7382   }
7383 
7384   return  MB_SUCCESS;
7385 }
mb_skin_higher_order_regions_test()7386 ErrorCode mb_skin_higher_order_regions_test()
7387   { return mb_skin_higher_order_regions_common(false); }
mb_skin_adj_higher_order_regions_test()7388 ErrorCode mb_skin_adj_higher_order_regions_test()
7389   { return mb_skin_higher_order_regions_common(true); }
7390 
7391 
mb_skin_reversed_common(int dim,bool use_adj)7392 ErrorCode mb_skin_reversed_common( int dim, bool use_adj )
7393 {
7394   EntityType type, subtype;
7395   switch (dim) {
7396     case 2: type = MBTRI; subtype = MBEDGE; break;
7397     case 3: type = MBTET; subtype = MBTRI;  break;
7398     default: assert(false); return MB_FAILURE;
7399   }
7400 
7401   /*      3
7402          /|\
7403         / | \
7404        /  |  \
7405       /   |   \
7406      0----1----2
7407   */
7408 
7409   ErrorCode rval;
7410   Core moab;
7411   Interface& mb = moab;
7412   Range hexes;
7413 
7414   double coords[][3] = { { 0, 0, 0 },
7415                          { 1, 0, 0 },
7416                          { 2, 0, 0 },
7417                          { 1, 2, 0 },
7418                          { 1, 2, 2 } };
7419   EntityHandle verts[5];
7420   const int nvtx = 2+dim;
7421   for (int i = 0; i < nvtx; ++i) {
7422     rval = mb.create_vertex( coords[i], verts[i] );
7423     if (MB_SUCCESS != rval) return rval;
7424   }
7425     // NOTE: order connectivity such that side 1 is shared!
7426   EntityHandle conn[2][4] = {
7427     { verts[0], verts[1], verts[3], verts[4] },
7428     { verts[2], verts[3], verts[1], verts[4] } };
7429   const int conn_len = dim+1;
7430   Range elems;
7431   for (int i = 0; i < 2; ++i) {
7432     EntityHandle h;
7433     rval = mb.create_element( type, conn[i], conn_len, h );
7434     if (MB_SUCCESS != rval) return rval;
7435     elems.insert(h);
7436   }
7437 
7438     // create one reversed side
7439   EntityHandle side_conn[3];
7440   int side_indices[3] = {0,0,0};
7441   CN::SubEntityVertexIndices(type, dim-1, 0, side_indices );
7442   side_conn[0] = conn[0][side_indices[1]];
7443   side_conn[1] = conn[0][side_indices[0]];
7444   side_conn[2] = conn[0][side_indices[2]];
7445   EntityHandle side;
7446   rval = mb.create_element( subtype, side_conn, dim, side );
7447   if (MB_SUCCESS != rval) return rval;
7448 
7449   Range forward, reverse;
7450   Skinner tool(&mb);
7451   rval = tool.find_skin( 0, elems, false, forward, &reverse, use_adj, true );
7452   if (MB_SUCCESS != rval) {
7453     std::cout << "Skinner failed." << std::endl;
7454     return rval;
7455   }
7456 
7457     // expect all faces created by the skinner to be forward,
7458     // so the only reversed side should be the one created above.
7459   if (reverse.size() != 1 || reverse.front() != side) {
7460     std::cout << "Expected 1 reversed side, got: " << reverse.size() << std::endl;
7461     return MB_FAILURE;
7462   }
7463 
7464   return MB_SUCCESS;
7465 }
mb_skin_faces_reversed_test()7466 ErrorCode mb_skin_faces_reversed_test()
7467   { return mb_skin_reversed_common( 2, false ); }
mb_skin_adj_faces_reversed_test()7468 ErrorCode mb_skin_adj_faces_reversed_test()
7469   { return mb_skin_reversed_common( 2, true ); }
mb_skin_regions_reversed_test()7470 ErrorCode mb_skin_regions_reversed_test()
7471   { return mb_skin_reversed_common( 3, false ); }
mb_skin_adj_regions_reversed_test()7472 ErrorCode mb_skin_adj_regions_reversed_test()
7473   { return mb_skin_reversed_common( 3, true ); }
7474 
7475 
mb_skin_subset_common(int dimension,bool use_adj)7476 ErrorCode mb_skin_subset_common( int dimension, bool use_adj )
7477 {
7478   EntityType type;
7479   switch (dimension) {
7480     case 2: type = MBTRI; break;
7481     case 3: type = MBPRISM; break;
7482     default: assert(false); return MB_FAILURE;
7483   }
7484 
7485 
7486   /*      0
7487          /|\
7488         / | \
7489        5  |  1
7490        |\ | /|
7491        | \|/ |
7492        |  6  |
7493        | /|\ |
7494        |/ | \|
7495        4  |  2
7496         \ | /
7497          \|/
7498           3
7499    */
7500 
7501   ErrorCode rval;
7502   Core moab;
7503   Interface& mb = moab;
7504   Range expected_verts;
7505 
7506   const double coords2D[7][2] = { {0,2}, {1,1}, {1,-1}, {0,-2}, {-1,-1}, {-1,1}, {0,0} };
7507   EntityHandle verts[2][7] = { {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0} };
7508   for (int d = 1; d < dimension; ++d) {
7509     for (int i = 0; i < 7; ++i) {
7510       double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast<double>(d-1) };
7511       rval = mb.create_vertex( coords, verts[d-1][i] );
7512       if (MB_SUCCESS != rval) return rval;
7513       if (i != 4 && i != 5)
7514         expected_verts.insert( verts[d-1][i] );
7515     }
7516   }
7517 
7518   EntityHandle elems[6];
7519   for (int i = 0; i < 6; ++i) {
7520     EntityHandle conn[6] = { verts[0][6], verts[0][(i+1)%6], verts[0][i],
7521                                verts[1][6], verts[1][(i+1)%6], verts[1][i] };
7522     rval = mb.create_element( type, conn, CN::VerticesPerEntity(type), elems[i] );
7523     if (MB_SUCCESS != rval) return rval;
7524   }
7525 
7526   Range input;
7527   input.insert( elems[0] );
7528   input.insert( elems[1] );
7529   input.insert( elems[2] );
7530 
7531   Range skin;
7532   Skinner tool(&mb);
7533   rval = tool.find_skin( 0, input, true, skin, 0, use_adj, false );
7534   if (MB_SUCCESS != rval) {
7535     std::cout << "Skinner failed to find skin vertices" << std::endl;
7536     return MB_FAILURE;
7537   }
7538   if (skin != expected_verts) {
7539     std::cout << "Skinner returned incorrect skin vertices" << std::endl;
7540     return MB_FAILURE;
7541   }
7542   int n = 0;
7543   mb.get_number_entities_by_dimension( 0, dimension-1, n );
7544   if (n > 0) {
7545     std::cout << "Skinner created lower-dimension entities for vertex-only skinning" << std::endl;
7546     return MB_FAILURE;
7547   }
7548 
7549   std::vector<EntityHandle> sv( skin.begin(), skin.end() );
7550   std::vector<int> counts( sv.size(), 0 );
7551   skin.clear();
7552   rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
7553   if (MB_SUCCESS != rval) {
7554     std::cout << "Skinner failed to find skin elements" << std::endl;
7555     return MB_FAILURE;
7556   }
7557   for (Range::iterator i = skin.begin(); i != skin.end(); ++i) {
7558     const EntityHandle *conn;
7559     int len;
7560     rval = mb.get_connectivity( *i, conn, len );
7561     if (MB_SUCCESS != rval) return rval;
7562     for (int j = 0; j < len; ++j) {
7563       size_t idx = std::find(sv.begin(), sv.end(), conn[j]) - sv.begin();
7564       if (idx == sv.size()) {
7565         std::cout << "Skinner returned non-skin element" << std::endl;
7566         return MB_FAILURE;
7567       }
7568       counts[idx]++;
7569     }
7570   }
7571   for (size_t i = 0; i < counts.size(); ++i) {
7572     if (counts[i] < dimension) { // 2 for dim==2, {3,4,5} for dim==3
7573       std::cout << "Skinner did not return all skin elements" << std::endl;
7574       return MB_FAILURE;
7575     }
7576   }
7577   mb.get_number_entities_by_dimension( 0, dimension-1, n );
7578   if ((size_t)n != skin.size()) {
7579     std::cout << "Skinner created extra lower-dimension entities" << std::endl;
7580     return MB_FAILURE;
7581   }
7582 
7583   return MB_SUCCESS;
7584 }
7585 
mb_skin_faces_subset_test()7586 ErrorCode mb_skin_faces_subset_test()
7587   { return mb_skin_subset_common( 2, false ); }
mb_skin_adj_faces_subset_test()7588 ErrorCode mb_skin_adj_faces_subset_test()
7589   { return mb_skin_subset_common( 2, true ); }
mb_skin_regions_subset_test()7590 ErrorCode mb_skin_regions_subset_test()
7591   { return mb_skin_subset_common( 3, false ); }
mb_skin_adj_regions_subset_test()7592 ErrorCode mb_skin_adj_regions_subset_test()
7593   { return mb_skin_subset_common( 3, true ); }
7594 
7595 
7596 
7597 
mb_skin_full_common(int dimension,bool use_adj)7598 ErrorCode mb_skin_full_common( int dimension, bool use_adj )
7599 {
7600   EntityType type;
7601   switch (dimension) {
7602     case 2: type = MBQUAD; break;
7603     case 3: type = MBHEX; break;
7604     default: assert(false); return MB_FAILURE;
7605   }
7606 
7607 
7608   /*
7609       3----4----5
7610       |    |    |
7611       |    |    |
7612       0----1----2
7613   */
7614 
7615   ErrorCode rval;
7616   Core moab;
7617   Interface& mb = moab;
7618 
7619     // create vertices
7620   const double coords2D[6][2] = { {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1} };
7621   EntityHandle v[2][6] = { {0,0,0,0,0,0}, {0,0,0,0,0,0} };
7622   for (int d = 1; d < dimension; ++d) {
7623     for (int i = 0; i < 6; ++i) {
7624       double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast<double>(d-1) };
7625       rval = mb.create_vertex( coords, v[d-1][i] );
7626       if (MB_SUCCESS != rval) return rval;
7627     }
7628   }
7629 
7630     // create elements
7631   Range input;
7632   EntityHandle elems[2], econn[2][8];;
7633   for (int i = 0; i < 2; ++i) {
7634     EntityHandle conn[8] = { v[0][i], v[0][i+1], v[0][i+4], v[0][i+3],
7635                                v[1][i], v[1][i+1], v[1][i+4], v[1][i+3] };
7636     memcpy( econn[i], conn, sizeof(conn) );
7637     rval = mb.create_element( type, conn, CN::VerticesPerEntity(type), elems[i] );
7638     if (MB_SUCCESS != rval) return rval;
7639     input.insert( elems[i] );
7640   }
7641 
7642     // create sides
7643     // NOTE: Shared side is element 0 side 1 and element 1 side 3
7644   Range expected;
7645   for (int i = 0; i < CN::NumSubEntities( type, dimension-1 ); ++i) {
7646     EntityType subtype;
7647     int len;
7648     const short* indices = CN::SubEntityVertexIndices( type, dimension-1,
7649                                                          i, subtype, len );
7650     EntityHandle conn[4];
7651     assert((size_t)len <= sizeof(conn)/sizeof(conn[0]));
7652     for (int j = 0; j < 2; ++j) {
7653       if (j == 1 && i == 3) // don't create shared face twice
7654         continue;
7655       for (int k = 0; k < len; ++k)
7656         conn[k] = econn[j][indices[k]];
7657       EntityHandle h;
7658       rval = mb.create_element( subtype, conn, len, h );
7659       if (MB_SUCCESS != rval) return rval;
7660       if (j != 0 || i != 1) // don't insert shared face
7661         expected.insert(h);
7662     }
7663   }
7664 
7665   Range skin;
7666   Skinner tool(&mb);
7667   rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
7668   if (MB_SUCCESS != rval) {
7669     std::cout << "Skinner failed to find skin elements" << std::endl;
7670     return MB_FAILURE;
7671   }
7672   if (skin != expected) {
7673     std::cout << "Skinner returned incorrect skin elements" << std::endl;
7674     return MB_FAILURE;
7675   }
7676 
7677   int n = 0;
7678   mb.get_number_entities_by_dimension( 0, dimension-1, n );
7679   if ((size_t)n != expected.size()+1) {
7680     std::cout << "Skinner created extra lower-dimension entities" << std::endl;
7681     return MB_FAILURE;
7682   }
7683 
7684   return MB_SUCCESS;
7685 }
7686 
mb_skin_faces_full_test()7687 ErrorCode mb_skin_faces_full_test()
7688   { return mb_skin_full_common( 2, false ); }
mb_skin_adj_faces_full_test()7689 ErrorCode mb_skin_adj_faces_full_test()
7690   { return mb_skin_full_common( 2, true ); }
mb_skin_regions_full_test()7691 ErrorCode mb_skin_regions_full_test()
7692   { return mb_skin_full_common( 3, false ); }
mb_skin_adj_regions_full_test()7693 ErrorCode mb_skin_adj_regions_full_test()
7694   { return mb_skin_full_common( 3, true ); }
7695 
mb_skin_adjacent_surf_patches()7696 ErrorCode mb_skin_adjacent_surf_patches()
7697 {
7698   Core moab;
7699   Interface& mb = moab;
7700   ErrorCode rval;
7701   Skinner tool(&mb);
7702 
7703   /* Mesh with vertices and quads numbered.
7704      Groups are indicated by letters {A,B,C,D}
7705 
7706      0----1----2----3----4----5
7707      | (0)| (1)| (2)| (3)| (4)|
7708      |  A |  A |  B |  B |  B |
7709      6----7----8----9---10---11
7710      | (5)| (6)| (7)| (8)| (9)|
7711      |  A |  A |  A |  B |  B |
7712     12---13---14---15---16---17
7713      |(10)|(11)|(12)|(13)|(14)|
7714      |  A |  C |  D |  D |  D |
7715     18---19---20---21---22---23
7716      |(15)|(16)|(17)|(18)|(19)|
7717      |  C |  C |  C |  D |  D |
7718     24---25---26---27---28---29
7719   */
7720 
7721   const int num_vtx = 30;
7722   EntityHandle vtx[num_vtx];
7723   for (int i = 0; i < 6; ++i) {
7724     for (int j = 0; j < 5; ++j) {
7725       double coords[3] = {static_cast<double>(i), static_cast<double>(j), 0};
7726       rval = mb.create_vertex( coords, vtx[6*j+i] );
7727       if (MB_SUCCESS != rval) return rval;
7728     }
7729   }
7730 
7731   EntityHandle quads[20];
7732   for (int i = 0; i < 5; ++i) {
7733     for (int j = 0; j < 4; ++j) {
7734       int v = 6*j+i;
7735       EntityHandle conn[4] = { vtx[v+6], vtx[v+7], vtx[v+1], vtx[v+0] };
7736       rval = mb.create_element( MBQUAD, conn, 4, quads[5*j+i] );
7737       if (MB_SUCCESS != rval) return rval;
7738     }
7739   }
7740 
7741     // Define four groups of quads (as labeled above)
7742   const int Aquads[] = { 0, 1, 5, 6, 7, 10 };
7743   const int Aquads_size = sizeof(Aquads)/sizeof(Aquads[0]);
7744   const int Bquads[] = { 2, 3, 4, 8, 9 };
7745   const int Bquads_size = sizeof(Bquads)/sizeof(Bquads[0]);
7746   const int Cquads[] = { 11, 15, 16, 17 };
7747   const int Cquads_size = sizeof(Cquads)/sizeof(Cquads[0]);
7748   const int Dquads[] = { 12, 13, 14, 18, 19 };
7749   const int Dquads_size = sizeof(Dquads)/sizeof(Dquads[0]);
7750 
7751     // Define the results we expect for each group as a loop
7752     // of vertex indices
7753   const int Askin[] =   { 0, 1, 2, 8, 9, 15, 14, 13, 19, 18, 12, 6 };
7754   const int Ashared[] = {-1,-1, 1, 1, 1,  3,  2,  2,  2, -1, -1,-1 };
7755   const int Askin_size = sizeof(Askin)/sizeof(Askin[0]);
7756   const int Bskin[] =   { 2, 3, 4, 5, 11, 17, 16, 15, 9, 8 };
7757   const int Bshared[] = {-1,-1,-1,-1, -1,  3,  3,  0, 0, 0 };
7758   const int Bskin_size = sizeof(Bskin)/sizeof(Bskin[0]);
7759   const int Cskin[] =   { 18, 19, 13, 14, 20, 21, 27, 26, 25, 24 };
7760   const int Cshared[] = {  0,  0,  0,  3,  3,  3, -1, -1, -1, -1 };
7761   const int Cskin_size = sizeof(Cskin)/sizeof(Cskin[0]);
7762   const int Dskin[] =   { 14, 15, 16, 17, 23, 29, 28, 27, 21, 20 };
7763   const int Dshared[] = {  0,  1,  1, -1, -1, -1, -1,  2,  2,  2 };
7764   const int Dskin_size = sizeof(Dskin)/sizeof(Dskin[0]);
7765 
7766     // Make the above stuff indexable for easier looping
7767   const int* const gquads[4] = { Aquads, Bquads, Cquads, Dquads };
7768   const int gquads_size[4] = { Aquads_size, Bquads_size, Cquads_size, Dquads_size };
7769   const int* const skin[4] = { Askin, Bskin, Cskin, Dskin };
7770   const int* const shared[4] = { Ashared, Bshared, Cshared, Dshared };
7771   const int skin_size[4] = { Askin_size, Bskin_size, Cskin_size, Dskin_size };
7772 
7773     // Create an Range for each group of quads
7774   Range ranges[4];
7775   for (int grp = 0; grp < 4; ++grp)
7776     for (int i = 0; i < gquads_size[grp]; ++i)
7777       ranges[grp].insert( quads[gquads[grp][i]] );
7778 
7779     // run test 4 times, one for each of:
7780     // o no adjacencies, no edges
7781     // o no adjacencies, edges
7782     // o adjacencies, edges
7783     // o adjacencies, no edges
7784     //
7785     // Be careful here: once we specify use_adj, we can't
7786     // unspecify it (the adjacencies will exist so the skinner
7787     // will use them, regardless of the passed flag.)
7788   int error_count = 0;
7789   for (int run = 0; run < 4; ++run) {
7790     const bool use_adj = run > 1;
7791     if (run == 3) {
7792       Range dead;
7793       mb.get_entities_by_type( 0, MBEDGE, dead );
7794       mb.delete_entities( dead );
7795     }
7796 
7797       // test each group
7798     Range edges[4];
7799     for (int grp = 0; grp < 4; ++grp) {
7800         // get the skin edges
7801       rval = tool.find_skin( 0, ranges[grp], 1, edges[grp], use_adj );
7802       if (MB_SUCCESS != rval) {
7803         std::cout << "Skinner failed for run " << run << " group " << grp << std::endl;
7804         return rval;
7805       }
7806 
7807         // check that we have the expected result
7808       std::vector<bool> seen(skin_size[grp], false);
7809       for (Range::iterator e = edges[grp].begin(); e != edges[grp].end(); ++e) {
7810         const EntityHandle* conn;
7811         int len;
7812         rval = mb.get_connectivity( *e, conn, len );
7813         if (MB_SUCCESS != rval) return rval;
7814         if (len != 2) return MB_FAILURE;
7815         const int idx1 = std::find( vtx, vtx+num_vtx, conn[0] ) - vtx;
7816         const int idx2 = std::find( vtx, vtx+num_vtx, conn[1] ) - vtx;
7817         int pos = std::find( skin[grp], skin[grp]+skin_size[grp], idx1 ) - skin[grp];
7818         if (pos == skin_size[grp]) {
7819           std::cout << "Non-skin vertex in skin for run " << run << " group " << grp << std::endl;
7820           std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7821           ++error_count;
7822           continue;
7823         }
7824 
7825 
7826         if (skin[grp][(pos+skin_size[grp]-1)%skin_size[grp]] == idx2)
7827           pos = (pos + skin_size[grp] - 1)%skin_size[grp];
7828         else if (skin[grp][(pos+1)%skin_size[grp]] != idx2) {
7829           std::cout << "Non-skin edge in skin for run " << run << " group " << grp << std::endl;
7830           std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7831           ++error_count;
7832           continue;
7833         }
7834 
7835         if (seen[pos]) {
7836           std::cout << "Duplicate edge in skin for run " << run << " group " << grp << std::endl;
7837           std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7838           ++error_count;
7839         }
7840         seen[pos] = true;
7841 
7842         int shared_with = shared[grp][pos];
7843         if (shared_with < 0) // not shared with another group
7844           continue;
7845         if (shared_with > grp) // didn't skin other group yet
7846           continue;
7847         if (edges[shared_with].find(*e) == edges[shared_with].end()) {
7848           std::cout << "Skin edge duplicated for run " << run << " group " << grp << std::endl;
7849           std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2
7850                     << " not in skin for group " << shared_with << std::endl;
7851           ++error_count;
7852         }
7853       }
7854 
7855       int missing = std::count( seen.begin(), seen.end(), false );
7856       if (missing) {
7857         std::cout << "Missking " << missing << " skin edges for run " << run << " group " << grp << std::endl;
7858         error_count += missing;
7859       }
7860     }
7861   }
7862 
7863   return error_count ? MB_FAILURE : MB_SUCCESS;
7864 }
7865 
7866 
get_by_all_types_and_tag(Interface * mb,EntityHandle meshset,const Tag * tag_handles,const void * const * values,int num_tags,Range & result,int condition,bool recursive)7867 static ErrorCode get_by_all_types_and_tag( Interface* mb,
7868                                            EntityHandle meshset,
7869                                            const Tag* tag_handles,
7870                                            const void* const* values,
7871                                            int num_tags,
7872                                            Range& result,
7873                                            int condition,
7874                                            bool recursive )
7875 {
7876   ErrorCode rval;
7877   Range tmp;
7878   const EntityType LAST = recursive ? MBENTITYSET : MBMAXTYPE;
7879   for (EntityType t = MBVERTEX; t < LAST; ++t) {
7880     tmp.clear();
7881     rval = mb->get_entities_by_type_and_tag( meshset, t, tag_handles, values, num_tags, tmp, condition, recursive );
7882     if (MB_SUCCESS != rval)
7883       return rval;
7884     result.insert( tmp.begin(), tmp.end() );
7885   }
7886   return MB_SUCCESS;
7887 }
7888 
7889 
7890 /** Check that functions which accept a type return the
7891  *  result for all types when passed MBMAXTYPE
7892  */
mb_type_is_maxtype_test()7893 ErrorCode mb_type_is_maxtype_test()
7894 {
7895   Core moab;
7896   Interface* mb = &moab;
7897   ErrorCode rval = create_some_mesh( mb );
7898   if (MB_SUCCESS != rval)
7899     return rval;
7900 
7901   Range r1, r2;
7902   rval = mb->get_entities_by_type( 0, MBMAXTYPE, r1, false ); MB_CHK_ERR(rval);
7903   rval = mb->get_entities_by_handle( 0, r2, false ); MB_CHK_ERR(rval);
7904   CHECK( r1 == r2 );
7905 
7906   std::vector<EntityHandle> v1, v2;
7907   rval = mb->get_entities_by_type( 0, MBMAXTYPE, v1, false ); MB_CHK_ERR(rval);
7908   rval = mb->get_entities_by_handle( 0, v2, false ); MB_CHK_ERR(rval);
7909   CHECK( v1 == v2 );
7910 
7911   int c1, c2;
7912   rval = mb->get_number_entities_by_type( 0, MBMAXTYPE, c1, false ); MB_CHK_ERR(rval);
7913   rval = mb->get_number_entities_by_handle( 0, c2, false ); MB_CHK_ERR(rval);
7914   CHECK( c1 == c2 );
7915 
7916   Range h1, h2;
7917   Range::iterator it = r1.begin() + r1.size()/2;
7918   h1.insert( r1.begin(), it );
7919   if (it != r1.end())
7920     h2.insert( ++it, r1.end() );
7921 
7922   EntityHandle s1, s2;
7923   rval = mb->create_meshset( MESHSET_SET, s1 ); MB_CHK_ERR(rval);
7924   rval = mb->create_meshset( MESHSET_ORDERED, s2 ); MB_CHK_ERR(rval);
7925   rval = mb->add_entities( s1, r1 ); MB_CHK_ERR(rval);
7926   rval = mb->add_entities( s2, r2 ); MB_CHK_ERR(rval);
7927   rval = mb->add_entities( s2, &s1, 1 ); MB_CHK_ERR(rval);
7928 
7929   r1.clear();
7930   r2.clear();
7931   rval = mb->get_entities_by_type( s1, MBMAXTYPE, r1, false ); MB_CHK_ERR(rval);
7932   rval = mb->get_entities_by_handle( s1, r2, false ); MB_CHK_ERR(rval);
7933   CHECK( r1 == r2 );
7934 
7935   r1.clear();
7936   r2.clear();
7937   rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, false ); MB_CHK_ERR(rval);
7938   rval = mb->get_entities_by_handle( s2, r2, false ); MB_CHK_ERR(rval);
7939   CHECK( r1 == r2 );
7940 
7941   r1.clear();
7942   r2.clear();
7943   rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, true ); MB_CHK_ERR(rval);
7944   rval = mb->get_entities_by_handle( s2, r2, true ); MB_CHK_ERR(rval);
7945   CHECK( r1 == r2 );
7946 
7947 
7948   v1.clear();
7949   v2.clear();
7950   rval = mb->get_entities_by_type( s1, MBMAXTYPE, v1, false ); MB_CHK_ERR(rval);
7951   rval = mb->get_entities_by_handle( s1, v2, false ); MB_CHK_ERR(rval);
7952   CHECK( v1 == v2 );
7953 
7954   v1.clear();
7955   v2.clear();
7956   rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, false ); MB_CHK_ERR(rval);
7957   rval = mb->get_entities_by_handle( s2, v2, false ); MB_CHK_ERR(rval);
7958   CHECK( v1 == v2 );
7959 
7960   v1.clear();
7961   v2.clear();
7962   rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, true ); MB_CHK_ERR(rval);
7963   rval = mb->get_entities_by_handle( s2, v2, true ); MB_CHK_ERR(rval);
7964   CHECK( v1 == v2 );
7965 
7966 
7967   rval = mb->get_number_entities_by_type( s1, MBMAXTYPE, c1, false ); MB_CHK_ERR(rval);
7968   rval = mb->get_number_entities_by_handle( s1, c2, false ); MB_CHK_ERR(rval);
7969   CHECK( c1 == c2 );
7970 
7971   rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, false ); MB_CHK_ERR(rval);
7972   rval = mb->get_number_entities_by_handle( s2, c2, false ); MB_CHK_ERR(rval);
7973   CHECK( c1 == c2 );
7974 
7975   rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, true ); MB_CHK_ERR(rval);
7976   rval = mb->get_number_entities_by_handle( s2, c2, true ); MB_CHK_ERR(rval);
7977   CHECK( c1 == c2 );
7978 
7979   r1.clear();
7980   rval = mb->get_entities_by_handle( s1, r1 ); MB_CHK_ERR(rval);
7981   Tag t1;
7982   rval = mb->tag_get_handle( "maxtype1", 1, MB_TYPE_INTEGER, t1, MB_TAG_SPARSE|MB_TAG_EXCL );
7983   MB_CHK_ERR(rval);
7984   std::vector<int> d1(r1.size());
7985   Range::iterator ri;
7986   std::vector<int>::iterator ii = d1.begin();
7987   for (ri = r1.begin(); ri != r1.end(); ++ri, ++ii)
7988     *ii = ((int)ID_FROM_HANDLE(*ri)) % 20;
7989   rval = mb->tag_set_data( t1, r1, &d1[0] ); MB_CHK_ERR(rval);
7990 
7991   r1.clear(); r2.clear();
7992   rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
7993   rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
7994   rval = get_by_all_types_and_tag( mb, 0, &t1, 0, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
7995   CHECK( r1 == r2 );
7996   CHECK( (unsigned)c1 == r2.size() );
7997 
7998   r1.clear(); r2.clear();
7999   rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8000   rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8001   rval = get_by_all_types_and_tag( mb, s1, &t1, 0, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8002   CHECK( r1 == r2 );
8003   CHECK( (unsigned)c1 == r2.size() );
8004 
8005   r1.clear(); r2.clear();
8006   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8007   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8008   rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8009   CHECK( r1 == r2 );
8010   CHECK( (unsigned)c1 == r2.size() );
8011 
8012   r1.clear(); r2.clear();
8013   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8014   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8015   rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8016   CHECK( r1 == r2 );
8017   CHECK( (unsigned)c1 == r2.size() );
8018 
8019   int value = 3;
8020   const void* vallist[2] = { &value, 0 };
8021 
8022   r1.clear(); r2.clear();
8023   rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8024   rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8025   rval = get_by_all_types_and_tag( mb, 0, &t1, vallist, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8026   CHECK( r1 == r2 );
8027   CHECK( (unsigned)c1 == r2.size() );
8028 
8029   r1.clear(); r2.clear();
8030   rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8031   rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8032   rval = get_by_all_types_and_tag( mb, s1, &t1, vallist, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8033   CHECK( r1 == r2 );
8034   CHECK( (unsigned)c1 == r2.size() );
8035 
8036   r1.clear(); r2.clear();
8037   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8038   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8039   rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8040   CHECK( r1 == r2 );
8041   CHECK( (unsigned)c1 == r2.size() );
8042 
8043   r1.clear(); r2.clear();
8044   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8045   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8046   rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8047   CHECK( r1 == r2 );
8048   CHECK( (unsigned)c1 == r2.size() );
8049 
8050   r1.clear(); r2.clear();
8051   rval = mb->get_entities_by_handle( s1, r1 ); MB_CHK_ERR(rval);
8052   r2.insert( r1.back() );
8053   r1.clear();
8054   rval = mb->get_entities_by_handle( s2, r1 ); MB_CHK_ERR(rval);
8055   r2.insert( r1.front() );
8056 
8057   Tag t2;
8058   rval = mb->tag_get_handle( "maxtype2", 1, MB_TYPE_INTEGER, t2, MB_TAG_DENSE|MB_TAG_EXCL );
8059   MB_CHK_ERR(rval);
8060   d1.resize(r2.size());
8061   ii = d1.begin();;
8062   for (ri = r2.begin(); ri != r2.end(); ++ri, ++ii)
8063     *ii = ((int)ID_FROM_HANDLE(*ri)) % 2;
8064   rval = mb->tag_set_data( t2, r2, &d1[0] ); MB_CHK_ERR(rval);
8065 
8066   Tag tags[] = { t1, t2 };
8067 
8068   r1.clear(); r2.clear();
8069   rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8070   rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8071   rval = get_by_all_types_and_tag( mb, 0, tags, 0, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8072   CHECK( r1 == r2 );
8073   CHECK( (unsigned)c1 == r2.size() );
8074 
8075   r1.clear(); r2.clear();
8076   rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8077   rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8078   rval = get_by_all_types_and_tag( mb, s1, tags, 0, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8079   CHECK( r1 == r2 );
8080   CHECK( (unsigned)c1 == r2.size() );
8081 
8082   r1.clear(); r2.clear();
8083   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8084   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8085   rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8086   CHECK( r1 == r2 );
8087   CHECK( (unsigned)c1 == r2.size() );
8088 
8089   r1.clear(); r2.clear();
8090   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8091   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8092   rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8093   CHECK( r1 == r2 );
8094   CHECK( (unsigned)c1 == r2.size() );
8095 
8096   int val2 = 1;
8097   vallist[1] = &val2;
8098 
8099   r1.clear(); r2.clear();
8100   rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8101   rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8102   rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8103   CHECK( r1 == r2 );
8104   CHECK( (unsigned)c1 == r2.size() );
8105 
8106   r1.clear(); r2.clear();
8107   rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8108   rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8109   rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8110   CHECK( r1 == r2 );
8111   CHECK( (unsigned)c1 == r2.size() );
8112 
8113   r1.clear(); r2.clear();
8114   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8115   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8116   rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, false ); MB_CHK_ERR(rval);
8117   CHECK( r1 == r2 );
8118   CHECK( (unsigned)c1 == r2.size() );
8119 
8120   r1.clear(); r2.clear();
8121   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8122   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8123   rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, true ); MB_CHK_ERR(rval);
8124   CHECK( r1 == r2 );
8125   CHECK( (unsigned)c1 == r2.size() );
8126 
8127   r1.clear(); r2.clear();
8128   rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false ); MB_CHK_ERR(rval);
8129   rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false ); MB_CHK_ERR(rval);
8130   rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::UNION, false ); MB_CHK_ERR(rval);
8131   CHECK( r1 == r2 );
8132   CHECK( (unsigned)c1 == r2.size() );
8133 
8134   r1.clear(); r2.clear();
8135   rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false ); MB_CHK_ERR(rval);
8136   rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false ); MB_CHK_ERR(rval);
8137   rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::UNION, false ); MB_CHK_ERR(rval);
8138   CHECK( r1 == r2 );
8139   CHECK( (unsigned)c1 == r2.size() );
8140 
8141   r1.clear(); r2.clear();
8142   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false ); MB_CHK_ERR(rval);
8143   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false ); MB_CHK_ERR(rval);
8144   rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, false ); MB_CHK_ERR(rval);
8145   CHECK( r1 == r2 );
8146   CHECK( (unsigned)c1 == r2.size() );
8147 
8148   r1.clear(); r2.clear();
8149   rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, true ); MB_CHK_ERR(rval);
8150   rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, true ); MB_CHK_ERR(rval);
8151   rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, true ); MB_CHK_ERR(rval);
8152   CHECK( r1 == r2 );
8153   CHECK( (unsigned)c1 == r2.size() );
8154 
8155   return MB_SUCCESS;
8156 }
8157 
8158 /** Test behavior of various functions when passed the root set
8159  */
mb_root_set_test()8160 ErrorCode mb_root_set_test()
8161 {
8162   ErrorCode rval;
8163   Core moab;
8164   Interface* mb = &moab;
8165   EntityHandle rs = mb->get_root_set();
8166 
8167     // expect root set to have zero handle
8168   CHECK(!rs);
8169 
8170     // check type
8171   EntityType type = mb->type_from_handle( rs );
8172   CHECK( MBENTITYSET == type );
8173 
8174     // Create a set to test with
8175   EntityHandle some_set;
8176   rval = mb->create_meshset( MESHSET_SET, some_set );
8177   MB_CHK_ERR( rval );
8178   Range sets;
8179   sets.insert( some_set );
8180 
8181   int exp_dim = mb->dimension_from_handle( some_set );
8182   int dim = mb->dimension_from_handle( rs );
8183   CHECK( exp_dim == dim );
8184 
8185     // test some stuff that should fail
8186   rval = mb->clear_meshset( &rs, 1 );
8187   CHECK( MB_SUCCESS != rval );
8188   rval = mb->set_meshset_options( rs, MESHSET_ORDERED );
8189   CHECK( MB_SUCCESS != rval );
8190   rval = mb->subtract_meshset( rs, some_set );
8191   CHECK( MB_SUCCESS != rval );
8192   rval = mb->intersect_meshset( rs, some_set );
8193   CHECK( MB_SUCCESS != rval );
8194   rval = mb->unite_meshset( rs, some_set );
8195   CHECK( MB_SUCCESS != rval );
8196 
8197     // add/remove should fail for root set?
8198   rval = mb->add_entities( rs, &some_set, 1 );
8199   CHECK( MB_SUCCESS != rval );
8200   rval = mb->remove_entities( rs, &some_set, 1 );
8201   CHECK( MB_SUCCESS != rval );
8202   rval = mb->replace_entities( rs, &some_set, &some_set, 1 );
8203   CHECK( MB_SUCCESS != rval );
8204 
8205     // check flags
8206   unsigned flags;
8207   rval = mb->get_meshset_options( rs, flags );
8208   CHECK( flags & MESHSET_SET );
8209   CHECK( !(flags & MESHSET_ORDERED) );
8210   CHECK( flags & MESHSET_TRACK_OWNER );
8211 
8212     // contains tests
8213   bool c = mb->contains_entities( rs, &some_set, 1 );
8214   CHECK( c );
8215 
8216   Range sets2;
8217   rval = mb->get_contained_meshsets( rs, sets2 );
8218   MB_CHK_ERR(rval);
8219   CHECK( sets == sets2 );
8220 
8221   int count;
8222   rval = mb->num_contained_meshsets( rs, &count );
8223   MB_CHK_ERR(rval);
8224   CHECK( count == (int)sets.size() );
8225 
8226     // The expected behavior for parent/child queries on the root set
8227     // is to return an error.
8228 
8229   rval = mb->get_parent_meshsets( rs, sets2 );
8230   CHECK( MB_SUCCESS != rval );
8231   rval = mb->get_parent_meshsets( rs, sets2, 2 );
8232   CHECK( MB_SUCCESS != rval );
8233 
8234   rval = mb->get_child_meshsets( rs, sets2 );
8235   CHECK( MB_SUCCESS != rval );
8236   rval = mb->get_child_meshsets( rs, sets2, 2 );
8237   CHECK( MB_SUCCESS != rval );
8238 
8239   rval = mb->num_parent_meshsets( rs, &count );
8240   CHECK( MB_SUCCESS != rval );
8241   rval = mb->num_parent_meshsets( rs, &count, 2 );
8242   CHECK( MB_SUCCESS != rval );
8243 
8244   rval = mb->num_child_meshsets( rs, &count );
8245   CHECK( MB_SUCCESS != rval );
8246   rval = mb->num_child_meshsets( rs, &count, 2 );
8247   CHECK( MB_SUCCESS != rval );
8248 
8249   rval = mb->add_parent_meshset( rs, some_set );
8250   CHECK(MB_SUCCESS != rval);
8251   rval = mb->add_parent_meshsets( rs, &some_set, 1 );
8252   CHECK(MB_SUCCESS != rval);
8253   rval = mb->add_child_meshset( rs, some_set );
8254   CHECK(MB_SUCCESS != rval);
8255   rval = mb->add_child_meshsets( rs, &some_set, 1 );
8256   CHECK(MB_SUCCESS != rval);
8257   rval = mb->add_parent_child( rs, some_set );
8258   CHECK(MB_SUCCESS != rval);
8259   rval = mb->remove_parent_child( rs, some_set );
8260   CHECK(MB_SUCCESS != rval);
8261   rval = mb->remove_parent_meshset( rs, some_set );
8262   CHECK(MB_SUCCESS != rval);
8263   rval = mb->remove_child_meshset( rs, some_set );
8264   CHECK(MB_SUCCESS != rval);
8265 
8266   return MB_SUCCESS;
8267 }
8268 
8269 
8270 /* Create a regular 2x2x2 hex mesh */
create_some_mesh(Interface * iface)8271 ErrorCode create_some_mesh( Interface* iface )
8272 {
8273   const double coords[] = { 0, 0, 0,
8274                             1, 0, 0,
8275                             2, 0, 0,
8276                             0, 1, 0,
8277                             1, 1, 0,
8278                             2, 1, 0,
8279                             0, 2, 0,
8280                             1, 2, 0,
8281                             2, 2, 0,
8282                             0, 0, 1,
8283                             1, 0, 1,
8284                             2, 0, 1,
8285                             0, 1, 1,
8286                             1, 1, 1,
8287                             2, 1, 1,
8288                             0, 2, 1,
8289                             1, 2, 1,
8290                             2, 2, 1,
8291                             0, 0, 2,
8292                             1, 0, 2,
8293                             2, 0, 2,
8294                             0, 1, 2,
8295                             1, 1, 2,
8296                             2, 1, 2,
8297                             0, 2, 2,
8298                             1, 2, 2,
8299                             2, 2, 2 };
8300   const size_t num_vtx = sizeof(coords)/sizeof(double)/3;
8301   assert(num_vtx == 27u);
8302 
8303   const int conn[] = {  0,  1,  4,  3,  9, 10, 13, 12,
8304                         1,  2,  5,  4, 10, 11, 14, 13,
8305                         3,  4,  7,  6, 12, 13, 16, 15,
8306                         4,  5,  8,  9, 13, 14, 17, 16,
8307                         9, 10, 13, 12, 18, 19, 22, 21,
8308                        10, 11, 14, 13, 19, 20, 23, 22,
8309                        12, 13, 16, 15, 21, 22, 25, 24,
8310                        13, 14, 17, 18, 22, 23, 26, 25 };
8311   const size_t num_elem = sizeof(conn)/sizeof(conn[0])/8;
8312   assert(num_elem == 8u);
8313 
8314   EntityHandle verts[num_vtx], hexes[num_elem];
8315   for (size_t i = 0; i < num_vtx; ++i) {
8316     ErrorCode err = iface->create_vertex( coords + 3*i, verts[i] );
8317     if (MB_SUCCESS != err) return err;
8318   }
8319 
8320   for (size_t i = 0; i < num_elem; ++i) {
8321     EntityHandle c[8];
8322     for (int j = 0; j < 8; ++j) {
8323       assert(conn[8*i+j] < (int)num_vtx);
8324       c[j] = verts[conn[8*i+j]];
8325     }
8326     ErrorCode err = iface->create_element( MBHEX, c, 8, hexes[i] );
8327     if (MB_SUCCESS != err) return err;
8328   }
8329 
8330   return MB_SUCCESS;
8331 }
8332 
contained(const std::vector<EntityHandle> & list,EntityHandle h)8333 inline bool contained( const std::vector<EntityHandle>& list, EntityHandle h )
8334 {
8335   std::vector<EntityHandle>::const_iterator i;
8336   i = std::lower_bound( list.begin(), list.end(), h );
8337   return i != list.end() && *i == h;
8338 }
8339 
check_valid_connectivity(Interface * iface)8340 ErrorCode check_valid_connectivity( Interface* iface )
8341 {
8342   ErrorCode rval;
8343 
8344   // get sorted array of vertex handles so that we can
8345   // check that all vertices in connectivity are valid
8346   // handles
8347   std::vector<EntityHandle> vertices, storage;
8348   rval = iface->get_entities_by_type( 0, MBVERTEX, vertices ); MB_CHK_ERR(rval);
8349   std::sort( vertices.begin(), vertices.end() );
8350 
8351   // get all the elements
8352   Range elements, tmp;
8353   for (int d = 1; d < 4; ++d) {
8354     tmp.clear();
8355     rval = iface->get_entities_by_dimension( 0, d, tmp ); MB_CHK_ERR(rval);
8356     elements.merge(tmp);
8357   }
8358 
8359   // check that all connectivity handles are valid
8360   Range::iterator it;
8361   ErrorCode result = MB_SUCCESS;
8362   for (it = elements.begin(); it != elements.end(); ++it) {
8363     const EntityHandle* conn;
8364     int len;
8365     rval = iface->get_connectivity( *it, conn, len, false, &storage ); MB_CHK_ERR(rval);
8366     for (int i = 0; i < len; ++i) {
8367       if (!contained( vertices, conn[i] )) {
8368         printf("Invalid handle (%s %d) in connectivity of %s %d\n",
8369           CN::EntityTypeName(TYPE_FROM_HANDLE(conn[i])),
8370           (int)ID_FROM_HANDLE(conn[i]),
8371           CN::EntityTypeName(TYPE_FROM_HANDLE(*it)),
8372           (int)ID_FROM_HANDLE(*it));
8373         result = MB_FAILURE;
8374       }
8375     }
8376   }
8377 
8378   return result;
8379 }
8380 
8381 
usage(const char * exe)8382 static void usage(const char* exe) {
8383   cerr << "Usage: " << exe << " [-nostress] [-d input_file_dir]\n";
8384   exit (1);
8385 }
8386 
8387 
8388 int number_tests = 0;
8389 int number_tests_failed = 0;
8390 #define RUN_TEST_ERR( A ) _run_test( (A), #A )
8391 
8392 typedef ErrorCode (*TestFunc)();
_run_test(TestFunc func,const char * func_str)8393 static int _run_test( TestFunc func, const char* func_str )
8394 {
8395   ++number_tests;
8396   return run_test ( func, func_str );
8397 }
8398 
8399 
8400 /*!
8401   main routine for test harness
8402 */
main(int argc,char * argv[])8403 int main(int argc, char* argv[])
8404 {
8405 #ifdef MOAB_HAVE_MPI
8406   int fail = MPI_Init(&argc, &argv);
8407   if (fail) return fail;
8408 #endif
8409 
8410   argv0 = argv[0];
8411 
8412     // Check command line arg to see if we should avoid doing the stress test
8413 #ifdef MOAB_HAVE_NETCDF
8414   bool stress_test = true;
8415 #endif
8416 
8417   std::cout << "Size of mConnMap = " << sizeof(CN::mConnectivityMap)
8418             << std::endl;
8419   std::cout << "Size of mUpConnMap = " << sizeof(CN::mUpConnMap)
8420             << std::endl;
8421   std::cout << "Size of CN = " << sizeof(CN)
8422             << std::endl;
8423 
8424   for (int i = 1; i < argc; ++i) {
8425 
8426     if (string(argv[i]) == "-h" || string(argv[i]) == "--help")
8427       usage( argv[0] );
8428 #if MOAB_HAVE_NETCDF
8429     else if (string(argv[i]) == "-nostress")
8430       stress_test = false;
8431 #endif
8432     else {
8433       cerr << "Invalid argument: " << argv[i] << endl;
8434       usage( argv[0] );
8435     }
8436   }
8437 
8438     // Print out Header information
8439 
8440   cout << "\n\nMOAB Comprehensive test suite:\n\n";
8441 
8442   number_tests = number_tests_failed = 0;
8443   number_tests_failed += RUN_TEST_ERR( mb_adjacent_vertex_test );
8444   number_tests_failed += RUN_TEST_ERR( mb_adjacencies_create_delete_test );
8445   number_tests_failed += RUN_TEST_ERR( mb_upward_adjacencies_test );
8446   number_tests_failed += RUN_TEST_ERR( mb_adjacent_create_test );
8447   number_tests_failed += RUN_TEST_ERR( mb_vertex_coordinate_test );
8448   number_tests_failed += RUN_TEST_ERR( mb_vertex_tag_test );
8449   number_tests_failed += RUN_TEST_ERR( mb_temporary_test );
8450   number_tests_failed += RUN_TEST_ERR( mb_mesh_sets_set_test );
8451   number_tests_failed += RUN_TEST_ERR( mb_mesh_sets_list_test );
8452   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_parent_child_test );
8453   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_appends );
8454   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_list_appends );
8455   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_root_appends );
8456   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_replace_test );
8457   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_list_replace_test );
8458   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_flag_test );
8459   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_add_remove_test );
8460   number_tests_failed += RUN_TEST_ERR( mb_dense_tag_test );
8461   number_tests_failed += RUN_TEST_ERR( mb_sparse_tag_test );
8462   number_tests_failed += RUN_TEST_ERR( mb_higher_order_test );
8463   number_tests_failed += RUN_TEST_ERR( mb_bit_tags_test );
8464 #if MOAB_HAVE_NETCDF
8465   number_tests_failed += RUN_TEST_ERR( mb_adjacencies_test );
8466   number_tests_failed += RUN_TEST_ERR( mb_tags_test );
8467   number_tests_failed += RUN_TEST_ERR( mb_delete_mesh_test );
8468   number_tests_failed += RUN_TEST_ERR( mb_entity_conversion_test );
8469   number_tests_failed += RUN_TEST_ERR( mb_mesh_set_tracking_test );
8470 #endif
8471   number_tests_failed += RUN_TEST_ERR( mb_forced_adjacencies_test );
8472   number_tests_failed += RUN_TEST_ERR( mb_canon_number_test );
8473   number_tests_failed += RUN_TEST_ERR(mb_side_number_test);
8474   number_tests_failed += RUN_TEST_ERR( mb_poly_test );
8475   number_tests_failed += RUN_TEST_ERR( mb_topo_util_test );
8476   number_tests_failed += RUN_TEST_ERR( mb_split_test );
8477   number_tests_failed += RUN_TEST_ERR( mb_range_seq_intersect_test );
8478   number_tests_failed += RUN_TEST_ERR( mb_poly_adjacency_test );
8479   number_tests_failed += RUN_TEST_ERR( mb_poly_adjacency_test2 );
8480   number_tests_failed += RUN_TEST_ERR( mb_memory_use_test );
8481   number_tests_failed += RUN_TEST_ERR( mb_skin_curve_test );
8482   number_tests_failed += RUN_TEST_ERR( mb_skin_curve_adj_test );
8483   number_tests_failed += RUN_TEST_ERR( mb_skin_surface_test );
8484   number_tests_failed += RUN_TEST_ERR( mb_skin_surface_adj_test );
8485   number_tests_failed += RUN_TEST_ERR( mb_skin_volume_test );
8486   number_tests_failed += RUN_TEST_ERR( mb_skin_volume_adj_test );
8487   number_tests_failed += RUN_TEST_ERR( mb_skin_surf_verts_test );
8488   number_tests_failed += RUN_TEST_ERR( mb_skin_vol_verts_test );
8489   number_tests_failed += RUN_TEST_ERR( mb_skin_surf_verts_elems_test );
8490   number_tests_failed += RUN_TEST_ERR( mb_skin_vol_verts_elems_test );
8491   number_tests_failed += RUN_TEST_ERR( mb_skin_poly_test );
8492   number_tests_failed += RUN_TEST_ERR( mb_skin_higher_order_faces_test );
8493   number_tests_failed += RUN_TEST_ERR( mb_skin_higher_order_regions_test );
8494   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_higher_order_faces_test );
8495   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_higher_order_regions_test );
8496   number_tests_failed += RUN_TEST_ERR( mb_skin_faces_reversed_test );
8497   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_reversed_test );
8498   number_tests_failed += RUN_TEST_ERR( mb_skin_regions_reversed_test );
8499   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_reversed_test );
8500   number_tests_failed += RUN_TEST_ERR( mb_skin_faces_subset_test );
8501   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_subset_test );
8502   number_tests_failed += RUN_TEST_ERR( mb_skin_regions_subset_test );
8503   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_subset_test );
8504   number_tests_failed += RUN_TEST_ERR( mb_skin_faces_full_test );
8505   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_full_test );
8506   number_tests_failed += RUN_TEST_ERR( mb_skin_regions_full_test );
8507   number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_full_test );
8508   number_tests_failed += RUN_TEST_ERR( mb_skin_adjacent_surf_patches );
8509   number_tests_failed += RUN_TEST_ERR( mb_skin_scd_test );
8510   number_tests_failed += RUN_TEST_ERR( mb_skin_fileset_test );
8511   number_tests_failed += RUN_TEST_ERR( mb_read_fail_test );
8512   number_tests_failed += RUN_TEST_ERR( mb_enum_string_test );
8513   number_tests_failed += RUN_TEST_ERR( mb_merge_update_test );
8514   number_tests_failed += RUN_TEST_ERR( mb_type_is_maxtype_test );
8515   number_tests_failed += RUN_TEST_ERR( mb_root_set_test );
8516 #if MOAB_HAVE_NETCDF
8517   number_tests_failed += RUN_TEST_ERR( mb_merge_test );
8518   if (stress_test) number_tests_failed += RUN_TEST_ERR( mb_stress_test );
8519 #endif
8520 
8521     // summary
8522 
8523   cout << "\nMB TEST SUMMARY: \n"
8524        << "   Number Tests:           " << number_tests << "\n"
8525        << "   Number Successful:      " << number_tests - number_tests_failed << "\n"
8526        << "   Number Failed:          " << number_tests_failed
8527        << "\n\n";
8528 
8529 #ifdef MOAB_HAVE_MPI
8530   fail = MPI_Finalize();
8531   if (fail) return fail;
8532 #endif
8533 
8534   return number_tests_failed;
8535 }
8536