1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/** MOAB Damsel file reader
 * For description of the Damsel-MOAB data model mapping, see WriteDamsel.cpp.
 *
 */

#include "moab/ParallelComm.hpp"

#include "ReadDamsel.hpp"

#include <cassert>
#include "moab/Interface.hpp"
#include "moab/Core.hpp"
#include "moab/Range.hpp"
#include "moab/Error.hpp"
#include "moab/ReadUtilIface.hpp"
#include "moab/FileOptions.hpp"
#include "MBTagConventions.hpp"
#include "EntitySequence.hpp"
#include "Internals.hpp"
#include "DenseTag.hpp"

namespace moab
{

ReaderIface* ReadDamsel::factory( Interface* iface )
{
    return new ReadDamsel( iface );
}

ReadDamsel::ReadDamsel( Interface* impl )
    : mbImpl( impl ), readMeshIface( NULL ), nativeParallel( false ), myPcomm( NULL ), mGlobalIdTag( 0 ), dU()
{
    init();
}

ReadDamsel::~ReadDamsel()
{
    if( readMeshIface ) mbImpl->release_interface( readMeshIface );

    DMSLlib_finalize( dU.dmslLib );
}

ErrorCode ReadDamsel::init()
{
    mbImpl->query_interface( readMeshIface );
    assert( readMeshIface );

    return MB_SUCCESS;
}

ErrorCode ReadDamsel::parse_options( const FileOptions& opts, bool& parallel )
{
    // Handle parallel options
    bool use_mpio  = ( MB_SUCCESS == opts.get_null_option( "USE_MPIO" ) );
    ErrorCode rval = opts.match_option( "PARALLEL", "READ_PART" );
    parallel       = ( rval != MB_ENTITY_NOT_FOUND );
    nativeParallel = ( rval == MB_SUCCESS );
    if( use_mpio && !parallel )
    {
        MB_SET_ERR( MB_NOT_IMPLEMENTED, "'USE_MPIO' option specified w/out 'PARALLEL' option" );
    }

    return MB_SUCCESS;
}

// ASSUMPTIONS:
// Partition collection is a *flat* collection of handles for entities and other collections that
// will be represented on a part

ErrorCode ReadDamsel::load_file( const char* filename,
                                 const EntityHandle* file_set,
                                 const FileOptions& opts,
                                 const ReaderIface::SubsetList* subset_list,
                                 const Tag* file_id_tag )
{
    ErrorCode rval;

    rval = parse_options( opts, nativeParallel );
    if( MB_SUCCESS != rval ) return rval;

    // Initialize damsel
    dU.dmslLib = DMSLlib_init();

    // Create a damsel model
    dU.dmslModel =
        DMSLmodel_create( sizeof( EntityHandle ) == 8 ? DAMSEL_HANDLE_TYPE_HANDLE64 : DAMSEL_HANDLE_TYPE_HANDLE32 );

    // Model attach - need model id from make model, filename
#ifdef MOAB_HAVE_MPI
    MPI_Comm comm = MPI_COMM_WORLD;
    if( nativeParallel )
    {
        comm = myPcomm->proc_config().proc_comm();
    }
#endif

    damsel_err_t err;
    err = DMSLmodel_attach( dU.dmslModel, filename, comm, NULL );
    CHK_DMSL_ERR( err, "DMSLmodel_attach failed" );
    err = DMSLmodel_populate( dU.dmslModel );
    CHK_DMSL_ERR( err, "DMSLmodel_populate failed" );

    // STEP 0: GET COLLECTION, TAG, ENTITY INFOS FOR GLOBAL MODEL
    int num_containers = 0, num_tag_infos = 0, num_ent_infos = 0;
    DMSLmodel_get_tuple_count( dU.dmslModel, &num_containers, &num_tag_infos );
    num_ent_infos      = DMSLmodel_get_entity_count( dU.dmslModel );
    int num_coll_infos = DMSLmodel_get_collection_count( dU.dmslModel );
    CHK_DMSL_ERR( err, "DMSLmodel_get_collection_count failed" );
    if( -1 == num_containers || -1 == num_tag_infos || -1 == num_ent_infos )
        MB_SET_ERR( MB_FAILURE, "Bad count for containers/tags/ents" );

    std::vector< damsel_entity_buf_type > ent_infos( num_ent_infos );
    std::vector< damsel_collection_buf_type > coll_infos( num_coll_infos );
    std::vector< damsel_tag_buf_type > tag_infos( num_tag_infos );
    std::vector< damsel_container_buf_type > cont_infos( num_containers );
    err = DMSLmodel_get_entity_infos( dU.dmslModel, &ent_infos[0] );
    CHK_DMSL_ERR( err, "Failure getting entity infos" );
    err = DMSLmodel_get_collection_infos( dU.dmslModel, &coll_infos[0] );
    CHK_DMSL_ERR( err, "Failure getting collection infos" );
    err = DMSLmodel_get_tag_infos( dU.dmslModel, &tag_infos[0] );
    CHK_DMSL_ERR( err, "Failure getting tag infos" );
    err = DMSLmodel_get_container_infos( dU.dmslModel, &cont_infos[0] );
    CHK_DMSL_ERR( err, "Failure getting container infos" );

    // Create MOAB-side tags for all damsel tags except pre-defined ones
    rval = process_tags( tag_infos );MB_CHK_SET_ERR( rval, "Error processing tags" );

    /*
      if (nativeParallel) {
        // STEP 1: GET COLLECTION(S) REPRESENTING PARTITION:
        // Input: tag name, optionally value;
        // Output: container with file-side handles of collections satisfying those criteria
        // - Get all handles/values for tag
        // - Select handles matching criteria for tag value (will be collection handles)
        std::string partn_tag_name("PARALLEL_PARTITION");
        damsel_handle partn_tag = DMSLselect_tag_by_name(dU.dmslModel, partn_tag_name.c_str());
        // Get all the parts with that tag regardless of value
        damsel_container part_handles = DMSLselect_handles_with_values(dU.dmslModel, partn_tag);

        // STEP 2: GET HANDLES FOR TAGS WE NEED FOR THIS READER:
        // - "SET_CHARACTERISTIC"
        damsel_handle setchar_tag = DMSLselect_tag_by_name(dU.dmslModel, "SET_CHARACTERISTIC");
        // - "PARENT_LIST"
        //damsel_handle plist_tag = DMSLselect_tag_by_name(dU.dmslModel, "PARENT_LIST");
        // - "CHILD_LIST"
        //damsel_handle clist_tag = DMSLselect_tag_by_name(dU.dmslModel, "CHILD_LIST");

        // STEP 3: GET VALUES FOR "SET_CHARACTERISTIC" TAG ON PARTITION COLLECTIONS,
        //         GET VECTOR- OR SET-TYPE FLAGS FOR PARTITION COLLECTIONS
        // (gives tracking flag for moab)
        int num_handles = DMSLcontainer_count(part_handles);
        std::vector<unsigned> char_tagvals(num_handles);
        // Map the set chars
        err = DMSLmodel_map_tag(&char_tagvals[0], part_handles, &setchar_tag);CHK_DMSL_ERR(err,
      "Problem calling DMSLmodel_map_tag");

        // Execute the transfer
        err = DMSLmodel_transfer_sync(dU.dmslModel, DAMSEL_TRANSFER_TYPE_READ);CHK_DMSL_ERR(err,
      "Problem calling DMSLmodel_transfer_sync");

        // STEP 4: READ/PROCESS PARTITION COLLECTION(S)
        // Decide the handles I am responsible using round-robin for now
        // - GET TYPE, CONTENTS OF COLLECTION CONTENTS CONTAINER
        // - Allocate moab-side container (using count from container)
        // - MAP storage TO CONTAINER
        // - EXECUTE
        // ==> have list of all handles (entities + collections) represented on this proc

        int tmp_num = num_handles / proc_size, extra = num_handles % proc_size;
        if (extra) tmp_num++;
        int my_num_handles = tmp_num;
        if (proc_rank >= extra) my_num_handles--;
        int first_ind = std::min(proc_rank, extra) * tmp_num +
            std::max(proc_rank - extra, 0) * (tmp_num - 1);

        // - Create moab entity sets for partition collection(s)
        EntityHandle start_handle;
        rval = readMeshIface->create_entity_sets(my_num_handles, &char_tagvals[first_ind], 0,
      start_handle);MB_CHK_SET_ERR(rval, "Problem creating entity sets");
      }
      else {
    */
    // Initialize just by entity; each call to process_ent_info will:
    // a. Create moab-side representation to read into
    // b. Map those handles to damsel handles
    // c. Map coords / connectivity storage to damsel equivalent
    // d. For each tag, map moab storage to damsel storage
    std::vector< damsel_entity_buf_type >::iterator eiit;

    // Process verts info first
    for( eiit = ent_infos.begin(); eiit != ent_infos.end(); ++eiit )
    {
        if( ( *eiit ).entity_type == DAMSEL_ENTITY_TYPE_VERTEX )
        {
            rval = process_ent_info( *eiit );MB_CHK_ERR( rval );
        }
    }

    for( eiit = ent_infos.begin(); eiit != ent_infos.end(); ++eiit )
    {
        if( ( *eiit ).entity_type != DAMSEL_ENTITY_TYPE_VERTEX )
        {
            rval = process_ent_info( *eiit );MB_CHK_ERR( rval );
        }
    }

    /*
      }

      // Process collections
      rval = process_coll_infos(coll_infos);MB_CHK_ERR(rval);

      // STEP 5: Process into list of local info structs, each represents file-side struct and
      // portion of that struct
      // ASSUMPTION: Each local info struct represents single entity type & # vertices or collection

      // STEP 6: For each local info struct:

      // STEP 6b: READ CONTAINER INTO LOCAL BUFFER
      // STEP 6c: Create app representation of entities/vertices/collection, and damsel container
      for them,
      //    and MAP APP HANDLE CONTAINER TO DAMSEL CONTAINER
      // STEP 6d: Process vertices/entities/collection
      //    6d1: If vertices, continue
      //    6d2: If entities:
      //    - MAP LOCAL CONNECTIVITY REP'N TO DAMSEL (might be tag, don't know yet)
      //    6d3: If collection:
      //    - (everything in STEP 4 for this collection except for EXECUTE)
      //    - might need to filter out things not represented on this rank
      //    6d4: If sparse tag:
      //    - Create app-side representation of sparse tag
      //    - READ CONTAINER OF MODEL HANDLES INTO LOCAL BUFFER
      //    - Allocate app-side storage for tag values
      //    - MAP APP STORAGE TO MODEL TAG + (implicit?) CONTAINER

      // STEP 6e: Process dense tags for the local info struct; for each dense tag:
      //   - Get app tag handle for model tag handle
      //   - Get app storage for app tag handle + container
      //   - MAP APP STORAGE TO MODEL TAG + CONTAINER

      // STEP 7: EXECUTE
      //   - Assign all mapped data
      //   - Translate all damsel handles to app handles
      // uninit damsel

    */

    return MB_SUCCESS;
}

ErrorCode ReadDamsel::read_tag_values( const char* file_name,
                                       const char* tag_name,
                                       const FileOptions& opts,
                                       std::vector< int >& tag_values_out,
                                       const SubsetList* subset_list )
{
    return MB_FAILURE;
}

ErrorCode ReadDamsel::process_tags( std::vector< damsel_tag_buf_type >& tag_infos )
{
    Tag tagh;
    ErrorCode rval = MB_SUCCESS, tmp_rval;
    for( std::vector< damsel_tag_buf_type >::iterator tit = tag_infos.begin(); tit != tag_infos.end(); ++tit )
    {
        if( DamselUtil::dtom_data_type[( *tit ).tag_datatype] == MB_TYPE_OPAQUE )
        {
            std::cout << "Damsel reader encountered opaque tag." << std::endl;
            continue;
        }

        tmp_rval = mbImpl->tag_get_handle( ( *tit ).name, 1, DamselUtil::dtom_data_type[( *tit ).tag_datatype], tagh,
                                           MB_TAG_CREAT | MB_TAG_DENSE );
        if( MB_SUCCESS != tmp_rval )
            rval = tmp_rval;
        else
        {
            dU.tagMap.push_back( DamselUtil::tinfo( tagh, 0, MB_TAG_DENSE ) );
            // Also store predefined tags specially...
            if( !strncmp( ( *tit ).name, "mbdmsl_", 7 ) )
            {
                // Predefined tag name, store the handle
                if( !strcmp( ( *tit ).name, "mbdmsl_XCOORDS" ) )
                    dU.xcoordsTag = dU.tagMap.back();
                else if( !strcmp( ( *tit ).name, "mbdmsl_YCOORDS" ) )
                {
                    dU.ycoordsTag = dU.tagMap.back();
                }
                else if( !strcmp( ( *tit ).name, "mbdmsl_ZCOORDS" ) )
                {
                    dU.zcoordsTag = dU.tagMap.back();
                }
                else if( !strcmp( ( *tit ).name, "mbdmsl_COLL_FLAGS" ) )
                {
                    dU.collFlagsTag = dU.tagMap.back();
                }
                else if( !strcmp( ( *tit ).name, "mbdmsl_PARENTS" ) )
                {
                    dU.parentsTag = dU.tagMap.back();
                }
                else if( !strcmp( ( *tit ).name, "mbdmsl_CHILDREN" ) )
                {
                    dU.childrenTag = dU.tagMap.back();
                }
                else
                {
                    rval = MB_FAILURE;
                    continue;
                }
            }
        }
    }

    return rval;
}

ErrorCode ReadDamsel::process_ent_info( const damsel_entity_buf_type& einfo )
{
    // Create this chunk of entities
    EntityHandle *connect, start_handle;
    ErrorCode rval;
    damsel_err_t err;
    damsel_container app_cont;
    Range these_ents;

    // Check that there's only one contiguous run of file-side handles, fail if there isn't
#ifndef NDEBUG
    Range fside_handles;
    rval = DamselUtil::container_to_range( dU.dmslModel, const_cast< damsel_container& >( einfo.entity_container ),
                                           fside_handles );
    if( MB_SUCCESS != rval || fside_handles.size() != einfo.count || fside_handles.psize() != 1 ) return MB_FAILURE;
#endif

    if( einfo.entity_type != DAMSEL_ENTITY_TYPE_VERTEX )
    {
        // Create the moab entities
        rval = readMeshIface->get_element_connect( einfo.count, einfo.vertices_per_entity,
                                                   DamselUtil::dtom_entity_type[einfo.entity_type], 0, start_handle,
                                                   connect );MB_CHK_ERR( rval );
        these_ents.insert( start_handle, start_handle + einfo.count - 1 );

        // Create an app-side sequence and map to file-side container
        app_cont = DMSLcontainer_create_sequence( dU.dmslModel, einfo.count, start_handle, 1 );
        err      = DMSLmodel_map_handles( app_cont, einfo.entity_container );
        CHK_DMSL_ERR( err, "Error returned mapping entity handles" );

        // Map connectivity
        assert( DMSLcontainer_count( einfo.vertex_container ) == (int)( einfo.vertices_per_entity * einfo.count ) );
        rval = get_contents( dU.dmslModel, einfo.vertex_container, connect );MB_CHK_SET_ERR( rval, "Error returned mapping connectivity" );
    }
    else
    {
        // Get the number of coordinate arrays
        int num_ctags             = 0;
        damsel_handle xcoord_dtag = DMSLselect_tag_by_name( dU.dmslModel, "mbdmsl_XCOORDS" );
        if( xcoord_dtag ) num_ctags++;
        damsel_handle ycoord_dtag = DMSLselect_tag_by_name( dU.dmslModel, "mbdmsl_YCOORDS" );
        if( ycoord_dtag ) num_ctags++;
        damsel_handle zcoord_dtag = DMSLselect_tag_by_name( dU.dmslModel, "mbdmsl_ZCOORDS" );
        if( zcoord_dtag ) num_ctags++;

        // Should have one vertex per entity
        assert( einfo.vertices_per_entity == 1 );
        std::vector< double* > coord_arrays;
        rval = readMeshIface->get_node_coords( num_ctags, einfo.count, 0, start_handle, coord_arrays );MB_CHK_ERR( rval );

        these_ents.insert( start_handle, start_handle + einfo.count - 1 );

        // Create an app-side sequence and map to file-side container
        app_cont = DMSLcontainer_create_sequence( dU.dmslModel, start_handle, einfo.count, 1 );
        err      = DMSLmodel_map_handles( app_cont, einfo.entity_container );
        CHK_DMSL_ERR( err, "Trouble mapping entity handles" );

        // Map the coords storage
        if( xcoord_dtag != 0 )
        {
            err = DMSLmodel_map_tag( coord_arrays[0], app_cont, (damsel_handle_ptr)&dU.xcoordsTag.mTagh );
            CHK_DMSL_ERR( err, "Trouble mapping x coordinate tag" );
        }
        if( ycoord_dtag != 0 )
        {
            err = DMSLmodel_map_tag( coord_arrays[1], app_cont, (damsel_handle_ptr)&dU.ycoordsTag.mTagh );
            CHK_DMSL_ERR( err, "Trouble mapping y coordinate tag" );
        }
        if( zcoord_dtag != 0 )
        {
            err = DMSLmodel_map_tag( coord_arrays[2], app_cont, (damsel_handle_ptr)&dU.zcoordsTag.mTagh );
            CHK_DMSL_ERR( err, "Trouble mapping z coordinate tag" );
        }
    }

    // Save mapping from moab entity to einfo
    dmHandleRMap.insert( DMSLcontainer_handle_at_position( einfo.entity_container, 0 ), start_handle, einfo.count );

    rval = process_entity_tags( einfo.tag_count, einfo.tag_handle_container, app_cont, these_ents );

    return rval;
}

ErrorCode ReadDamsel::process_entity_tags( int count,
                                           damsel_container tag_container,
                                           damsel_container app_cont,
                                           Range& these_ents )
{
    // Process tags on these entities
    ErrorCode rval = MB_SUCCESS;
    for( int i = 0; i < count; i++ )
    {
        damsel_handle dtagh = DMSLcontainer_handle_at_position( tag_container, i );

        // Don't do conventional tags here
        std::vector< DamselUtil::tinfo >::iterator vit =
            std::find_if( dU.tagMap.begin(), dU.tagMap.end(), DamselUtil::DtagP< DamselUtil::tinfo >( dtagh ) );

        if( ( *vit ).tagType == MB_TAG_ANY )
            continue;
        else if( vit == dU.tagMap.end() )
            MB_SET_ERR( MB_FAILURE, "Failed to find tag" );

        Tag tagh = ( *vit ).mTagh;
        assert( tagh );
        void* tag_data;
        int ecount = these_ents.size();
        rval       = mbImpl->tag_iterate( tagh, these_ents.begin(), these_ents.end(), ecount, tag_data );MB_CHK_SET_ERR( rval, "Problem getting tag iterator" );
        assert( ecount == (int)these_ents.size() );
        damsel_err_t err = DMSLmodel_map_tag( tag_data, app_cont, (damsel_handle_ptr)&tagh );
        CHK_DMSL_ERR( err, "Problem calling DMSLmodel_map_tag" );
    }

    return rval;
}

ErrorCode ReadDamsel::get_contents( damsel_model m, damsel_container c, Range& ents )
{
    EntityHandle eh;
    if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_SEQUENCE )
    {
        damsel_handle start;
        size_t count, stride;
        damsel_err_t err = DMSLcontainer_sequence_get_contents( m, c, &start, &count, &stride );
        CHK_DMSL_ERR( err, "DMSLcontainer_sequence_get_contents" );
        if( stride == 1 )
        {
            while( count )
            {
                // Get start in rangemap
                RangeMap< damsel_handle, EntityHandle, 0 >::iterator beg = dmHandleRMap.lower_bound( start );
                if( beg == dmHandleRMap.end() ) return MB_SUCCESS;
                unsigned long diff = std::max( ( *beg ).begin - start, (damsel_handle)0 );
                unsigned long num  = std::min( count - diff, (size_t)( *beg ).count );
                ents.insert( ( *beg ).begin + diff, ( *beg ).begin + diff + num - 1 );
                count -= ( diff + num );
                ++beg;
            }
        }
        else
        {
            for( int i = count - 1; i >= 0; i-- )
            {
                if( dmHandleRMap.find( start + i, eh ) ) ents.insert( eh );
            }
        }
    }
    else if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_VECTOR )
    {
        damsel_handle* handle_ptr;
        size_t count;
        damsel_err_t err = DMSLcontainer_vector_get_contents( m, c, &handle_ptr, &count );
        CHK_DMSL_ERR( err, "Trouble getting vector contents" );
        for( int i = count - 1; i >= 0; i-- )
        {
            if( dmHandleRMap.find( handle_ptr[i], eh ) ) ents.insert( eh );
        }
    }
    else if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_TREE )
    {
        damsel_handle_ptr node_ptr = NULL;
        damsel_container cont      = NULL;
        while( DMSLcontainer_tree_get_contents( m, c, &node_ptr, &cont ) == DMSL_OK && cont )
        {
            ErrorCode rval = get_contents( m, c, ents );
            if( MB_SUCCESS != rval ) return rval;
        }
    }

    return MB_SUCCESS;
}

