avtCCMFileFormat.C 90.3 KB
Newer Older
whitlocb's avatar
whitlocb committed
1 2
/*****************************************************************************
*
bonnell's avatar
bonnell committed
3
* Copyright (c) 2000 - 2015, Lawrence Livermore National Security, LLC
whitlocb's avatar
whitlocb committed
4
* Produced at the Lawrence Livermore National Laboratory
5
* LLNL-CODE-442911
whitlocb's avatar
whitlocb committed
6 7
* All rights reserved.
*
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
whitlocb's avatar
whitlocb committed
9 10 11 12 13 14 15 16 17 18
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
19 20 21
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
whitlocb's avatar
whitlocb committed
22 23 24 25 26
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
27 28 29
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
whitlocb's avatar
whitlocb committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

// ************************************************************************* //
//                            avtCCMFileFormat.C                             //
// ************************************************************************* //

#include <avtCCMFileFormat.h>

45 46
#include <vtkCellArray.h>
#include <vtkCellData.h>
whitlocb's avatar
whitlocb committed
47 48
#include <vtkCellTypes.h>
#include <vtkFloatArray.h>
49
#include <vtkIdList.h>
50 51
#include <vtkIntArray.h>
#include <vtkPointData.h>
52
#include <vtkUnsignedIntArray.h>
whitlocb's avatar
whitlocb committed
53 54
#include <vtkUnstructuredGrid.h>

55
#include <avtCallback.h>
whitlocb's avatar
whitlocb committed
56
#include <avtDatabaseMetaData.h>
57 58
#include <avtFacelist.h>
#include <avtVariableCache.h>
cyrush's avatar
cyrush committed
59
#include <avtPolygonToTrianglesTesselator.h>
whitlocb's avatar
whitlocb committed
60

61
#include <Expression.h>
whitlocb's avatar
whitlocb committed
62 63
#include <Expression.h>

64
#include <InvalidFilesException.h>
whitlocb's avatar
whitlocb committed
65 66 67
#include <InvalidVariableException.h>

#include <DebugStream.h>
68
#include <TimingsManager.h>
whitlocb's avatar
whitlocb committed
69

70 71
#include <avtParallel.h>

72 73 74 75 76 77
#include <algorithm>
#include <deque>
#include <set>
#include <string>
#include <vector>

78 79 80 81 82 83 84
#ifdef PARALLEL
// If we're running in parallel then we can enable subdivision of single domains.
// This only kicks in when there is a single domain that we want to split among
// all processors.
#define ENABLE_SUBDIVISION
#endif

whitlocb's avatar
whitlocb committed
85 86 87 88
// Prototypes
ostream &operator << (ostream &os, CCMIOEntity e);
ostream &operator << (ostream &os, const CCMIONode &node);
ostream &operator << (ostream &os, const CCMIOID &id);
89

whitlocb's avatar
whitlocb committed
90 91 92 93 94 95
// ****************************************************************************
//  Method: avtCCM constructor
//
//  Programmer: Brad Whitlock
//  Creation:   Thu Aug 2 15:01:17 PST 2007
//
96 97 98 99
//  Modifications:
//    Kathleen Bonnell, Thu Feb 28 15:00:24 PST 2008
//    Added varsOnSubmesh.
//
whitlocb's avatar
whitlocb committed
100 101 102
// ****************************************************************************

avtCCMFileFormat::avtCCMFileFormat(const char *filename)
103
    : avtSTMDFileFormat(&filename, 1), varsToFields(), varsOnSubmesh()
whitlocb's avatar
whitlocb committed
104 105
{
    ccmOpened = false;
106
    ccmStateFound = false;
whitlocb's avatar
whitlocb committed
107
    ccmErr = kCCMIONoErr;
108
    subdividingSingleMesh = false;
109
    initialized = false;
whitlocb's avatar
whitlocb committed
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
}

// ****************************************************************************
//  Method: avtCCM destructor
//
//  Programmer: Brad Whitlock
//  Creation:   Thu Aug 2 15:01:17 PST 2007
//
// ****************************************************************************

avtCCMFileFormat::~avtCCMFileFormat()
{
    FreeUpResources();
}

// ****************************************************************************
//  Method: avtCCMFileFormat::FreeUpResources
//
//  Purpose:
//      When VisIt is done focusing on a particular timestep, it asks that
//      timestep to free up any resources (memory, file descriptors) that
//      it has associated with it.  This method is the mechanism for doing
//      that.
//
//  Programmer: Brad Whitlock
//  Creation:   Thu Aug 2 15:01:17 PST 2007
//
137 138 139 140
//  Modifications:
//    Kathleen Bonnell, Thu Feb 28 15:00:24 PST 2008
//    Added varsOnSubmesh.
//
141 142 143
//    Brad Whitlock, Mon Jul 30 16:32:08 PDT 2012
//    Set ccmStateFound to false.
//
whitlocb's avatar
whitlocb committed
144 145 146 147 148 149 150 151
// ****************************************************************************

void
avtCCMFileFormat::FreeUpResources(void)
{
    if(ccmOpened)
    {
        ccmOpened = false;
152
        ccmStateFound = false;
whitlocb's avatar
whitlocb committed
153 154 155
        CCMIOCloseFile(&ccmErr, ccmRoot);
        ccmErr = kCCMIONoErr;
    }
156
    for (size_t i = 0; i < originalCells.size(); ++i)
157 158 159 160 161 162 163 164 165
    {
        if (originalCells[i] != NULL)
        {
            originalCells[i]->Delete();
            originalCells[i] = NULL;
        }
    }
    originalCells.clear();
    varsToFields.clear();
166
    varsOnSubmesh.clear();
167 168

    subdividingSingleMesh = false;
169
    initialized = false;
cyrush's avatar
cyrush committed
170
}
171 172 173 174 175 176 177 178 179 180


// ****************************************************************************
//  Method:  avtCCMFileFormat::CanCacheVariable
//
//  Purpose:
//    Determines if the given variable can be cached above the layer of the
//    plugin. In some cases, particularly where different ghosting is used
//    for different variables, the mesh variable cannot be cached.
//
cyrush's avatar
cyrush committed
181 182
//  Programmer:  Kathleen Bonnell
//  Creation:    February 28, 2008
183 184 185 186 187 188 189
//
// ***************************************************************************

bool
avtCCMFileFormat::CanCacheVariable(const char *varname)
{
    return varsOnSubmesh.empty();
whitlocb's avatar
whitlocb committed
190 191 192 193 194
}

// ****************************************************************************
// Method: avtCCMFileFormat::GetRoot
//
cyrush's avatar
cyrush committed
195
// Purpose:
whitlocb's avatar
whitlocb committed
196 197 198 199 200 201
//   Opens the file and passes back an id for the "root" node that can be used
//   to read information about the file. We use this instead of ccmRoot so the
//   file can be implicitly opened, if needed.
//
// Arguments:
//
cyrush's avatar
cyrush committed
202
// Returns:
whitlocb's avatar
whitlocb committed
203
//
cyrush's avatar
cyrush committed
204
// Note:
whitlocb's avatar
whitlocb committed
205 206 207 208 209
//
// Programmer: Brad Whitlock
// Creation:   Mon Aug 6 09:11:07 PDT 2007
//
// Modifications:
cyrush's avatar
cyrush committed
210
//
whitlocb's avatar
whitlocb committed
211 212 213 214 215 216 217 218 219
// ****************************************************************************

CCMIOID &
avtCCMFileFormat::GetRoot()
{
    const char *mName = "avtCCMFileFormat::GetRoot: ";
    if(!ccmOpened)
    {
        ccmErr = kCCMIONoErr;
220
        ccmErr = CCMIOOpenFile(NULL, filenames[0], kCCMIORead, &ccmRoot);
whitlocb's avatar
whitlocb committed
221 222 223
        if(ccmErr == kCCMIONoErr)
            ccmOpened = true;
        else
cyrush's avatar
cyrush committed
224
            debug4 << mName << "Could not open CCM file "
225
                   << filenames[0] << endl;
whitlocb's avatar
whitlocb committed
226 227 228 229 230
    }

    return ccmRoot;
}

231 232 233 234

// ****************************************************************************
// Method: avtCCMFileFormat::GetState
//
cyrush's avatar
cyrush committed
235
// Purpose:
236 237
//   Gets the 'state' entity.  A 'default' state is tried first, and if
//   not found the first state found is used.  We may want to change this
cyrush's avatar
cyrush committed
238
//   in the future, so that multiple states can be retrieved.
239 240
//
// Programmer: Kathleen Bonnell
cyrush's avatar
cyrush committed
241
// Creation:   September 11, 2007
242 243
//
// Modifications:
cyrush's avatar
cyrush committed
244
//
245 246 247 248 249 250 251 252 253
// ****************************************************************************

CCMIOID &
avtCCMFileFormat::GetState()
{
    const char *mName = "avtCCMFileFormat::GetState: ";
    if (!ccmStateFound)
    {
        // first try default state
254
        CCMIOGetState(&ccmErr, GetRoot(), "default", &ccmProblem, &ccmState);
255 256 257 258
        if (ccmErr == kCCMIONoErr)
        {
            ccmStateFound = true;
        }
cyrush's avatar
cyrush committed
259
        else
260 261
        {
            int i = 0;
cyrush's avatar
cyrush committed
262 263
            ccmErr = kCCMIONoErr;
            if (CCMIONextEntity(NULL, GetRoot(), kCCMIOState, &i, &ccmState)
264 265 266
                == kCCMIONoErr)
            {
                ccmStateFound = true;
267
                int j = 0;
cyrush's avatar
cyrush committed
268
                CCMIONextEntity(NULL, GetRoot(), kCCMIOProblemDescription,
269
                                &j, &ccmProblem);
270 271 272 273 274 275 276 277 278 279 280
            }
            else
            {
                debug4 << mName <<  "Could not find state entity." << endl;
            }
        }
    }
    return ccmState;
}


whitlocb's avatar
whitlocb committed
281 282 283
// ****************************************************************************
// Method: avtCCMFileFormat::GetIDsForDomain
//
cyrush's avatar
cyrush committed
284
// Purpose:
whitlocb's avatar
whitlocb committed
285 286 287 288 289
//   Gets nodes for state, processor, vertices, topology and solution that can
//   be used to query attributes for variables and meshes.
//
// Arguments:
//
cyrush's avatar
cyrush committed
290
// Returns:
whitlocb's avatar
whitlocb committed
291
//
cyrush's avatar
cyrush committed
292
// Note:
whitlocb's avatar
whitlocb committed
293 294 295 296 297
//
// Programmer: Brad Whitlock
// Creation:   Mon Aug 6 09:10:29 PDT 2007
//
// Modifications:
cyrush's avatar
cyrush committed
298
//
whitlocb's avatar
whitlocb committed
299 300 301
// ****************************************************************************

bool
cyrush's avatar
cyrush committed
302
avtCCMFileFormat::GetIDsForDomain(int dom,
whitlocb's avatar
whitlocb committed
303 304 305
    CCMIOID &processor, CCMIOID &vertices, CCMIOID &topology,
    CCMIOID &solution, bool &hasSolution)
{
306
    //const char *mName = "avtCCMFileFormat::GetIDsForDomain: ";
whitlocb's avatar
whitlocb committed
307 308 309 310

    // Try and get the requested processor.
    int proc = dom;
    bool ret = (
311
        CCMIONextEntity(NULL, GetState(), kCCMIOProcessor, &proc, &processor) ==
whitlocb's avatar
whitlocb committed
312 313 314 315
        kCCMIONoErr);
    if(ret)
    {
        hasSolution = true;
316
        ccmErr = kCCMIONoErr;
cyrush's avatar
cyrush committed
317
        // Try and read the vertices, topology, and solution ids for this
318
        // processor.
cyrush's avatar
cyrush committed
319
        CCMIOReadProcessor(&ccmErr, processor, &vertices, &topology, NULL,
320
                           &solution);
whitlocb's avatar
whitlocb committed
321 322
        if(ccmErr != kCCMIONoErr)
        {
cyrush's avatar
cyrush committed
323
            // That didn't work. (Maybe no solution). See if we can at least
324
            // get the vertices and processor.
325
            ccmErr = kCCMIONoErr;
cyrush's avatar
cyrush committed
326
            CCMIOReadProcessor(&ccmErr, processor, &vertices, &topology, NULL,
327
                               NULL);
whitlocb's avatar
whitlocb committed
328 329 330 331 332 333 334 335 336 337
            if(ccmErr == kCCMIONoErr)
                hasSolution = false;
            else
                ret = false;
        }
    }

    return ret;
}

338 339 340 341

// ****************************************************************************
//  Method: avtCCMFileFormat::GetFaces
//
cyrush's avatar
cyrush committed
342
//  Purpose: Reads the face info.
343 344
//
//  Arguments:
345 346
//    faceID        The ID of the face entity.
//    faceType      The type of faces (internal or boundary).
cyrush's avatar
cyrush committed
347
//    nFaces        How many faces are in the entity.
348 349 350 351 352 353
//    cellIDMap     Used to map cell IDs to indices
//    vertexIDMap   Used to map vertex IDs to indices
//    minSize       Min num verts in a face
//    maxSize       Max num verts in a face
//    ci            A place to store the face info, must be allocated by
//                  calling method.
354
//
cyrush's avatar
cyrush committed
355 356
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2007
357 358
//
//  Modifications:
bonnell's avatar
bonnell committed
359 360
//    Kathleen Bonnell, Thu Mar  6 09:21:02 PST 2008
//    Removed unused variable.
361
//
362 363 364
//    Dave Bremer, Fri Apr  4 16:29:49 PDT 2008
//    Fixed a bug in which cell and vertex ids were mistaken for 1-based
//    indices.
365 366 367 368
// ****************************************************************************

void
avtCCMFileFormat::GetFaces(CCMIOID faceID, CCMIOEntity faceType,
369
                           unsigned int nFaces, const IDMap &cellIDMap,
cyrush's avatar
cyrush committed
370
                           const IDMap &vertexIDMap,
371
                           int &minSize, int &maxSize, CellInfoVector &ci)
372 373 374 375 376
{
    if (faceType != kCCMIOInternalFaces && faceType != kCCMIOBoundaryFaces)
    {
        debug1 << "avtCCMFileFormat::GetFaces encountered an internal error"
                << endl;
cyrush's avatar
cyrush committed
377
        return;
378 379
    }
    int getFacesTimer = visitTimer->StartTimer();
bonnell's avatar
bonnell committed
380
    CCMIOID mapID;
381
    unsigned int /*nCells = 0,*/ size = 0;
