1 #include "SequenceManager.hpp"
2 #include "VertexSequence.hpp"
3 #include "UnstructuredElemSeq.hpp"
4 #include "ScdVertexData.hpp"
5 #include "MeshSetSequence.hpp"
6 #include "SweptElementSeq.hpp"
7 #include "StructuredElementSeq.hpp"
8 #include "moab/HomXform.hpp"
9 #include "PolyElementSeq.hpp"
10 #include "SysUtil.hpp"
11 #include "moab/Error.hpp"
12 
13 #include <assert.h>
14 #include <new>
15 #include <algorithm>
16 
17 #ifndef NDEBUG
18 #include <iostream>
19 #endif
20 
21 namespace moab {
22 
23 const EntityID SequenceManager::DEFAULT_VERTEX_SEQUENCE_SIZE = 512 * 1024;
24 const EntityID SequenceManager::DEFAULT_ELEMENT_SEQUENCE_SIZE = DEFAULT_VERTEX_SEQUENCE_SIZE;
25 const EntityID SequenceManager::DEFAULT_POLY_SEQUENCE_SIZE = 16 * 1024;
26 const EntityID SequenceManager::DEFAULT_MESHSET_SEQUENCE_SIZE = DEFAULT_VERTEX_SEQUENCE_SIZE;
27 
28 const int UNUSED_SIZE = 0;
29 
default_poly_sequence_size(int conn_len)30 EntityID SequenceManager::default_poly_sequence_size(int conn_len)
31 {
32   return std::max(DEFAULT_POLY_SEQUENCE_SIZE / conn_len, (EntityID)1);
33 }
34 
~SequenceManager()35 SequenceManager::~SequenceManager()
36 {
37   // Release variable-length tag data
38   for (unsigned i = 0; i < tagSizes.size(); ++i)
39     if (tagSizes[i] == MB_VARIABLE_LENGTH)
40       release_tag_array(0, i, false);
41 }
42 
clear()43 void SequenceManager::clear()
44 {
45   // reset sequence multiplier
46   sequence_multiplier = 1.0;
47 
48   // Destroy all TypeSequenceManager instances
49   for (EntityType t = MBVERTEX; t < MBMAXTYPE; ++t)
50     typeData[t].~TypeSequenceManager();
51 
52   // Now re-create TypeSequenceManager instances
53   for (EntityType t = MBVERTEX; t < MBMAXTYPE; ++t)
54     new (typeData + t)TypeSequenceManager();
55 }
56 
get_entities(Range & entities_out) const57 void SequenceManager::get_entities(Range& entities_out) const
58 {
59   for (EntityType t = MBENTITYSET; t >= MBVERTEX; --t)
60     typeData[t].get_entities(entities_out);
61 }
62 
get_entities(std::vector<EntityHandle> & entities_out) const63 void SequenceManager::get_entities(std::vector<EntityHandle>& entities_out) const
64 {
65   for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
66     typeData[t].get_entities(entities_out);
67 }
68 
get_number_entities() const69 EntityID SequenceManager::get_number_entities() const
70 {
71   EntityID sum = 0;
72   for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
73     sum += typeData[t].get_number_entities();
74 
75   return sum;
76 }
77 
check_valid_entities(Error *,const Range & entities) const78 ErrorCode SequenceManager::check_valid_entities(Error* /* error */,
79                                                 const Range& entities) const
80 {
81   ErrorCode rval;
82   Range::const_pair_iterator i;
83   for (i = entities.const_pair_begin(); i != entities.const_pair_end(); ++i) {
84     const EntityType type1 = TYPE_FROM_HANDLE(i->first);
85     const EntityType type2 = TYPE_FROM_HANDLE(i->second);
86     if (type1 == type2) {
87       rval = typeData[type1].check_valid_handles(NULL, i->first, i->second);
88       if (MB_SUCCESS != rval)
89         return rval;
90     }
91     else {
92       int junk;
93       EntityHandle split = CREATE_HANDLE(type2, 0, junk);
94       rval = typeData[type1].check_valid_handles(NULL, i->first, split - 1);
95       if (MB_SUCCESS != rval)
96         return rval;
97       rval = typeData[type2].check_valid_handles(NULL, split, i->second);
98       if (MB_SUCCESS != rval)
99         return rval;
100     }
101   }
102 
103   return MB_SUCCESS;
104 }
105 
check_valid_entities(Error *,const EntityHandle * entities,size_t num_entities,bool root_set_okay) const106 ErrorCode SequenceManager::check_valid_entities(Error* /* error_handler */,
107                                                 const EntityHandle* entities,
108                                                 size_t num_entities,
109                                                 bool root_set_okay) const
110 {
111   ErrorCode rval;
112   const EntitySequence* ptr = 0;
113 
114   const EntityHandle* const end = entities + num_entities;
115   for (; entities < end; ++entities) {
116     rval = find(*entities, ptr);
117     if (MB_SUCCESS != rval && !(root_set_okay && !*entities)) {
118       if (MB_ENTITY_NOT_FOUND == rval) {
119         // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
120 #       if 0
121         fprintf(stderr, "[Warning]: Invalid entity handle: 0x%lx\n", (unsigned long)*entities);
122 #       endif
123       }
124       return rval;
125     }
126   }
127 
128   return MB_SUCCESS;
129 }
130 
delete_entity(Error *,EntityHandle entity)131 ErrorCode SequenceManager::delete_entity(Error* /* error */, EntityHandle entity)
132 {
133   return typeData[TYPE_FROM_HANDLE(entity)].erase(NULL, entity);
134 }
135 
delete_entities(Error *,const Range & entities)136 ErrorCode SequenceManager::delete_entities(Error* /* error */, const Range& entities)
137 {
138   ErrorCode rval = check_valid_entities(NULL, entities);
139   if (MB_SUCCESS != rval)
140     return rval;
141 
142   ErrorCode result = MB_SUCCESS;
143   Range::const_pair_iterator i;
144   for (i = entities.const_pair_begin(); i != entities.const_pair_end(); ++i) {
145     const EntityType type1 = TYPE_FROM_HANDLE(i->first);
146     const EntityType type2 = TYPE_FROM_HANDLE(i->second);
147     if (type1 == type2) {
148       rval = typeData[type1].erase(NULL, i->first, i->second);
149       if (MB_SUCCESS != rval)
150         return result = rval;
151     }
152     else {
153       int junk;
154       EntityHandle split = CREATE_HANDLE(type2, 0, junk);
155       rval = typeData[type1].erase(NULL, i->first, split - 1);
156       if (MB_SUCCESS != rval)
157         return result = rval;
158       rval = typeData[type2].erase(NULL, split, i->second);
159       if (MB_SUCCESS != rval)
160         return result = rval;
161     }
162   }
163 
164   return result;
165 }
166 
create_vertex(const double coords[3],EntityHandle & handle)167 ErrorCode SequenceManager::create_vertex(const double coords[3],
168                                          EntityHandle& handle)
169 {
170   const EntityHandle start = CREATE_HANDLE(MBVERTEX, MB_START_ID);
171   const EntityHandle   end = CREATE_HANDLE(MBVERTEX,   MB_END_ID);
172   bool append;
173   TypeSequenceManager::iterator seq = typeData[MBVERTEX].find_free_handle(start, end, append);
174   VertexSequence* vseq;
175 
176   if (seq == typeData[MBVERTEX].end()) {
177     SequenceData* seq_data = 0;
178     EntityID seq_data_size = 0;
179     handle = typeData[MBVERTEX].find_free_sequence(DEFAULT_VERTEX_SEQUENCE_SIZE, start, end, seq_data, seq_data_size);
180     if (!handle)
181       return MB_FAILURE;
182 
183     if (seq_data)
184       vseq = new VertexSequence(handle, 1, seq_data);
185     else
186       vseq = new VertexSequence(handle, 1, DEFAULT_VERTEX_SEQUENCE_SIZE);
187 
188     ErrorCode rval = typeData[MBVERTEX].insert_sequence(vseq);
189     if (MB_SUCCESS != rval) {
190       SequenceData* vdata = vseq->data();
191       delete vseq;
192       if (!seq_data)
193         delete vdata;
194 
195       return rval;
196     }
197   }
198   else {
199     vseq = reinterpret_cast<VertexSequence*>(*seq);
200     if (append) {
201       vseq->push_back(1);
202       handle = vseq->end_handle();
203       typeData[MBVERTEX].notify_appended(seq);
204     }
205     else {
206       vseq->push_front(1);
207       handle = vseq->start_handle();
208       typeData[MBVERTEX].notify_prepended(seq);
209     }
210   }
211 
212   return vseq->set_coordinates(handle, coords);
213 }
214 
create_element(EntityType type,const EntityHandle * conn,unsigned conn_len,EntityHandle & handle)215 ErrorCode SequenceManager::create_element(EntityType type,
216                                           const EntityHandle* conn,
217                                           unsigned conn_len,
218                                           EntityHandle& handle)
219 {
220   if (type <= MBVERTEX || type >= MBENTITYSET)
221     return MB_TYPE_OUT_OF_RANGE;
222 
223   const EntityHandle start = CREATE_HANDLE(type, MB_START_ID);
224   const EntityHandle   end = CREATE_HANDLE(type,   MB_END_ID);
225   bool append;
226   TypeSequenceManager::iterator seq = typeData[type].find_free_handle(start, end, append, conn_len);
227   UnstructuredElemSeq* eseq;
228 
229   if (seq == typeData[type].end()) {
230     SequenceData* seq_data = 0;
231     unsigned size = DEFAULT_ELEMENT_SEQUENCE_SIZE;
232     if (type == MBPOLYGON || type == MBPOLYHEDRON) {
233       size = default_poly_sequence_size(conn_len);
234     }
235     EntityID seq_data_size = 0;
236     handle = typeData[type].find_free_sequence(size, start, end, seq_data, seq_data_size, conn_len);
237     if (!handle)
238       return MB_FAILURE;
239 
240     if (MBPOLYGON == type || MBPOLYHEDRON == type) {
241       if (seq_data)
242         eseq = new PolyElementSeq(handle, 1, conn_len, seq_data);
243       else
244         eseq = new PolyElementSeq(handle, 1, conn_len, size);
245     }
246     else {
247       if (seq_data)
248         eseq = new UnstructuredElemSeq(handle, 1, conn_len, seq_data);
249       else
250         eseq = new UnstructuredElemSeq(handle, 1, conn_len, size);
251     }
252 
253     ErrorCode rval = typeData[type].insert_sequence(eseq);
254     if (MB_SUCCESS != rval) {
255       SequenceData* vdata = eseq->data();
256       delete eseq;
257       if (!seq_data)
258         delete vdata;
259 
260       return rval;
261     }
262   }
263   else {
264     eseq = reinterpret_cast<UnstructuredElemSeq*>(*seq);
265     if (append) {
266       eseq->push_back(1);
267       handle = eseq->end_handle();
268       typeData[type].notify_appended(seq);
269     }
270     else {
271       eseq->push_front(1);
272       handle = eseq->start_handle();
273       typeData[type].notify_prepended(seq);
274     }
275   }
276 
277   return eseq->set_connectivity(handle, conn, conn_len);
278 }
279 
create_mesh_set(unsigned flags,EntityHandle & handle)280 ErrorCode SequenceManager::create_mesh_set(unsigned flags,
281                                            EntityHandle& handle)
282 {
283   const EntityHandle start = CREATE_HANDLE(MBENTITYSET, MB_START_ID);
284   const EntityHandle   end = CREATE_HANDLE(MBENTITYSET,   MB_END_ID);
285   bool append;
286   TypeSequenceManager::iterator seq = typeData[MBENTITYSET].find_free_handle(start, end, append);
287   MeshSetSequence* msseq;
288 
289   if (seq == typeData[MBENTITYSET].end()) {
290     SequenceData* seq_data = 0;
291     EntityID seq_data_size = 0;
292     handle = typeData[MBENTITYSET].find_free_sequence(DEFAULT_MESHSET_SEQUENCE_SIZE, start, end, seq_data, seq_data_size);
293     if (!handle)
294       return MB_FAILURE;
295 
296     if (seq_data)
297       msseq = new MeshSetSequence(handle, 1, flags, seq_data);
298     else
299       msseq = new MeshSetSequence(handle, 1, flags, DEFAULT_MESHSET_SEQUENCE_SIZE);
300 
301     ErrorCode rval = typeData[MBENTITYSET].insert_sequence(msseq);
302     if (MB_SUCCESS != rval) {
303       SequenceData* vdata = msseq->data();
304       delete msseq;
305       if (!seq_data)
306         delete vdata;
307 
308       return rval;
309     }
310   }
311   else {
312     msseq = reinterpret_cast<MeshSetSequence*>(*seq);
313     if (append) {
314       msseq->push_back(1, &flags);
315       handle = msseq->end_handle();
316       typeData[MBENTITYSET].notify_appended(seq);
317     }
318     else {
319       msseq->push_front(1, &flags);
320       handle = msseq->start_handle();
321       typeData[MBENTITYSET].notify_prepended(seq);
322     }
323   }
324 
325   return MB_SUCCESS;
326 }
327 
allocate_mesh_set(EntityHandle handle,unsigned flags)328 ErrorCode SequenceManager::allocate_mesh_set(EntityHandle handle,
329                                              unsigned flags)
330 {
331   SequenceData* data = 0;
332   TypeSequenceManager::iterator seqptr;
333   EntityHandle block_start = 1, block_end = 0;
334   ErrorCode rval = typeData[MBENTITYSET].is_free_handle(handle, seqptr, data, block_start, block_end);
335   if (MB_SUCCESS != rval)
336     return rval;
337 
338   MeshSetSequence* seq;
339   if (seqptr != typeData[MBENTITYSET].end()) {
340     seq = static_cast<MeshSetSequence*>(*seqptr);
341     if (seq->start_handle() - 1 == handle) {
342       rval = seq->push_front(1, &flags);
343       if (MB_SUCCESS == rval) {
344         rval = typeData[MBENTITYSET].notify_prepended(seqptr);
345         if (MB_SUCCESS != rval)
346           seq->pop_front(1);
347       }
348       return rval;
349     }
350     else if (seq->end_handle() + 1 == handle) {
351       rval = seq->push_back(1, &flags);
352       if (MB_SUCCESS == rval) {
353         rval = typeData[MBENTITYSET].notify_appended(seqptr);
354         if (MB_SUCCESS != rval)
355           seq->pop_back(1);
356       }
357       return rval;
358     }
359     else
360       return MB_FAILURE; // Should be unreachable
361   }
362   else {
363     if (data) {
364       seq = new MeshSetSequence(handle, 1, flags, data);
365     }
366     else {
367       assert(handle >= block_start && handle <= block_end);
368       trim_sequence_block(handle, block_end, DEFAULT_MESHSET_SEQUENCE_SIZE);
369       seq = new MeshSetSequence(handle, 1, flags, block_end - handle + 1);
370     }
371 
372     rval = typeData[MBENTITYSET].insert_sequence(seq);
373     if (MB_SUCCESS != rval) {
374       SequenceData* vdata = seq->data();
375       delete seq;
376       if (!data)
377         delete vdata;
378       return rval;
379     }
380 
381     return MB_SUCCESS;
382   }
383 }
384 
trim_sequence_block(EntityHandle start_handle,EntityHandle & end_handle,unsigned max_size)385 void SequenceManager::trim_sequence_block(EntityHandle start_handle,
386                                           EntityHandle& end_handle,
387                                           unsigned max_size)
388 {
389   assert(end_handle >= start_handle);
390   assert((int)max_size > 0); // Cast to int also prohibits some ridiculously large values
391 
392   // If input range is larger than preferred size, trim it
393   if (end_handle - start_handle >= max_size)
394     end_handle = start_handle + max_size - 1;
395 }
396 
sequence_start_handle(EntityType type,EntityID count,int size,EntityID start,SequenceData * & data,EntityID & data_size)397 EntityHandle SequenceManager::sequence_start_handle(EntityType type,
398                                                     EntityID count,
399                                                     int size,
400                                                     EntityID start,
401                                                     SequenceData*& data,
402                                                     EntityID &data_size)
403 {
404   TypeSequenceManager &tsm = typeData[type];
405   data = 0;
406   EntityHandle handle = CREATE_HANDLE(type, start);
407   if (start < MB_START_ID ||
408       !tsm.is_free_sequence(handle, count, data, size)) {
409     EntityHandle pstart = CREATE_HANDLE(type, MB_START_ID);
410     EntityHandle pend   = CREATE_HANDLE(type,   MB_END_ID);
411     handle = tsm.find_free_sequence(count, pstart, pend, data, data_size, size);
412   }
413 
414   return handle;
415 }
416 
new_sequence_size(EntityHandle start,EntityID requested_size,int sequence_size) const417 EntityID SequenceManager::new_sequence_size(EntityHandle start,
418                                             EntityID requested_size,
419                                             int sequence_size) const
420 {
421 
422   requested_size = (EntityID) (this->sequence_multiplier*requested_size);
423 
424   if (sequence_size < (int)requested_size)
425     return requested_size;
426 
427   EntityHandle last = typeData[TYPE_FROM_HANDLE(start)].last_free_handle(start);
428   if (!last) {
429     assert(false);
430     return 0;
431   }
432 
433   EntityID available_size = last - start + 1;
434   if (sequence_size < available_size)
435     return sequence_size;
436   else
437     return available_size;
438 }
439 
create_entity_sequence(EntityType type,EntityID count,int size,EntityID start,EntityHandle & handle,EntitySequence * & sequence,int sequence_size)440 ErrorCode SequenceManager::create_entity_sequence(EntityType type,
441                                                   EntityID count,
442                                                   int size,
443                                                   EntityID start,
444                                                   EntityHandle& handle,
445                                                   EntitySequence*& sequence,
446                                                   int sequence_size)
447 {
448   SequenceData* data = NULL;
449   EntityID data_size = 0;
450   handle = sequence_start_handle(type, count, size, start, data, data_size);
451 
452   if (!handle)
453     return MB_MEMORY_ALLOCATION_FAILED;
454 
455   switch (type) {
456   case MBENTITYSET:
457   case MBMAXTYPE:
458     return MB_TYPE_OUT_OF_RANGE;
459 
460   case MBVERTEX:
461     if (size != 0)
462       return MB_INDEX_OUT_OF_RANGE;
463 
464     if (data)
465       sequence = new VertexSequence(handle, count, data);
466     else {
467       if (!data_size)
468         data_size = new_sequence_size(handle, count, sequence_size);
469       sequence = new VertexSequence(handle, count, data_size);
470     }
471     break;
472 
473   case MBPOLYGON:
474   case MBPOLYHEDRON:
475     if (size == 0)
476       return MB_INDEX_OUT_OF_RANGE;
477 
478     if (data)
479       sequence = new PolyElementSeq(handle, count, size, data);
480     else {
481       if (!data_size)
482         data_size = new_sequence_size(handle, count,
483                                       (-1 == sequence_size ? default_poly_sequence_size(size) :
484                                        sequence_size));
485       sequence = new PolyElementSeq(handle, count, size, data_size);
486     }
487     break;
488 
489   default:
490     if (size == 0)
491       return MB_INDEX_OUT_OF_RANGE;
492 
493     if (data)
494       sequence = new UnstructuredElemSeq(handle, count, size, data);
495     else {
496       if (!data_size)
497         data_size = new_sequence_size(handle, count, sequence_size);
498       sequence = new UnstructuredElemSeq(handle, count, size, data_size);
499     }
500     // tjt calling new_sequence_size 'cuz don't have a sequence data;
501     // start 41467, count 246
502     break;
503   }
504 
505   ErrorCode result = typeData[type].insert_sequence(sequence);
506   if (MB_SUCCESS != result) {
507     // Change to NULL if had an existing data or if no existing data,
508     // change to the new data created
509     data = data ? 0 : sequence->data();
510     delete sequence;
511     delete data;
512     return result;
513   }
514 
515   return MB_SUCCESS;
516 }
517 
create_meshset_sequence(EntityID count,EntityID start,const unsigned * flags,EntityHandle & handle,EntitySequence * & sequence)518 ErrorCode SequenceManager::create_meshset_sequence(EntityID count,
519                                                    EntityID start,
520                                                    const unsigned* flags,
521                                                    EntityHandle& handle,
522                                                    EntitySequence*& sequence)
523 {
524   SequenceData* data = 0;
525   EntityID data_size = 0;
526   handle = sequence_start_handle(MBENTITYSET, count, 0, start, data, data_size);
527 
528   if (!handle)
529     return MB_MEMORY_ALLOCATION_FAILED;
530 
531   if (data)
532     sequence = new MeshSetSequence(handle, count, flags, data);
533   else
534     sequence = new MeshSetSequence(handle, count, flags, count);
535 
536   ErrorCode result = typeData[MBENTITYSET].insert_sequence(sequence);
537   if (MB_SUCCESS != result) {
538     // Change to NULL if had an existing data or if no existing data,
539     // change to the new data created
540     data = data ? 0 : sequence->data();
541     delete sequence;
542     delete data;
543     return result;
544   }
545 
546   return MB_SUCCESS;
547 }
548 
create_meshset_sequence(EntityID count,EntityID start,unsigned flags,EntityHandle & handle,EntitySequence * & sequence)549 ErrorCode SequenceManager::create_meshset_sequence(EntityID count,
550                                                    EntityID start,
551                                                    unsigned flags,
552                                                    EntityHandle& handle,
553                                                    EntitySequence*& sequence)
554 {
555   SequenceData* data = 0;
556   EntityID data_size = 0;
557   handle = sequence_start_handle(MBENTITYSET, count, 0, start, data, data_size);
558   if (!handle)
559     return MB_MEMORY_ALLOCATION_FAILED;
560 
561   if (data)
562     sequence = new MeshSetSequence(handle, count, flags, data);
563   else
564     sequence = new MeshSetSequence(handle, count, flags, count);
565 
566   ErrorCode result = typeData[MBENTITYSET].insert_sequence(sequence);
567   if (MB_SUCCESS != result) {
568     // Change to NULL if had an existing data or if no existing data,
569     // change to the new data created
570     data = data ? 0 : sequence->data();
571     delete sequence;
572     delete data;
573     return result;
574   }
575 
576   return MB_SUCCESS;
577 }
578 
create_scd_sequence(int imin,int jmin,int kmin,int imax,int jmax,int kmax,EntityType type,EntityID start_id_hint,EntityHandle & handle,EntitySequence * & sequence,int * is_periodic)579 ErrorCode SequenceManager::create_scd_sequence(int imin, int jmin, int kmin,
580                                                int imax, int jmax, int kmax,
581                                                EntityType type,
582                                                EntityID start_id_hint,
583                                                EntityHandle& handle,
584                                                EntitySequence*& sequence,
585                                                int *is_periodic)
586 {
587   int this_dim = CN::Dimension(type);
588 
589   // Use > instead of != in the following assert to also catch cases where imin > imax, etc.
590   assert((this_dim < 3 || kmax > kmin) &&
591          (this_dim < 2 || jmax > jmin) &&
592          (this_dim < 1 || imax > imin));
593 
594   // Compute # entities; not as easy as it would appear...
595   EntityID num_ent;
596   if (MBVERTEX == type)
597     num_ent = (EntityID)(imax - imin + 1) * (EntityID)(jmax - jmin + 1) * (EntityID)(kmax - kmin + 1);
598   else {
599     num_ent = (imax-imin + (is_periodic && is_periodic[0] ? 1 : 0)) *
600       (this_dim >= 2 ? (jmax - jmin + (is_periodic && is_periodic[1] ? 1 : 0)) : 1) *
601       (this_dim >= 3 ? (kmax - kmin) : 1);
602   }
603 
604   if (MBVERTEX == type && (is_periodic && (is_periodic[0] || is_periodic[1])))
605     return MB_FAILURE;
606 
607   // Get a start handle
608   SequenceData* data = 0;
609   EntityID data_size = 0;
610   handle = sequence_start_handle(type, num_ent, -1, start_id_hint, data, data_size);
611 
612   if (!handle)
613     return MB_MEMORY_ALLOCATION_FAILED;
614   assert(!data);
615 
616   switch (type) {
617   case MBVERTEX:
618     data = new ScdVertexData(handle, imin, jmin, kmin, imax, jmax, kmax);
619     sequence = new VertexSequence(handle, data->size(), data);
620     break;
621   case MBEDGE:
622   case MBQUAD:
623   case MBHEX:
624       sequence = new StructuredElementSeq(handle, imin, jmin, kmin, imax, jmax, kmax,
625                                           is_periodic);
626     break;
627   default:
628     return MB_TYPE_OUT_OF_RANGE;
629   }
630 
631   ErrorCode result = typeData[type].insert_sequence(sequence);
632   if (MB_SUCCESS != result) {
633     data = sequence->data();
634     delete sequence;
635     delete data;
636     return result;
637   }
638 
639   return MB_SUCCESS;
640 }
641 
create_scd_sequence(const HomCoord & coord_min,const HomCoord & coord_max,EntityType type,EntityID start_id_hint,EntityHandle & first_handle_out,EntitySequence * & sequence_out,int * is_periodic)642 ErrorCode SequenceManager::create_scd_sequence(const HomCoord& coord_min,
643                                                const HomCoord& coord_max,
644                                                EntityType type,
645                                                EntityID start_id_hint,
646                                                EntityHandle& first_handle_out,
647                                                EntitySequence*& sequence_out,
648                                                int *is_periodic)
649 {
650   return create_scd_sequence(coord_min.i(), coord_min.j(), coord_min.k(),
651                              coord_max.i(), coord_max.j(), coord_max.k(),
652                              type, start_id_hint,
653                              first_handle_out, sequence_out, is_periodic);
654 }
655 
create_sweep_sequence(int imin,int jmin,int kmin,int imax,int jmax,int kmax,int * Cq,EntityType type,EntityID start_id_hint,EntityHandle & handle,EntitySequence * & sequence)656 ErrorCode SequenceManager::create_sweep_sequence(int imin, int jmin, int kmin,
657                                                  int imax, int jmax, int kmax,
658                                                  int* Cq,
659                                                  EntityType type,
660                                                  EntityID start_id_hint,
661                                                  EntityHandle& handle,
662                                                  EntitySequence*& sequence)
663 {
664   int this_dim = CN::Dimension(type);
665 
666   assert((this_dim < 3 || kmax > kmin) &&
667          (this_dim < 2 || jmax > jmin) &&
668          (this_dim < 1 || imax > imin));
669 
670   EntityID num_ent;
671   if (MBVERTEX == type)
672     num_ent = (EntityID)(imax - imin + 1) * (EntityID)(jmax - jmin + 1) * (EntityID)(kmax - kmin + 1);
673   else {
674     num_ent = (imax-imin) *
675       (this_dim >= 2 ? (jmax - jmin) : 1) *
676       (this_dim >= 3 ? (kmax - kmin) : 1);
677   }
678 
679   // Get a start handle
680   SequenceData* data = 0;
681   EntityID data_size = 0;
682   handle = sequence_start_handle(type, num_ent, -1, start_id_hint, data, data_size);
683 
684   if (!handle)
685     return MB_MEMORY_ALLOCATION_FAILED;
686   assert(!data);
687 
688   switch (type) {
689   case MBVERTEX:
690     data = new ScdVertexData(handle, imin, jmin, kmin, imax, jmax, kmax);
691     sequence = new VertexSequence(handle, data->size(), data);
692     break;
693   case MBEDGE:
694   case MBQUAD:
695   case MBHEX:
696     sequence = new SweptElementSeq(handle, imin, jmin, kmin, imax, jmax, kmax, Cq);
697     break;
698   default:
699     return MB_TYPE_OUT_OF_RANGE;
700   }
701 
702   ErrorCode result = typeData[type].insert_sequence(sequence);
703   if (MB_SUCCESS != result) {
704     data = sequence->data();
705     delete sequence;
706     delete data;
707     return result;
708   }
709 
710   return MB_SUCCESS;
711 }
712 
create_sweep_sequence(const HomCoord & coord_min,const HomCoord & coord_max,int * Cq,EntityType type,EntityID start_id_hint,EntityHandle & first_handle_out,EntitySequence * & sequence_out)713 ErrorCode SequenceManager::create_sweep_sequence(const HomCoord& coord_min,
714                                                  const HomCoord& coord_max,
715                                                  int* Cq,
716                                                  EntityType type,
717                                                  EntityID start_id_hint,
718                                                  EntityHandle& first_handle_out,
719                                                  EntitySequence*& sequence_out)
720 {
721   return create_sweep_sequence(coord_min.i(), coord_min.j(), coord_min.k(),
722                                coord_max.i(), coord_max.j(), coord_max.k(),
723                                Cq,
724                                type, start_id_hint,
725                                first_handle_out, sequence_out);
726 }
727 
add_vsequence(EntitySequence * vert_seq,EntitySequence * elem_seq,const HomCoord & p1,const HomCoord & q1,const HomCoord & p2,const HomCoord & q2,const HomCoord & p3,const HomCoord & q3,bool bb_input,const HomCoord * bb_min,const HomCoord * bb_max)728 ErrorCode SequenceManager::add_vsequence(EntitySequence *vert_seq,
729                                          EntitySequence *elem_seq,
730                                          const HomCoord &p1, const HomCoord &q1,
731                                          const HomCoord &p2, const HomCoord &q2,
732                                          const HomCoord &p3, const HomCoord &q3,
733                                          bool bb_input,
734                                          const HomCoord *bb_min,
735                                          const HomCoord *bb_max)
736 {
737   // Check first that they're structured vtx/elem sequences
738   ScdVertexData *scd_vd = dynamic_cast<ScdVertexData*>(vert_seq->data());
739   if (!scd_vd)
740     return MB_FAILURE;
741 
742   ScdElementData *scd_ed = dynamic_cast<ScdElementData*>(elem_seq->data());
743   if (!scd_ed)
744     return MB_FAILURE;
745 
746   if (bb_min && bb_max)
747     return scd_ed->add_vsequence(scd_vd, p1, q1, p2, q2, p3, q3,
748                                  bb_input, *bb_min, *bb_max);
749   else
750     return scd_ed->add_vsequence(scd_vd, p1, q1, p2, q2, p3, q3,
751                                  bb_input, HomCoord::unitv[0], HomCoord::unitv[0]);
752 }
753 
replace_subsequence(EntitySequence * new_seq)754 ErrorCode SequenceManager::replace_subsequence(EntitySequence* new_seq)
755 {
756   const EntityType type = TYPE_FROM_HANDLE(new_seq->start_handle());
757   return typeData[type].replace_subsequence(new_seq, &tagSizes[0], tagSizes.size());
758 }
759 
get_memory_use(unsigned long long & total_entity_storage,unsigned long long & total_storage) const760 void SequenceManager::get_memory_use(unsigned long long& total_entity_storage,
761                                      unsigned long long& total_storage) const
762 
763 {
764   total_entity_storage = 0;
765   total_storage = 0;
766   unsigned long long temp_entity, temp_total;
767   for (EntityType i = MBVERTEX; i < MBMAXTYPE; ++i) {
768     temp_entity = temp_total = 0;
769     get_memory_use(i, temp_entity, temp_total);
770     total_entity_storage += temp_entity;
771     total_storage        += temp_total;
772   }
773 }
774 
get_memory_use(EntityType type,unsigned long long & total_entity_storage,unsigned long long & total_storage) const775 void SequenceManager::get_memory_use(EntityType type,
776                                      unsigned long long& total_entity_storage,
777                                      unsigned long long& total_storage) const
778 {
779   typeData[type].get_memory_use(total_entity_storage, total_storage);
780 }
781 
get_memory_use(const Range & entities,unsigned long long & total_entity_storage,unsigned long long & total_amortized_storage) const782 void SequenceManager::get_memory_use(const Range& entities,
783                                      unsigned long long& total_entity_storage,
784                                      unsigned long long& total_amortized_storage) const
785 {
786   total_entity_storage = 0;
787   total_amortized_storage = 0;
788   unsigned long long temp_entity, temp_total;
789   Range::const_pair_iterator i;
790   for (i = entities.const_pair_begin(); i != entities.const_pair_end(); ++i) {
791     const EntityType t1 = TYPE_FROM_HANDLE(i->first);
792     const EntityType t2 = TYPE_FROM_HANDLE(i->second);
793     if (t1 == t2) {
794       temp_entity = temp_total = 0;
795       typeData[t1].get_memory_use(i->first, i->second, temp_entity, temp_total);
796       total_entity_storage += temp_entity;
797       total_amortized_storage += temp_total;
798     }
799     else {
800       int junk;
801 
802       temp_entity = temp_total = 0;
803       typeData[t1].get_memory_use(i->first, CREATE_HANDLE(t1, MB_END_ID, junk), temp_entity, temp_total);
804       total_entity_storage += temp_entity;
805       total_amortized_storage += temp_total;
806 
807       temp_entity = temp_total = 0;
808       typeData[t2].get_memory_use(CREATE_HANDLE(t2, MB_START_ID, junk), i->second, temp_entity, temp_total);
809       total_entity_storage += temp_entity;
810       total_amortized_storage += temp_total;
811     }
812   }
813 }
814 
reserve_tag_array(Error *,int size,int & index)815 ErrorCode SequenceManager::reserve_tag_array(Error* /* error_handler */,
816                                              int size, int& index)
817 {
818   if (size < 1 && size != MB_VARIABLE_LENGTH) {
819     MB_SET_ERR(MB_INVALID_SIZE, "Invalid tag size: " << size);
820   }
821 
822   std::vector<int>::iterator i = std::find(tagSizes.begin(), tagSizes.end(), UNUSED_SIZE);
823   if (i == tagSizes.end()) {
824     index = tagSizes.size();
825     tagSizes.push_back(size);
826   }
827   else {
828     index = i - tagSizes.begin();
829     *i = size;
830   }
831 
832   return MB_SUCCESS;
833 }
834 
release_tag_array(Error *,int index,bool release_id)835 ErrorCode SequenceManager::release_tag_array(Error* /* error_handler */,
836                                              int index, bool release_id)
837 {
838   if ((unsigned)index >= tagSizes.size() || UNUSED_SIZE == tagSizes[index]) {
839     // MB_TAG_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
840 #if 0
841     fprintf(stderr, "[Warning]: Invalid dense tag index: %d\n", index);
842 #endif
843     return MB_TAG_NOT_FOUND;
844   }
845 
846   for (EntityType t = MBVERTEX; t <= MBENTITYSET; ++t) {
847     TypeSequenceManager& seqs = entity_map(t);
848     for (TypeSequenceManager::iterator i = seqs.begin(); i != seqs.end(); ++i)
849       (*i)->data()->release_tag_data(index, tagSizes[index]);
850   }
851 
852   if (release_id)
853     tagSizes[index] = UNUSED_SIZE;
854 
855   return MB_SUCCESS;
856 }
857 
858 // These are meant to be called from the debugger (not declared in any header)
859 // so leave them out of release builds (-DNDEBUG).
860 #ifndef NDEBUG
861 
operator <<(std::ostream & s,const TypeSequenceManager & seq_man)862 std::ostream& operator<<(std::ostream& s, const TypeSequenceManager& seq_man)
863 {
864   const SequenceData* prev_data = 0;
865   for (TypeSequenceManager::const_iterator i = seq_man.begin(); i != seq_man.end(); ++i) {
866     const EntitySequence* seq = *i;
867     if (seq->data() != prev_data) {
868       prev_data = seq->data();
869       s << "SequenceData ["
870         << ID_FROM_HANDLE(seq->data()->start_handle())
871         << ","
872         << ID_FROM_HANDLE(seq->data()->end_handle())
873         << "]"
874         << std::endl;
875     }
876     s << "  Sequence ["
877       << ID_FROM_HANDLE(seq->start_handle())
878       << ","
879       << ID_FROM_HANDLE(seq->end_handle())
880       << "]"
881       << std::endl;
882   }
883 
884   return s;
885 }
886 
operator <<(std::ostream & s,const SequenceManager & seq_man)887 std::ostream& operator<<(std::ostream& s, const SequenceManager& seq_man)
888 {
889   for (EntityType t = MBVERTEX; t < MBMAXTYPE; ++t) {
890     if (!seq_man.entity_map(t).empty())
891       s << std::endl
892         << "****************** " << CN::EntityTypeName(t) << " ******************"
893         << std::endl << seq_man.entity_map(t) << std::endl;
894   }
895 
896   return s;
897 }
898 
print_sequences(const SequenceManager & seqman)899 void print_sequences(const SequenceManager& seqman)
900 {
901   std::cout << seqman << std::endl;
902 }
903 
print_sequences(const TypeSequenceManager & seqman)904 void print_sequences(const TypeSequenceManager& seqman)
905 {
906   std::cout << seqman << std::endl;
907 }
908 
909 #endif
910 
911 } // namespace moab
912