ErrorCode ReadDamsel::get_contents( damsel_model m, damsel_container c, EntityHandle* ents )
{
    EntityHandle eh;
    int ind = 0;

    if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_SEQUENCE )
    {
        damsel_handle start;
        size_t count, stride;
        damsel_err_t err = DMSLcontainer_sequence_get_contents( m, c, &start, &count, &stride );
        CHK_DMSL_ERR( err, "Problem calling DMSLcontainer_sequence_get_contents" );
        if( stride == 1 )
        {
            while( count )
            {
                // Get start in rangemap
                RangeMap< damsel_handle, EntityHandle, 0 >::iterator beg = dmHandleRMap.lower_bound( start );
                if( beg == dmHandleRMap.end() ) return MB_SUCCESS;
                unsigned int diff = std::max( ( *beg ).begin - start, (damsel_handle)0 );
                unsigned int num  = std::min( count - diff, (size_t)( *beg ).count );
                for( EntityHandle hdl = ( *beg ).begin + diff; hdl <= (int)( *beg ).begin + diff + num - 1; hdl++ )
                    ents[ind++] = hdl;
                count -= ( diff + num );
                ++beg;
            }
        }
        else
        {
            for( int i = count - 1; i >= 0; i-- )
            {
                if( dmHandleRMap.find( start + i, eh ) ) ents[i] = eh;
            }
        }
    }
    else if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_VECTOR )
    {
        damsel_handle_ptr handle_ptr;
        size_t count;
        damsel_err_t err = DMSLcontainer_vector_get_contents( m, c, &handle_ptr, &count );
        CHK_DMSL_ERR( err, "Failed to get vector contents" );
        for( int i = count - 1; i >= 0; i-- )
        {
            if( dmHandleRMap.find( handle_ptr[i], eh ) ) ents[i] = eh;
        }
    }
    else if( DMSLcontainer_get_type( c ) == DAMSEL_HANDLE_CONTAINER_TYPE_TREE )
    {
        damsel_handle_ptr node_ptr = NULL;
        damsel_container cont      = NULL;
        while( DMSLcontainer_tree_get_contents( m, c, &node_ptr, &cont ) == DMSL_OK && cont )
        {
            ErrorCode rval = get_contents( m, cont, ents );
            if( MB_SUCCESS != rval ) return rval;
            unsigned int num = DMSLcontainer_count( cont );
            ents += num;
        }
    }

    return MB_SUCCESS;
}