382 383
    //intVector faces;
    intVector faceNodes, faceCells;
384

385
    int t0 = visitTimer->StartTimer();
386 387 388 389 390
    // Determine the size of the faceNodes array, which is of the
    // form n1, v1, v2, ...vn1, n2, v1, v2, ... vn2, )
    CCMIOReadFaces(&ccmErr, faceID, faceType, NULL, &size, NULL,
                   kCCMIOStart, kCCMIOEnd);
    faceNodes.resize(size);
391
    //faces.resize(nFaces);
392 393
    if (faceType == kCCMIOInternalFaces)
        faceCells.resize(nFaces*2);
cyrush's avatar
cyrush committed
394
    else
395 396 397 398 399
        faceCells.resize(nFaces);
    CCMIOReadFaces(&ccmErr, faceID, faceType, &mapID, NULL,
                   &faceNodes[0], kCCMIOStart, kCCMIOEnd);
    CCMIOReadFaceCells(&ccmErr, faceID, faceType, &faceCells[0],
                       kCCMIOStart, kCCMIOEnd);
400
    //CCMIOReadMap(&ccmErr, mapID, &faces[0], kCCMIOStart, kCCMIOEnd);
401
    visitTimer->StopTimer(t0, "CCM IO calls");
402 403

    unsigned int pos = 0;
404
    for (unsigned int i = 0; i < nFaces; ++i)
405 406
    {
        FaceInfo newFace;
407
        //newFace.id = faces[i];
408 409 410 411 412
        if (faceType == kCCMIOInternalFaces)
        {
            newFace.cells[0] = faceCells[i*2];
            newFace.cells[1] = faceCells[i*2+1];
        }
cyrush's avatar
cyrush committed
413
        else
414 415 416 417 418 419 420 421 422 423
        {
            newFace.cells[0] = faceCells[i];
        }
        int nVerts = faceNodes[pos];

        if (nVerts < minSize)
            minSize = nVerts;
        if (nVerts > maxSize)
            maxSize = nVerts;

424
        for (int j = 0; j < nVerts; ++j)
425
        {
426
            newFace.nodes.push_back( vertexIDMap.IDtoIndex(faceNodes[pos+1+j]) );
427 428 429 430 431
        }
        // cell ids are 1-origin, so must subract 1 to get the
        // correct index into the CellInfoVector
        if (faceType == kCCMIOInternalFaces)
        {
432 433 434 435 436 437 438
            int  c0 = cellIDMap.IDtoIndex(newFace.cells[0]);
            int  c1 = cellIDMap.IDtoIndex(newFace.cells[1]);

            ci[c0].faceTypes.push_back(1);
            ci[c0].faces.push_back(newFace);
            ci[c1].faceTypes.push_back(2);
            ci[c1].faces.push_back(newFace);
439
        }
cyrush's avatar
cyrush committed
440
        else
441
        {
442 443 444 445
            int  c0 = cellIDMap.IDtoIndex(newFace.cells[0]);

            ci[c0].faceTypes.push_back(0);
            ci[c0].faces.push_back(newFace);
446 447 448 449 450 451
        }
        pos += faceNodes[pos] +1;
    }
    visitTimer->StopTimer(getFacesTimer, "GetFaces");
}

whitlocb's avatar
whitlocb committed
452 453 454 455 456 457 458 459 460 461 462 463
// ****************************************************************************
//  Method: avtCCMFileFormat::PopulateDatabaseMetaData
//
//  Purpose:
//      This database meta-data object is like a table of contents for the
//      file.  By populating it, you are telling the rest of VisIt what
//      information it can request from you.
//
//  Programmer: Brad Whitlock
//  Creation:   Thu Aug 2 15:01:17 PST 2007
//
//  Modifications:
464
//    Kathleen Bonnell, Thu Feb 28 15:00:24 PST 2008
cyrush's avatar
cyrush committed
465 466
//    Fixed determination of centering for Vector variables.  Added code to
//    determine if any variables are defined only on parts of the mesh, by
467
//    reading the number of cells, then mapData size for each var.
whitlocb's avatar
whitlocb committed
468
//
469 470 471
//    Brad Whitlock, Mon Jul 30 16:22:02 PDT 2012
//    Allow for NULL metadata.
//
whitlocb's avatar
whitlocb committed
472 473 474 475 476 477
// ****************************************************************************