/*
ErrorCode ReadDamsel::process_coll_infos(std::vector<damsel_collection_buf_type> &coll_infos)
{
  ErrorCode rval = MB_SUCCESS, tmp_rval;
  EntityHandle seth;
  std::vector<subrange> handle_subranges;
  for (std::vector<damsel_collection_buf_type>::iterator cit = coll_infos.begin(); cit !=
coll_infos.end(); ++cit) {
    // Make the set
    tmp_rval = mbImpl->create_meshset(((*cit).type ==  DAMSEL_HANDLE_COLLECTION_TYPE_SET ?
MESHSET_SET : MESHSET_ORDERED), seth); if (MB_SUCCESS != tmp_rval) rval = tmp_rval;
    // Make datastructures to pass things to process_entity_tags
    Range tmp_range(seth, seth);
    damsel_container ch = DMSLcontainer_create_sequence(dU.dmslModel, seth, 1, 1);

    // Get the tags on this set
    tmp_rval = process_entity_tags((*cit).tag_count, (*cit).tag_handle_container, ch, tmp_range);
    if (MB_SUCCESS != tmp_rval)
      rval = tmp_rval;

    // Process the set contents
    if ((*cit).type == DAMSEL_HANDLE_COLLECTION_TYPE_SET) {
      Range ents;
      tmp_rval = get_contents(dU.dmslModel, (*cit).contents, ents);
      if (MB_SUCCESS != tmp_rval)
        rval = tmp_rval;
      else if (!ents.empty()) {
        tmp_rval = mbImpl->add_entities(seth, ents);
        if (MB_SUCCESS != tmp_rval)
          rval = tmp_rval;
      }
    }
    else {
      std::vector<EntityHandle> ents(DMSLcontainer_count((*cit).contents));
      tmp_rval = get_contents(dU.dmslModel, (*cit).contents, &ents[0]);
      if (MB_SUCCESS != tmp_rval)
        rval = tmp_rval;
      else if (!ents.empty()) {
        tmp_rval = mbImpl->add_entities(seth, &ents[0], ents.size());
        if (MB_SUCCESS != tmp_rval)
          rval = tmp_rval;
      }
    }

    // Get the file handle for this collection, and map it to moab's set handle
    damsel_handle collh = (damsel_handle)(*((*cit).collection_handle));
    if (handle_subranges.empty() || seth != (*handle_subranges.rbegin()).seth + 1 ||
        collh != (*handle_subranges.rbegin()).collh + 1) {
      handle_subranges.push_back(subrange(collh, seth, 1));
    }
    else (*handle_subranges.rbegin()).count++;
  }

  for (std::vector<subrange>::iterator vit = handle_subranges.begin(); vit !=
handle_subranges.end(); ++vit) dmHandleRMap.insert((*vit).collh, (*vit).seth, (*vit).count);

  return rval;
}
*/

}  // namespace moab