void
avtCCMFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md)
{
    const char *mName = "avtCCMFileFormat::PopulateDatabaseMetaData: ";
478

479 480 481
    if(initialized)
        return;

cyrush's avatar
cyrush committed
482
    // Count the number of processors in the file.
483 484 485 486
    // Use that for the number of domains.
    CCMIOID processor;
    int proc = 0;
    int nblocks = 0;
cyrush's avatar
cyrush committed
487
    while (CCMIONextEntity(NULL, GetState(), kCCMIOProcessor, &proc,
488 489 490 491 492
           &processor) == kCCMIONoErr)
    {
        ++nblocks;
    }
    debug4 << mName << "Found " << nblocks << " domains in the file." << endl;
cyrush's avatar
cyrush committed
493

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
#if 0
    // this will be useful for subsetting by the cell type
    int nCellTypes = 0;
    if (CCMIOIsValidEntity(ccmProblem))
    {
        // Determine the number of kCCMIOCellTypes present.
        int i = 0;
        CCMIOID next;
        while(CCMIONextEntity(NULL, ccmProblem, kCCMIOCellType, &i, &next)
              == kCCMIONoErr)
        ++nCellTypes;
    }
#endif


whitlocb's avatar
whitlocb committed
509 510 511 512 513 514
#if 0
    // Read the simulation title.
    char *title = NULL;
    ccmErr = CCMIOGetTitle(&ccmErr, GetRoot(), &title);
    if(title != NULL)
    {
515 516
        if(md != NULL)
            md->SetDatabaseComment(title);
whitlocb's avatar
whitlocb committed
517 518 519 520
        free(title);
    }
#endif

521
    for (int i = 0; i < nblocks; ++i)
522
        originalCells.push_back(NULL);
whitlocb's avatar
whitlocb committed
523 524 525 526
    // Determine the spatial dimensions.
    int dims = 3;
    CCMIOID vertices, topology, solution;
    bool hasSolution = true;
527
    if(GetIDsForDomain(0, processor, vertices, topology, solution,
whitlocb's avatar
whitlocb committed
528 529
                       hasSolution))
    {
530 531 532 533 534 535
        dims = 1 ;
        CCMIOReadVerticesf(&ccmErr, vertices, &dims, NULL, NULL, NULL, 0, 1);
    }
    else
    {
        EXCEPTION1(InvalidFilesException, filenames[0]);
whitlocb's avatar
whitlocb committed
536 537
    }

538 539 540 541 542 543 544
    // If there's just 1 block, read the mesh now and decompose it into
    // more meshes, caching them for later.
    int nDomains = nblocks;
#ifdef ENABLE_SUBDIVISION
    if(nblocks == 1)
    {
        subdividingSingleMesh = true;
545 546
        if(md != NULL)
            md->SetFormatCanDoDomainDecomposition(true);
547 548 549
    }
#endif

whitlocb's avatar
whitlocb committed
550
    // Create a mesh.
551 552 553 554 555 556 557 558 559 560 561 562
    if(md != NULL)
    {
        avtMeshMetaData *mmd = new avtMeshMetaData;
        mmd->name = "Mesh";
        mmd->spatialDimension = dims;
        mmd->topologicalDimension = dims;
        mmd->meshType = AVT_UNSTRUCTURED_MESH;
        mmd->numBlocks = nDomains;
        mmd->cellOrigin = 1;
        mmd->nodeOrigin = 1;
        md->Add(mmd);
    }
563 564 565 566

    // Find variable data
    if (hasSolution)
    {
567 568 569 570 571 572 573 574
        // Determine number of cells, in order to find out
        // which variables are NOT defined on entire mesh.
        CCMIOError err = kCCMIONoErr;
        CCMIOID cellsID;
        CCMIOSize nCells;
        CCMIOGetEntity(&err, topology, kCCMIOCells, 0, &cellsID);
        CCMIOEntitySize(&err, cellsID, &nCells, NULL);

whitlocb's avatar
whitlocb committed
575
        debug5 << mName << "Reading variable information" << endl;
576

whitlocb's avatar
whitlocb committed
577 578
        CCMIOID field, phase = solution;
        int h = 0;
579
        int i = 0;
cyrush's avatar
cyrush committed
580
        bool oldFile = CCMIONextEntity(NULL, solution, kCCMIOFieldPhase,
581
                                       &h, &phase) != kCCMIONoErr;
whitlocb's avatar
whitlocb committed
582

583
        h = 0;
584 585 586 587
        while(oldFile ||
              CCMIONextEntity(NULL, solution, kCCMIOFieldPhase, &h, &phase) ==
                                                                   kCCMIONoErr)
        {
whitlocb's avatar
whitlocb committed
588 589 590
            debug5 << mName << "CCMIONextEntity for solution " << solution
                   << " returned h=" << h << ", phase = " << phase << endl;

591 592 593 594
            if (oldFile)
                phase = solution;
            else
            {
595
                int phaseNum = 0;
596 597
                CCMIOGetEntityIndex(NULL, phase, &phaseNum);
            }
whitlocb's avatar
whitlocb committed
598 599 600 601 602

            // This i needs to be set to 0 here because we're asking for the
            // first field from the current phase. Since we're iterating
            // over phases so far, we need to reset i to 0 here to get the
            // first field.
603 604 605 606
            while(CCMIONextEntity(NULL, phase, kCCMIOField, &i, &field) ==
                  kCCMIONoErr)
            {
                char name[kCCMIOMaxStringLength+1];
cyrush's avatar
cyrush committed
607
                char sName[kCCMIOProstarShortNameLength+1];
608 609 610 611 612 613
                char *units = NULL;
                int usize;
                CCMIODataType datatype;
                CCMIODimensionality cdims;
                CCMIOID fieldData, mapID;
                CCMIODataLocation type;
614
                CCMIOID varField = field;
615

whitlocb's avatar
whitlocb committed
616 617 618 619
                debug5 << mName << "CCMIONextEntity for phase " << phase
                       << " returned i=" << i << ", field = " << field << endl;

                // Get the field's name, dims, and data type.
620
                CCMIOReadField(&ccmErr, field, name, sName, &cdims, &datatype);
whitlocb's avatar
whitlocb committed
621
                debug5 << mName << "CCMIOReadField for field " << field
cyrush's avatar
cyrush committed
622
                       << " returned name=" << name << ", sName = "
623 624 625 626 627 628
                       << sName << endl;

                if (cdims == kCCMIOVector)
                {
                    CCMIOID scalar;
                    CCMIOError err = kCCMIONoErr;
cyrush's avatar
cyrush committed
629
                    CCMIOReadMultiDimensionalFieldData(&err, field,
630 631 632 633 634 635 636 637
                                             kCCMIOVectorX, &scalar);
                    if (err == kCCMIONoErr)
                    {
                        // componentized vector, use the X component scalar
                        // in order to retrieve more info about the vector
                        field = scalar;
                    }
                }
638 639 640 641

                char *usename;
                if (oldFile)
                    usename = name;
cyrush's avatar
cyrush committed
642
                else
643 644
                    usename = sName;

whitlocb's avatar
whitlocb committed
645
                // Read the field's units
646 647 648 649 650 651
                if (CCMIOReadOptstr(NULL, field, "Units", &usize, NULL) ==
                    kCCMIONoErr)
                {
                    units = new char[usize+1];
                    CCMIOReadOptstr(&ccmErr, field, "Units", NULL, units);
                }
whitlocb's avatar
whitlocb committed
652

cyrush's avatar
cyrush committed
653
                // Reset j to 0 to get the first field data. We read the
654
                // field data to determine the variable centering.
whitlocb's avatar
whitlocb committed
655 656
                int j = 0;
                avtCentering centering = AVT_UNKNOWN_CENT;
657 658
                CCMIOSize cellVarSize = 0;

cyrush's avatar
cyrush committed
659
                while (CCMIONextEntity(NULL, field, kCCMIOFieldData,
660 661
                       &j, &fieldData) == kCCMIONoErr)
                {
whitlocb's avatar
whitlocb committed
662
                    debug5 << mName << "CCMIONextEntity for field " << field
cyrush's avatar
cyrush committed
663
                           << " returned kCCMIONoErr, j=" << j
664
                           << ",fieldData=" << fieldData << endl;
whitlocb's avatar
whitlocb committed
665 666

                    // Read information about the field.
667
                    CCMIOReadFieldDataf(&ccmErr, fieldData, &mapID, &type,
whitlocb's avatar
whitlocb committed
668 669 670
                                        NULL, kCCMIOStart, kCCMIOEnd);
                    if(ccmErr != kCCMIONoErr)
                    {
cyrush's avatar
cyrush committed
671
                        debug5 << mName << "CCMIOReadFieldDataf failed."
672
                               << endl;
whitlocb's avatar
whitlocb committed
673 674 675 676
                        continue;
                    }

                    // Determine the variable centering.
677
                    if (type == kCCMIOVertex)
cyrush's avatar
cyrush committed
678
                    {
679
                        centering = AVT_NODECENT;
cyrush's avatar
cyrush committed
680
                        debug4 << "Var " << usename << " is node centered"
681
                               << endl;
cyrush's avatar
cyrush committed
682
                    }
683
                    else if (type == kCCMIOCell)
cyrush's avatar
cyrush committed
684
                    {
685
                        centering = AVT_ZONECENT;
cyrush's avatar
cyrush committed
686
                        debug4 << "Var " << usename << " is zone centered"
687 688 689 690 691
                               << endl;
                        CCMIOSize n;
                        CCMIOIndex max;
                        CCMIOEntitySize(&ccmErr, fieldData, &n, &max);
                        cellVarSize += n;
cyrush's avatar
cyrush committed
692
                    }
693
                    else if (type == kCCMIOFace)
cyrush's avatar
cyrush committed
694
                    {
695 696
                        debug4 << "Var " << usename << " is face-centered, "
                               << "ignoring for now. " << endl;
whitlocb's avatar
whitlocb committed
697 698 699
                    }
                }

700 701 702 703
                if (cellVarSize != nCells)
                {
                    varsOnSubmesh.push_back(usename);
                }
whitlocb's avatar
whitlocb committed
704 705 706
                // If we don't have metadata for the variable yet, add it.
                if(varsToFields.find(usename) == varsToFields.end())
                {
cyrush's avatar
cyrush committed
707
                    // Variables with an unsupported centering are tagged
708
                    // invalid.
whitlocb's avatar
whitlocb committed
709 710
                    bool validVariable = (centering != AVT_UNKNOWN_CENT);

711 712
                    if(cdims==kCCMIOScalar)
                    {
713
                        if(md != NULL)
714
                        {
cyrush's avatar
cyrush committed
715
                            avtScalarMetaData *smd = new avtScalarMetaData(usename,
716 717 718 719 720 721 722 723
                                "Mesh", centering);
                            if (units != NULL)
                            {
                                smd->hasUnits = true;
                                smd->units = units;
                            }
                            smd->validVariable = validVariable;
                            md->Add(smd);
724
                        }
725
                        varsToFields[usename] = varField;
726 727 728
                    }
                    else if(cdims==kCCMIOVector)
                    {
729
                        if(md != NULL)
730
                        {
cyrush's avatar
cyrush committed
731
                            avtVectorMetaData *vmd = new avtVectorMetaData(usename,
732 733 734 735 736 737 738 739
                                "Mesh", centering, 3);
                            if (units != NULL)
                            {
                                vmd->hasUnits = true;
                                vmd->units = units;
                            }
                            vmd->validVariable = validVariable;
                            md->Add(vmd);
740
                        }
741
                        varsToFields[usename] = varField;
742 743 744
                    }
                    else if(cdims==kCCMIOTensor)
                    {
745
                        if(md != NULL)
746
                        {
cyrush's avatar
cyrush committed
747
                            avtTensorMetaData *tmd = new avtTensorMetaData(usename,
748 749 750 751 752 753
                                "Mesh", centering, 9);
                            if (units != NULL)
                            {
                                tmd->hasUnits = true;
                                tmd->units = units;
                            }
whitlocb's avatar
whitlocb committed
754
#if 1
cyrush's avatar
cyrush committed
755
                            // Just make tensor vars display for now.
756 757
                            // Don't plot them.
                            tmd->validVariable = false;
whitlocb's avatar
whitlocb committed
758
#else
759
                            tmd->validVariable = validVariable;
whitlocb's avatar
whitlocb committed
760
#endif
761 762
                            md->Add(tmd);
                        }
763
                        varsToFields[usename] = varField;
764 765
                    }
                }
whitlocb's avatar
whitlocb committed
766

767 768 769 770 771 772 773 774 775
                if (units != NULL)
                {
                    delete [] units;
                    units = NULL;
                }
            }
            oldFile = false;
        }
    }
776 777

    initialized = true;
whitlocb's avatar
whitlocb committed
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
}


// ****************************************************************************
//  Method: avtCCMFileFormat::GetMesh
//
//  Purpose:
//      Gets the mesh associated with this file.  The mesh is returned as a
//      derived type of vtkDataSet (ie vtkRectilinearGrid, vtkStructuredGrid,
//      vtkUnstructuredGrid, etc).
//
//  Arguments:
//      domain      The index of the domain.  If there are NDomains, this
//                  value is guaranteed to be between 0 and NDomains-1,
//                  regardless of block origin.
//      meshname    The name of the mesh of interest.  This can be ignored if
//                  there is only one mesh.
//
//  Programmer: Brad Whitlock
//  Creation:   Thu Aug 2 15:01:17 PST 2007
//
//  Modifications:
whitlocb's avatar
whitlocb committed
800 801
//    Brad Whitlock, Tue Dec 18 12:57:28 PST 2007
//    Added support for 2D polygonal shapes.
whitlocb's avatar
whitlocb committed
802
//
803 804 805
//    Kathleen Bonnell, Thu Feb 28 15:00:24 PST 2008
//    If the primary variable (activeVisItVar) is defined only on a portion of
//    the mesh, only retrieve (and tesselate) those cells it is defined upon.
806 807 808 809
//
//    Dave Bremer, Fri Apr  4 16:29:49 PDT 2008
//    Fixed a bug in which cell and vertex ids were mistaken for 1-based
//    indices.
cyrush's avatar
cyrush committed
810
//
811 812 813 814
//    Brad Whitlock, Thu Oct  1 13:36:48 PDT 2009
//    I refactored this routine into helper routines and added support for
//    automatically subdividing a mesh on the fly.
//
815 816 817
//    Brad Whitlock, Mon Jul 30 16:22:14 PDT 2012
//    Force initialization if the plugin has not been initialized.
//
whitlocb's avatar
whitlocb committed
818 819
// ****************************************************************************

820

whitlocb's avatar
whitlocb committed
821
vtkDataSet *
822
avtCCMFileFormat::GetMesh(int domain, const char *meshname)
whitlocb's avatar
whitlocb committed
823
{
824 825
#ifdef MDSERVER
    return 0;
826
#else
827
    int t5 = visitTimer->StartTimer();
828 829 830
    // Override domain if we're automatically dividing the data
    int dom = subdividingSingleMesh ? 0 : domain;

whitlocb's avatar
whitlocb committed
831
    vtkUnstructuredGrid *ugrid = NULL;
832
    vtkPoints *points = NULL;
whitlocb's avatar
whitlocb committed
833

834 835 836 837
    // Force initialization if it has not been done.
    if(!initialized)
        PopulateDatabaseMetaData(NULL);

838
    TRY
whitlocb's avatar
whitlocb committed
839
    {
840
        // Read the points
841
        int t0 = visitTimer->StartTimer();
842
        points = ReadPoints(dom, meshname);
843
        visitTimer->StopTimer(t0, "Reading points");
whitlocb's avatar
whitlocb committed
844

845
        // Read the cell connectivity
846
        CellInfoVector cellInfo;
bonnell's avatar
bonnell committed
847
        int minFaceSize = VTK_INT_MAX;
848
        int maxFaceSize = -1;
849
        int t1 = visitTimer->StartTimer();
850 851
        ReadCellInfo(dom, meshname,
                     cellInfo, minFaceSize, maxFaceSize);
852
        visitTimer->StopTimer(t1, "Reading cell info");
853

854 855 856
        //
        // Convert cellInfo into vtkUnstructuredGrid
        //
857
        int t2 = visitTimer->StartTimer();
858
        SelectCellsForThisProcessor(cellInfo, points);
859
        visitTimer->StopTimer(t2, "cells for this processor");
860

whitlocb's avatar
whitlocb committed
861
        ugrid = vtkUnstructuredGrid::New();
862 863

        // Determine cell topology from face lists
whitlocb's avatar
whitlocb committed
864 865
        if (minFaceSize == 2 && maxFaceSize == 2)
        {
cyrush's avatar
cyrush committed
866
            // 2D edges that we must assemble into polygons and tessellate into
whitlocb's avatar
whitlocb committed
867
            // triangles that VisIt can digest.
cyrush's avatar
cyrush committed
868
            TesselateCells2D(domain, cellInfo, points, ugrid);
whitlocb's avatar
whitlocb committed
869 870
        }
        else if (minFaceSize <= 4 && maxFaceSize <= 4)
871
        {
872
#ifdef ENABLE_SUBDIVISION
cyrush's avatar
cyrush committed
873 874
            // If we're subdividing a single domain on the fly then we create
            // original cell numbers so we can use them in the GetVar method
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
            // to return only the cell values that we selected for this chunk
            // of the mesh.
            unsigned int oc[2] = {dom, 0};
            vtkUnsignedIntArray *origCells = 0;
            if(subdividingSingleMesh)
            {
                int useCount = 0;
                for(unsigned int i = 0; i < cellInfo.size(); ++i)
                    useCount += (cellInfo[i].id != -1) ? 1 : 0;
                origCells = vtkUnsignedIntArray::New();
                origCells->SetName("avtOriginalCellNumbers");
                origCells->SetNumberOfComponents(2);
                origCells->Allocate(useCount * 3);
                originalCells[dom] = origCells;
            }
#endif
891 892 893
            ugrid->SetPoints(points);
            // We have zoo elements that we can deal with.
            vtkCellArray *cellArray = vtkCellArray::New();
cyrush's avatar
cyrush committed
894
            intVector cellTypes;
895
            //bool unhandledCellType = false;
896
            for (unsigned int i = 0; i < cellInfo.size(); i++)
897
            {
cyrush's avatar
cyrush committed
898
                const CellInfo &ci = cellInfo[i];
899 900 901 902 903
                if(ci.id == -1)
                    continue;
#ifdef ENABLE_SUBDIVISION
                oc[1] = ci.id;
#endif
904 905
                switch(ci.faces.size())
                {
cyrush's avatar
cyrush committed
906
                    case 4 :
907 908 909 910 911
                        BuildTet(ci, cellArray, cellTypes);
#ifdef ENABLE_SUBDIVISION
                        if(subdividingSingleMesh)
                            origCells->InsertNextTupleValue(oc);
#endif
912
                        break;
cyrush's avatar
cyrush committed
913
                    case 5 :
914
                        {
bonnell's avatar
bonnell committed
915
                        size_t nNodes = 0;
916
                        for (size_t j = 0; j < ci.faces.size(); j++)
917 918 919
                        {
                            nNodes += ci.faces[j].nodes.size();
                        }
cyrush's avatar
cyrush committed
920
                        if (nNodes == 16) // Pyramid
921
                        {
922
                            BuildPyramid(ci, cellArray, cellTypes);
923 924 925 926 927
#ifdef ENABLE_SUBDIVISION
                            if(subdividingSingleMesh)
                                origCells->InsertNextTupleValue(oc);
#endif
                        }
928
                        else if (nNodes == 18) // Wedge
929
                        {
930
                            BuildWedge(ci, cellArray, cellTypes);
931 932 933 934 935
#ifdef ENABLE_SUBDIVISION
                            if(subdividingSingleMesh)
                                origCells->InsertNextTupleValue(oc);
#endif
                        }
936 937
                        //else
                        //    unhandledCellType = true;
938 939
                        break;
                        }
cyrush's avatar
cyrush committed
940
                    case 6 :
941 942 943 944 945
                        BuildHex(ci, cellArray, cellTypes);
#ifdef ENABLE_SUBDIVISION
                        if(subdividingSingleMesh)
                            origCells->InsertNextTupleValue(oc);
#endif
946
                        break;
cyrush's avatar
cyrush committed
947
                    default :
948
                        //unhandledCellType = true;
949 950 951 952 953 954 955
                        break;
                }
            }
            ugrid->SetCells(&cellTypes[0], cellArray);
            cellArray->Delete();
        }
        else
whitlocb's avatar
whitlocb committed
956
        {
957
            int t4 = visitTimer->StartTimer();
958
            TesselateCell(domain, cellInfo, points, ugrid);
959
            visitTimer->StopTimer(t4, "TesselateCell");
whitlocb's avatar
whitlocb committed
960
        }
961

962
        points->Delete();
whitlocb's avatar
whitlocb committed
963
    }
964 965 966 967 968 969 970 971 972
    CATCHALL
    {
        if(points != NULL)
            points->Delete();
        if(ugrid != NULL)
            ugrid->Delete();
    }
    ENDTRY

973
    visitTimer->StopTimer(t5, "GetMesh");
whitlocb's avatar
whitlocb committed
974
    return ugrid;
975 976 977 978 979 980
#endif
}

// ****************************************************************************
// Method: avtCCMFileFormat::ReadPoints
//
cyrush's avatar
cyrush committed
981
// Purpose:
982 983 984 985 986 987 988 989 990 991 992 993 994 995
//   Reads the points associated with a specified domain/mesh.
//
// Arguments:
//   dom         : The domain number.
//   meshname    : The name of the mesh.(for error reporting)
//
// Returns:    The vtkPoints object that contains the points.
//
// Note:       This method was broken out from the original GetMesh routine.
//
// Programmer: Kathleen Bonnell, Brad Whitlock
// Creation:   Thu Oct  1 13:29:03 PDT 2009
//
// Modifications:
cyrush's avatar
cyrush committed
996
//
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
// ****************************************************************************

vtkPoints *
avtCCMFileFormat::ReadPoints(int dom, const char *meshname)
{
    CCMIOID processor, vertices, topology, solution;
    bool hasSolution = true;
    if(!GetIDsForDomain(dom, processor, vertices, topology, solution,
                        hasSolution))
    {
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Read the size of the vertices
    CCMIOSize nnodes = 0;
    CCMIOEntitySize(&ccmErr, vertices, &nnodes, NULL);
    if(ccmErr != kCCMIONoErr)
    {
        debug4 << "CCMIOEntitySize for vertices failed with error " ;
        debug4 << ccmErr << endl;
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Read the dimensions of the vertex.
    int dims = 1;
    float scale;
    CCMIOReadVerticesf(&ccmErr, vertices, &dims, NULL, NULL, NULL, 0, 1);
    if(ccmErr != kCCMIONoErr)
    {
        debug4 << "CCMIOReadVertices for first vertex dimensions ";
        debug4 << "failed with error " << ccmErr << endl;
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Allocate VTK memory.
    vtkPoints *points = vtkPoints::New();
    points->SetNumberOfPoints(nnodes);
    float *pts = (float *)points->GetVoidPointer(0);

    // Read the data into the VTK points.
    CCMIOID mapID;
    if(dims == 2)
    {
        // Read 2D points and convert to 3D, storing into VTK.
        float *pts2d = new float[2 * nnodes];
        CCMIOReadVerticesf(&ccmErr, vertices, &dims, &scale, &mapID, pts2d,
                   0, nnodes);
        float *src = pts2d;
        float *dest = pts;
1046
        for(size_t i = 0; i < nnodes; ++i)
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
        {
            *dest++ = *src++;
            *dest++ = *src++;
            *dest++ = 0.;
        }
        delete [] pts2d;
    }
    else
    {
        // Read the data directly into the VTK buffer.
        CCMIOReadVerticesf(&ccmErr, vertices, &dims, &scale, &mapID, pts,
                   0, nnodes);
    }

cyrush's avatar
cyrush committed
1061
    // Scale the points, according to the scale factor read with the
1062
    // vertices.
1063
    for(size_t i = 0; i < nnodes; ++i)
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
    {
        pts[0] *= scale;
        pts[1] *= scale;
        pts[2] *= scale;
        pts += 3;
    }

    return points;
}

// ****************************************************************************
// Method: avtCCMFileFormat::ReadCellInfo
//
cyrush's avatar
cyrush committed
1077
// Purpose:
1078 1079 1080 1081 1082 1083 1084 1085 1086
//   Reads the cell info associated with a specified domain/mesh.
//
// Arguments:
//   dom         : The domain number.
//   meshname    : The name of the mesh.(for error reporting)
//   cellInfo    : The cell information to populate.
//   minFaceSize : Return value of the min face size.
//   maxFaceSize : Return value of the max face size.
//
cyrush's avatar
cyrush committed
1087
// Returns:
1088 1089
//
// Note:       This method was broken out from the original GetMesh routine.
cyrush's avatar
cyrush committed
1090
//             min/maxFaceSize are used to determine whether tesselation is
1091 1092 1093 1094 1095 1096
//             required.
//
// Programmer: Kathleen Bonnell, Brad Whitlock
// Creation:   Thu Oct  1 13:29:03 PDT 2009
//
// Modifications:
cyrush's avatar
cyrush committed
1097
//
1098 1099 1100
//   Hank Childs, Tue Mar 16 21:04:16 PDT 2010
//   Remove STL slowness, possibly n^2 algorithm.
//
1101 1102 1103 1104 1105 1106
// ****************************************************************************

void
avtCCMFileFormat::ReadCellInfo(int dom, const char *meshname,
    CellInfoVector &cellInfo, int &minFaceSize, int &maxFaceSize)
{
1107
    int t1 = visitTimer->StartTimer();
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
    CCMIOID processor, vertices, topology, solution;
    bool hasSolution = true;
    if(!GetIDsForDomain(dom, processor, vertices, topology, solution,
                       hasSolution))
    {
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Read the size of the vertices
    CCMIOSize nnodes = 0;
    CCMIOEntitySize(&ccmErr, vertices, &nnodes, NULL);
    if(ccmErr != kCCMIONoErr)
    {
        debug4 << "CCMIOEntitySize for vertices failed with error " ;
        debug4 << ccmErr << endl;
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Read the dimensions of the vertex and get the mapID
    int dims = 1;
    CCMIOID mapID;
    CCMIOReadVerticesf(&ccmErr, vertices, &dims, NULL, &mapID, NULL, 0, 1);
    if(ccmErr != kCCMIONoErr)
    {
        debug4 << "CCMIOReadVertices for first vertex dimensions ";
        debug4 << "failed with error " << ccmErr << endl;
        EXCEPTION1(InvalidVariableException, meshname);
    }

    // Read the vertex ids
    intVector tmpVertexMap(nnodes);
    CCMIOReadMap(&ccmErr, mapID, &tmpVertexMap[0], kCCMIOStart, kCCMIOEnd);
    IDMap  vertexIDMap;
    vertexIDMap.SetIDs(tmpVertexMap);
    tmpVertexMap.clear();

    // Get the topology information
    CCMIOID faceID, cellsID;
1146
    unsigned int nIFaces = 0, nCells = 0/*, size = 0*/;
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
    intVector cells;
    //intVector cellMatType;

    // Read the cells entity
    CCMIOGetEntity(&ccmErr, topology, kCCMIOCells, 0, &cellsID);
    // Read the cells entity size (num cells)
    CCMIOEntitySize(&ccmErr, cellsID, &nCells, NULL);
    cells.resize(nCells);
    cellInfo.resize(nCells);
    //cellMatType.resize(nCells);
    // this gets the cell types and the map that stores the cell ids
    CCMIOReadCells(&ccmErr, cellsID, &mapID, NULL,
                   kCCMIOStart, kCCMIOEnd);
    // this reads the cellids from the map.
    CCMIOReadMap(&ccmErr, mapID, &cells[0], kCCMIOStart, kCCMIOEnd);
1162
    for (size_t i = 0; i < nCells; ++i)
1163 1164 1165 1166 1167 1168 1169
        cellInfo[i].id = cells[i];

    IDMap cellIDMap;
    cellIDMap.SetIDs(cells);

    // Read the boundary faces.
    int index = 0;
1170
    //int count = 0;
1171
    int nBoundaries = 0;
cyrush's avatar
cyrush committed
1172
    while (CCMIONextEntity(NULL, topology, kCCMIOBoundaryFaces, &index,
1173 1174 1175 1176
                           &faceID) == kCCMIONoErr)
    {
        nBoundaries++;
    }
cyrush's avatar
cyrush committed
1177

1178
    index = 0;
cyrush's avatar
cyrush committed
1179
    while (CCMIONextEntity(NULL, topology, kCCMIOBoundaryFaces, &index,
1180 1181 1182 1183
                           &faceID) == kCCMIONoErr)
    {
        CCMIOSize nBFaces;
        CCMIOEntitySize(&ccmErr, faceID, &nBFaces, NULL);
cyrush's avatar
cyrush committed
1184
        GetFaces(faceID, kCCMIOBoundaryFaces, nBFaces,
1185
                 cellIDMap, vertexIDMap,
cyrush's avatar
cyrush committed
1186
                 minFaceSize, maxFaceSize, cellInfo);
1187 1188 1189 1190 1191 1192 1193
    }

    // Read the internal faces.
    // Get the InternalFaces entity.
    CCMIOGetEntity(&ccmErr, topology, kCCMIOInternalFaces, 0, &faceID);
    // Get the InternalFaces size (num faces).
    CCMIOEntitySize(&ccmErr, faceID, &nIFaces, NULL);
cyrush's avatar
cyrush committed
1194

1195 1196 1197
    visitTimer->StopTimer(t1, "CCM I/O calls (2)");
    int t2 = visitTimer->StartTimer();

1198 1199
    GetFaces(faceID, kCCMIOInternalFaces, nIFaces, cellIDMap, vertexIDMap,
             minFaceSize, maxFaceSize, cellInfo);
1200
    visitTimer->StopTimer(t2, "GetFaces");