avtEnzoFileFormat.C 69.9 KB
Newer Older
hrchilds's avatar
hrchilds committed
1 2
/*****************************************************************************
*
brugger's avatar
 
brugger committed
3
* Copyright (c) 2000 - 2011, Lawrence Livermore National Security, LLC
hrchilds's avatar
hrchilds committed
4
* Produced at the Lawrence Livermore National Laboratory
brugger's avatar
 
brugger committed
5
* LLNL-CODE-442911
hrchilds's avatar
hrchilds committed
6 7
* All rights reserved.
*
brugger's avatar
 
brugger committed
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
hrchilds's avatar
hrchilds 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
brugger's avatar
 
brugger committed
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
hrchilds's avatar
hrchilds 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
brugger's avatar
 
brugger committed
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
hrchilds's avatar
hrchilds committed
30 31 32 33 34 35 36 37 38
* 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.
*
*****************************************************************************/

hrchilds's avatar
hrchilds committed
39 40 41 42 43 44
// ************************************************************************* //
//                            avtEnzoFileFormat.C                           //
// ************************************************************************* //

#include <avtEnzoFileFormat.h>

45 46
#include <visit-config.h>

47 48 49
#include <string>
#include <vector>

hrchilds's avatar
hrchilds committed
50 51 52 53
#include <vtkFloatArray.h>
#include <vtkRectilinearGrid.h>
#include <vtkUnstructuredGrid.h>
#include <vtkDataSetWriter.h>
hrchilds's avatar
hrchilds committed
54
#include <vtkCellType.h>
hrchilds's avatar
hrchilds committed
55

hrchilds's avatar
hrchilds committed
56
#include <avtDatabase.h>
hrchilds's avatar
hrchilds committed
57 58 59 60
#include <avtDatabaseMetaData.h>
#include <avtStructuredDomainBoundaries.h>
#include <avtStructuredDomainNesting.h>
#include <avtVariableCache.h>
hrchilds's avatar
hrchilds committed
61
#include <avtIntervalTree.h>
62
#include <avtResolutionSelection.h>
hrchilds's avatar
hrchilds committed
63 64 65
#include <InvalidVariableException.h>
#include <InvalidFilesException.h>
#include <Expression.h>
hrchilds's avatar
hrchilds committed
66
#include <DebugStream.h>
67
#include <StringHelpers.h>
hrchilds's avatar
hrchilds committed
68

69
#ifdef HAVE_LIBHDF4
70 71
#include <hdf.h>
#include <mfhdf.h>
72
#endif
73 74

#ifdef HAVE_LIBHDF5
75 76 77 78 79 80 81
// Define this symbol BEFORE including hdf5.h to indicate the HDF5 code
// in this file uses version 1.6 of the HDF5 API. This is harmless for
// versions of HDF5 before 1.8 and ensures correct compilation with
// version 1.8 and thereafter. When, and if, the HDF5 code in this file
// is explicitly upgraded to the 1.8 API, this symbol should be removed.
#define H5_USE_16_API
#include <hdf5.h>
82
#include <visit-hdf5.h>
83
#endif
hrchilds's avatar
hrchilds committed
84

hrchilds's avatar
hrchilds committed
85
using std::string;
86
using std::vector;
hrchilds's avatar
hrchilds committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

void avtEnzoFileFormat::Grid::PrintRecursive(vector<Grid> &grids, int level)
{
    string indent(level*3, ' ');
    cerr << indent << ID << endl;
    for (int i=0; i<childrenID.size(); i++)
    {
        grids[childrenID[i]].PrintRecursive(grids,level+1);
    }
}

void avtEnzoFileFormat::Grid::Print()
{
    cerr << "ID:        "<<ID<<endl;
    cerr << "zdims:     "<<zdims[0]<<","<<zdims[1]<<","<<zdims[2]<<endl;
    cerr << "minSpatialExtents:"<<minSpatialExtents[0]<<","<<minSpatialExtents[1]<<","<<minSpatialExtents[2]<<endl;
    cerr << "maxSpatialExtents:"<<maxSpatialExtents[0]<<","<<maxSpatialExtents[1]<<","<<maxSpatialExtents[2]<<endl;
    cerr << "parentID:  "<<parentID<<endl;
    cerr << "level:     "<<level<<endl;
    cerr << "parMinExt: "<<minLogicalExtentsInParent[0]<<","<<minLogicalExtentsInParent[1]<<","<<minLogicalExtentsInParent[2]<<endl;
    cerr << "parMaxExt: "<<maxLogicalExtentsInParent[0]<<","<<maxLogicalExtentsInParent[1]<<","<<maxLogicalExtentsInParent[2]<<endl;
    cerr << "globMinExt:"<<minLogicalExtentsGlobally[0]<<","<<minLogicalExtentsGlobally[1]<<","<<minLogicalExtentsGlobally[2]<<endl;
    cerr << "globMaxExt:"<<maxLogicalExtentsGlobally[0]<<","<<maxLogicalExtentsGlobally[1]<<","<<maxLogicalExtentsGlobally[2]<<endl;
    cerr << "parRatio:  "<<refinementRatio[0]<<","<<refinementRatio[1]<<","<<refinementRatio[2]<<endl;
111 112
    cerr << "gridFileName:"<<gridFileName<<endl;
    cerr << "particleFileName:"<<particleFileName<<endl;
hrchilds's avatar
hrchilds committed
113 114 115
    cerr << endl;
}

hrchilds's avatar
hrchilds committed
116 117 118 119 120 121 122 123 124 125
// ****************************************************************************
//  Method:  avtEnzoFileFormat::Grid::DetermineExtentsInParent
//
//  Purpose:
//    Use our spatial extents and the spatial extents of our parent, as well
//    as our dimensions, to determine our logical extents within our parent.
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  3, 2005
//
hrchilds's avatar
hrchilds committed
126 127 128 129
//  Modifications:
//    Jeremy Meredith, Wed Feb 23 15:18:48 PST 2005
//    May have multiple root grids; identify by parentID==0, not by ID==1.
//
hrchilds's avatar
hrchilds committed
130 131 132
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.
//
hrchilds's avatar
hrchilds committed
133 134 135
//    Jeremy Meredith, Thu Aug 11 14:35:00 PDT 2005
//    Fixed logical extents when there are multiple root grids.
//
hrchilds's avatar
hrchilds committed
136 137 138 139
//    Eric Brugger, Tue Oct 17 09:49:26 PDT 2006
//    Removed coding to throw an exception if a non 2:1 refinement ratio
//    was encountered.
//
hrchilds's avatar
hrchilds committed
140
// ****************************************************************************
hrchilds's avatar
hrchilds committed
141 142
void avtEnzoFileFormat::Grid::DetermineExtentsInParent(vector<Grid> &grids)
{
hrchilds's avatar
hrchilds committed
143
    if (parentID != 0)
hrchilds's avatar
hrchilds committed
144
    {
hrchilds's avatar
hrchilds committed
145
        Grid &p = grids[parentID];
hrchilds's avatar
hrchilds committed
146 147
        minLogicalExtentsInParent[0] = int(.5 + double(p.zdims[0]) * (minSpatialExtents[0] - p.minSpatialExtents[0])/(p.maxSpatialExtents[0] - p.minSpatialExtents[0]));
        maxLogicalExtentsInParent[0] = int(.5 + double(p.zdims[0]) * (maxSpatialExtents[0] - p.minSpatialExtents[0])/(p.maxSpatialExtents[0] - p.minSpatialExtents[0]));
hrchilds's avatar
hrchilds committed
148
        minLogicalExtentsInParent[1] = int(.5 + double(p.zdims[1]) * (minSpatialExtents[1] - p.minSpatialExtents[1])/(p.maxSpatialExtents[1] - p.minSpatialExtents[1]));
hrchilds's avatar
hrchilds committed
149
        maxLogicalExtentsInParent[1] = int(.5 + double(p.zdims[1]) * (maxSpatialExtents[1] - p.minSpatialExtents[1])/(p.maxSpatialExtents[1] - p.minSpatialExtents[1]));
hrchilds's avatar
hrchilds committed
150 151 152 153 154 155 156 157 158 159 160
        if (dimension == 3)
        {
            minLogicalExtentsInParent[2] = int(.5 + double(p.zdims[2]) * (minSpatialExtents[2] - p.minSpatialExtents[2])/(p.maxSpatialExtents[2] - p.minSpatialExtents[2]));
            maxLogicalExtentsInParent[2] = int(.5 + double(p.zdims[2]) * (maxSpatialExtents[2] - p.minSpatialExtents[2])/(p.maxSpatialExtents[2] - p.minSpatialExtents[2]));
        }
        else
        {
            minLogicalExtentsInParent[2] = 0;
            maxLogicalExtentsInParent[2] = 0;
        }

hrchilds's avatar
hrchilds committed
161 162
        refinementRatio[0] = double(zdims[0]) / double(maxLogicalExtentsInParent[0]-minLogicalExtentsInParent[0]);
        refinementRatio[1] = double(zdims[1]) / double(maxLogicalExtentsInParent[1]-minLogicalExtentsInParent[1]);
hrchilds's avatar
hrchilds committed
163 164 165 166
        if (dimension == 3)
            refinementRatio[2] = double(zdims[2]) / double(maxLogicalExtentsInParent[2]-minLogicalExtentsInParent[2]);
        else
            refinementRatio[2] = 1;
hrchilds's avatar
hrchilds committed
167 168 169
    }
    else
    {
hrchilds's avatar
hrchilds committed
170 171 172 173 174 175 176 177 178 179
        Grid &p = grids[0];

        double xpct = (maxSpatialExtents[0] - minSpatialExtents[0])/(p.maxSpatialExtents[0] - p.minSpatialExtents[0]);
        minLogicalExtentsInParent[0] = int(.5 + (double(zdims[0])/xpct) * (minSpatialExtents[0] - p.minSpatialExtents[0])/(p.maxSpatialExtents[0] - p.minSpatialExtents[0]));
        maxLogicalExtentsInParent[0] = int(.5 + (double(zdims[0])/xpct) * (maxSpatialExtents[0] - p.minSpatialExtents[0])/(p.maxSpatialExtents[0] - p.minSpatialExtents[0]));

        double ypct = (maxSpatialExtents[1] - minSpatialExtents[1])/(p.maxSpatialExtents[1] - p.minSpatialExtents[1]);
        minLogicalExtentsInParent[1] = int(.5 + (double(zdims[1])/ypct) * (minSpatialExtents[1] - p.minSpatialExtents[1])/(p.maxSpatialExtents[1] - p.minSpatialExtents[1]));
        maxLogicalExtentsInParent[1] = int(.5 + (double(zdims[1])/ypct) * (maxSpatialExtents[1] - p.minSpatialExtents[1])/(p.maxSpatialExtents[1] - p.minSpatialExtents[1]));

hrchilds's avatar
hrchilds committed
180
        if (dimension == 3)
hrchilds's avatar
hrchilds committed
181 182 183 184 185
        {
            double zpct = (maxSpatialExtents[2] - minSpatialExtents[2])/(p.maxSpatialExtents[2] - p.minSpatialExtents[2]);
            minLogicalExtentsInParent[2] = int(.5 + (double(zdims[2])/zpct) * (minSpatialExtents[2] - p.minSpatialExtents[2])/(p.maxSpatialExtents[2] - p.minSpatialExtents[2]));
            maxLogicalExtentsInParent[2] = int(.5 + (double(zdims[2])/zpct) * (maxSpatialExtents[2] - p.minSpatialExtents[2])/(p.maxSpatialExtents[2] - p.minSpatialExtents[2]));
        }
hrchilds's avatar
hrchilds committed
186
        else
hrchilds's avatar
hrchilds committed
187 188
        {
            minLogicalExtentsInParent[2] = 0;
hrchilds's avatar
hrchilds committed
189
            maxLogicalExtentsInParent[2] = 0;
hrchilds's avatar
hrchilds committed
190 191
        }

hrchilds's avatar
hrchilds committed
192 193 194 195
        refinementRatio[0] = refinementRatio[1] = refinementRatio[2] = 1;
    }
}

hrchilds's avatar
hrchilds committed
196 197 198 199 200 201 202 203 204 205
// ****************************************************************************
//  Method:  avtEnzoFileFormat::Grid::DetermineExtentsGlobally
//
//  Purpose:
//    Use the global extents from the parent, and our local extens within
//    our parent, to determine our global extents.
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  3, 2005
//
hrchilds's avatar
hrchilds committed
206 207 208 209
//  Modifications:
//    Jeremy Meredith, Wed Feb 23 15:18:48 PST 2005
//    May have multiple root grids; identify by parentID==0, not by ID==1.
//
hrchilds's avatar
hrchilds committed
210 211 212
//    Jeremy Meredith, Thu Aug 11 14:35:00 PDT 2005
//    Fixed logical extents when there are multiple root grids.
//
hrchilds's avatar
hrchilds committed
213 214 215 216
// ****************************************************************************
void
avtEnzoFileFormat::Grid::DetermineExtentsGlobally(int numLevels,
                                                  vector<Grid> &grids)
hrchilds's avatar
hrchilds committed
217
{
hrchilds's avatar
hrchilds committed
218
    if (parentID != 0)
hrchilds's avatar
hrchilds committed
219
    {
hrchilds's avatar
hrchilds committed
220
        Grid &p = grids[parentID];
hrchilds's avatar
hrchilds committed
221 222 223 224 225 226 227 228 229
        minLogicalExtentsGlobally[0] = int((p.minLogicalExtentsGlobally[0] + minLogicalExtentsInParent[0])*refinementRatio[0]);
        minLogicalExtentsGlobally[1] = int((p.minLogicalExtentsGlobally[1] + minLogicalExtentsInParent[1])*refinementRatio[1]);
        minLogicalExtentsGlobally[2] = int((p.minLogicalExtentsGlobally[2] + minLogicalExtentsInParent[2])*refinementRatio[2]);
        maxLogicalExtentsGlobally[0] = int((p.minLogicalExtentsGlobally[0] + maxLogicalExtentsInParent[0])*refinementRatio[0]);
        maxLogicalExtentsGlobally[1] = int((p.minLogicalExtentsGlobally[1] + maxLogicalExtentsInParent[1])*refinementRatio[1]);
        maxLogicalExtentsGlobally[2] = int((p.minLogicalExtentsGlobally[2] + maxLogicalExtentsInParent[2])*refinementRatio[2]);
    }
    else
    {
hrchilds's avatar
hrchilds committed
230 231 232 233 234 235
        minLogicalExtentsGlobally[0] = minLogicalExtentsInParent[0];
        minLogicalExtentsGlobally[1] = minLogicalExtentsInParent[1];
        minLogicalExtentsGlobally[2] = minLogicalExtentsInParent[2];
        maxLogicalExtentsGlobally[0] = maxLogicalExtentsInParent[0];
        maxLogicalExtentsGlobally[1] = maxLogicalExtentsInParent[1];
        maxLogicalExtentsGlobally[2] = maxLogicalExtentsInParent[2];
hrchilds's avatar
hrchilds committed
236 237 238
    }
}

hrchilds's avatar
hrchilds committed
239 240 241 242 243 244 245 246 247 248 249 250
// ****************************************************************************
//  Method:  avtEnzoFileFormat::ReadHierachyFile
//
//  Purpose:
//    Read the .hierarchy file and get the grid/level hierarchy.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
hrchilds's avatar
hrchilds committed
251 252 253 254
//  Modifications:
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.
//
hrchilds's avatar
hrchilds committed
255 256 257 258 259 260
//    Jeremy Meredith, Thu Aug 11 16:59:19 PDT 2005
//    Moved the determination of the grid logical extents up a level
//    (to ReadAllMetaData), because when there are multiple root-
//    level grids, all of the root level grid extents must be unified
//    to determine any individual grid's logical extents.
//
hrchilds's avatar
hrchilds committed
261 262 263 264
//    Jeremy Meredith, Fri Oct 14 14:34:54 PDT 2005
//    Fixed bug where the last line of the .hierarchy file was assumed
//    to be a known item.
//
265 266 267 268
//    Jeremy Meredith, Mon Apr  6 14:36:58 EDT 2009
//    Added support for particle and grid file names.
//    This is for support for the new "Packed AMR" format.
//
hrchilds's avatar
hrchilds committed
269
// ****************************************************************************
hrchilds's avatar
hrchilds committed
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
void
avtEnzoFileFormat::ReadHierachyFile()
{

    // PARSE HIERARCHY

    ifstream h(fnameH.c_str());
    if (!h)
        EXCEPTION1(InvalidFilesException, fnameH.c_str());

    // Set something reasonable for a grid with id==0
    Grid root;
    root.ID = 0;
    root.level = -1;
    root.parentID = -1;
hrchilds's avatar
hrchilds committed
285
    root.dimension = dimension;
hrchilds's avatar
hrchilds committed
286 287 288 289 290
    root.minSpatialExtents[0] = root.minSpatialExtents[1] = root.minSpatialExtents[2] = -1e37;
    root.maxSpatialExtents[0] = root.maxSpatialExtents[1] = root.maxSpatialExtents[2] = 1e37;
    root.minLogicalExtentsGlobally[0] = 0;
    root.minLogicalExtentsGlobally[1] = 0;
    root.minLogicalExtentsGlobally[2] = 0;
291 292
    root.gridFileName = "";
    root.particleFileName = "";
hrchilds's avatar
hrchilds committed
293 294 295 296 297 298 299
    grids.push_back(root);

    string buff = "";
    int level = 0;
    int parent = 0;
    while (h)
    {
hrchilds's avatar
hrchilds committed
300
        while (h && buff != "Grid" && buff != "Pointer:" && buff != "Time")
hrchilds's avatar
hrchilds committed
301 302 303 304
            h >> buff;
        if (buff == "Grid")
        {
            Grid g;
hrchilds's avatar
hrchilds committed
305 306
            g.dimension = dimension;

hrchilds's avatar
hrchilds committed
307 308 309 310 311 312 313 314 315 316
            h >> buff; // '='
            h >> g.ID;

            int min3[3];
            int max3[3];
            while (buff != "GridStartIndex")
            {
                h >> buff;
            }
            h >> buff; // '='
hrchilds's avatar
hrchilds committed
317 318 319 320 321 322

            if (dimension == 3)
                h >> min3[0] >> min3[1] >> min3[2];
            else
                h >> min3[0] >> min3[1];

hrchilds's avatar
hrchilds committed
323 324 325 326 327
            while (buff != "GridEndIndex")
            {
                h >> buff;
            }
            h >> buff; // '='
hrchilds's avatar
hrchilds committed
328 329 330 331 332

            if (dimension == 3)
                h >> max3[0] >> max3[1] >> max3[2];
            else
                h >> max3[0] >> max3[1];
hrchilds's avatar
hrchilds committed
333 334 335

            g.zdims[0] = max3[0]-min3[0] + 1;
            g.zdims[1] = max3[1]-min3[1] + 1;
hrchilds's avatar
hrchilds committed
336 337 338 339
            if (dimension == 3)
                g.zdims[2] = max3[2]-min3[2] + 1;
            else
                g.zdims[2] = 1;
hrchilds's avatar
hrchilds committed
340 341 342

            g.ndims[0] = g.zdims[0]+1;
            g.ndims[1] = g.zdims[1]+1;
hrchilds's avatar
hrchilds committed
343 344 345 346
            if (dimension == 3)
                g.ndims[2] = g.zdims[2]+1;
            else
                g.ndims[2] = 1;
hrchilds's avatar
hrchilds committed
347 348 349 350 351 352

            while (buff != "GridLeftEdge")
            {
                h >> buff;
            }
            h >> buff; // '='
hrchilds's avatar
hrchilds committed
353 354 355 356 357 358 359 360

            if (dimension == 3)
                h >> g.minSpatialExtents[0] >> g.minSpatialExtents[1] >> g.minSpatialExtents[2];
            else
            {
                h >> g.minSpatialExtents[0] >> g.minSpatialExtents[1];
                g.minSpatialExtents[2] = 0;
            }
hrchilds's avatar
hrchilds committed
361 362 363 364 365 366

            while (buff != "GridRightEdge")
            {
                h >> buff;
            }
            h >> buff; // '='
hrchilds's avatar
hrchilds committed
367 368 369 370 371 372 373 374

            if (dimension == 3)
                h >> g.maxSpatialExtents[0] >> g.maxSpatialExtents[1] >> g.maxSpatialExtents[2];
            else
            {
                h >> g.maxSpatialExtents[0] >> g.maxSpatialExtents[1];
                g.maxSpatialExtents[2] = 0;
            }
hrchilds's avatar
hrchilds committed
375

376 377 378 379 380 381 382 383 384 385
            string fullpath;
            while (buff != "BaryonFileName")
            {
                h >> buff;
            }
            h >> buff; // '='
            h >> fullpath;
            g.gridFileName = fname_dir + "/" +
                    StringHelpers::Basename(fullpath.c_str());

hrchilds's avatar
hrchilds committed
386 387 388 389 390 391 392
            while (buff != "NumberOfParticles")
            {
                h >> buff;
            }
            h >> buff; // '='
            h >> g.numberOfParticles;

393 394 395 396 397 398 399 400 401 402 403 404
            if (g.numberOfParticles > 0)
            {
                while (buff != "ParticleFileName")
                {
                    h >> buff;
                }
                h >> buff; // '='
                h >> fullpath;
                g.particleFileName = fname_dir + "/" +
                    StringHelpers::Basename(fullpath.c_str());
            }

hrchilds's avatar
hrchilds committed
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
            g.level = level;
            g.parentID = parent;

            if (grids.size() != g.ID)
            {
                EXCEPTION2(InvalidFilesException, fnameH.c_str(),
                           "The grids in the hierarchy are currently "
                           "expected to be listed in order.");
            }

            grids.push_back(g);
            grids[parent].childrenID.push_back(g.ID);
            numGrids = grids.size()-1;
        }
        else if (buff == "Pointer:")
        {
            char c;
            buff = "";
            while ((c=h.get()) != '[');
            while ((c=h.get()) != ']') buff += c;
            int gridID = atoi(buff.c_str());
            h.get(); // -
            h.get(); // >
            h >> buff;
            if (buff == "NextGridNextLevel")
            {
                h >> buff; // '='
                int n;
                h >> n;
                if (n == 0)
                {
                }
                else
                {
                    level = grids[gridID].level + 1;
                    numLevels = level+1 > numLevels ? level+1 : numLevels;
                    parent = gridID;
                }
            }
            else // buff == "NextGridThisLevel"
            {
                h >> buff; // '='
                int n;
                h >> n;
                if (n == 0)
                {
                }
                else
                {
                }
            }
        }
        else if (buff == "Time")
        {
            h >> buff; // '='
            h >> curTime;
        }
        h >> buff;
    }
    h.close();
}

hrchilds's avatar
hrchilds committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480
// ****************************************************************************
//  Method:  avtEnzoFileFormat::ReadParameterFile
//
//  Purpose:
//    The parameter file is the one without an extension, and it
//    has some problem setup stuff in it.  We are currently only
//    using it to get the cycle and time.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
hrchilds's avatar
hrchilds committed
481 482 483 484
//  Modifications:
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.
//
hrchilds's avatar
hrchilds committed
485
// ****************************************************************************
hrchilds's avatar
hrchilds committed
486 487 488 489 490 491 492 493
void
avtEnzoFileFormat::ReadParameterFile()
{
    // PARSE PARAMETER FILE

    ifstream r(fname_base.c_str());
    if (!r)
        EXCEPTION2(InvalidFilesException, fname_base.c_str(),
hrchilds's avatar
hrchilds committed
494
                   "This parameter file did not exist.");
hrchilds's avatar
hrchilds committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509

    string buff("");
    while (r)
    {
        r >> buff;
        if (buff == "InitialCycleNumber")
        {
            r >> buff; // '='
            r >> curCycle;
        }
        else if (buff == "InitialTime")
        {
            r >> buff; // '='
            r >> curTime;
        }
hrchilds's avatar
hrchilds committed
510 511 512 513 514
        else if (buff == "TopGridRank")
        {
            r >> buff; // '='
            r >> dimension;
        }
hrchilds's avatar
hrchilds committed
515 516 517 518
    }
    r.close();
}

hrchilds's avatar
hrchilds committed
519
// ****************************************************************************
hrchilds's avatar
hrchilds committed
520
//  Method:  avtEnzoFileFormat::DetermineVariablesFromGridFile
hrchilds's avatar
hrchilds committed
521 522 523 524 525 526 527 528 529 530 531
//
//  Purpose:
//    Find the smallest grid that contains some particles, or just the smallest
//    grid if none have any particles.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
hrchilds's avatar
hrchilds committed
532 533 534 535
//  Modifications:
//    Jeremy Meredith, Fri Feb 11 18:15:49 PST 2005
//    Added HDF5 support.
//
hrchilds's avatar
hrchilds committed
536 537 538
//    Brad Whitlock, Mon Apr 3 11:04:09 PDT 2006
//    Added tracer particle support.
//
539 540
//    Mark C. Miller, Fri Mar 20 16:07:14 PST 2009
//    Made HDF5 related code conditionally compiled on HAVE_LIBHDF5
541 542 543 544 545 546 547
//
//    Jeremy Meredith, Mon Apr  6 14:36:58 EDT 2009
//    Added support for explicit particle and grid file names.
//    Also, try to descend into a top-level Group if its name
//    matches the format for a grid-group in the new format.
//    This is for support for the new "Packed AMR" format.
//
548 549 550 551
//    Jeremy Meredith, Wed Jan  6 14:57:18 EST 2010
//    Make HDF4 code conditionally compiled so we can support an
//    HDF5-only build for this plugin as well.
//
hrchilds's avatar
hrchilds committed
552
// ****************************************************************************
hrchilds's avatar
hrchilds committed
553 554 555 556 557
void
avtEnzoFileFormat::DetermineVariablesFromGridFile()
{
    int smallest_grid = 0;
    int smallest_grid_nzones = INT_MAX;
hrchilds's avatar
hrchilds committed
558
    bool found_grid_with_particles = false;
hrchilds's avatar
hrchilds committed
559 560 561
    for (int i=1; i<grids.size(); i++)
    {
        Grid &g = grids[i];
hrchilds's avatar
hrchilds committed
562 563 564
        if (found_grid_with_particles && g.numberOfParticles <= 0)
            continue;

hrchilds's avatar
hrchilds committed
565
        int numZones = g.zdims[0]*g.zdims[1]*g.zdims[2];
hrchilds's avatar
hrchilds committed
566 567
        if ((!found_grid_with_particles && g.numberOfParticles > 0) ||
            (numZones < smallest_grid_nzones))
hrchilds's avatar
hrchilds committed
568
        {
hrchilds's avatar
hrchilds committed
569 570 571 572 573 574 575
            if (!found_grid_with_particles ||
                (found_grid_with_particles && g.numberOfParticles > 0))
            {
                smallest_grid_nzones = numZones;
                smallest_grid = g.ID;
                found_grid_with_particles = (g.numberOfParticles > 0);
            }
hrchilds's avatar
hrchilds committed
576 577 578
        }
    }

579
    string gridFileName = grids[smallest_grid].gridFileName;
hrchilds's avatar
hrchilds committed
580
    debug3 << "Smallest Enzo grid with particles was # "<<smallest_grid<<endl;
hrchilds's avatar
hrchilds committed
581

582
#ifdef HAVE_LIBHDF4
583
    int32 file_handle = SDstart(gridFileName.c_str(), DFACC_READ);
hrchilds's avatar
hrchilds committed
584
    if (file_handle >= 0)
hrchilds's avatar
hrchilds committed
585
    {
hrchilds's avatar
hrchilds committed
586 587 588 589 590
        fileType = ENZO_FT_HDF4;

        int32 n_datasets;
        int32 n_file_attrs;
        SDfileinfo(file_handle, &n_datasets, &n_file_attrs);
hrchilds's avatar
hrchilds committed
591

hrchilds's avatar
hrchilds committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
        for (int var = 0 ; var < n_datasets ; var++)
        {
            int32 ndims;
            int32 dims[3];
            int32 data_type;
            char  name[65];
            int32 nattrs;
            int32 var_handle = SDselect(file_handle, var);
            SDgetinfo(var_handle, name, &ndims, dims, &data_type, &nattrs);
            SDendaccess(var_handle);
            if (ndims > 1)
            {
                // it's a normal mesh variable
                varNames.push_back(name);
            }
            else if (strlen(name) > 8 && strncmp(name,"particle",8)==0)
            {
                // it's a particle variable; skip over coordinate arrays
                if (strncmp(name,"particle_position_",18) != 0)
                {
                    particleVarNames.push_back(name);
                }
            }
hrchilds's avatar
hrchilds committed
615 616 617 618 619 620 621 622 623
            else if (strlen(name) > 16 &&
                     strncmp(name,"tracer_particles",16)==0)
            {
                // it's a particle variable; skip over coordinate arrays
                if (strncmp(name,"tracer_particle_position_",25) != 0)
                {
                    tracerparticleVarNames.push_back(name);
                }
            }
hrchilds's avatar
hrchilds committed
624
        }
hrchilds's avatar
hrchilds committed
625

626
        SDend(file_handle);
hrchilds's avatar
hrchilds committed
627 628
    }
    else
629
#endif
hrchilds's avatar
hrchilds committed
630
    {
bonnell's avatar
bonnell committed
631
#ifdef HAVE_LIBHDF5
632
        hid_t fileId = H5Fopen(gridFileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
hrchilds's avatar
hrchilds committed
633
        if (fileId < 0)
hrchilds's avatar
hrchilds committed
634
        {
635
#ifdef HAVE_LIBHDF4
636
            EXCEPTION1(InvalidFilesException, gridFileName.c_str());
637 638 639 640 641 642 643
#else
            EXCEPTION2(InvalidFilesException, gridFileName.c_str(),
                       "The HDF5 library failed to open this file and this"
                       "installation of the Enzo plugin is NOT compiled with "
                       "HDF4 support. So, the file may be an HDF4 file but if "
                       "so, it cannot be opened with this installation.");
#endif
hrchilds's avatar
hrchilds committed
644
        }
hrchilds's avatar
hrchilds committed
645 646 647 648 649 650 651 652 653

        fileType = ENZO_FT_HDF5;

        // NOTE: H5Gget_num_objs fails using a file id in HDF51.6.0, but
        //       works correctly (as the documentation says it should) in
        //       1.6.3.  Since we're going for portability, just open the
        //       darn root group and use that instead.
        hid_t rootId = H5Gopen(fileId, "/");

654 655 656
        // Make a pass over the contents of the root directory
        // looking for a group corresponding to our grid name, and
        // open it if necessary.
hrchilds's avatar
hrchilds committed
657 658
        hsize_t n_objs;
        H5Gget_num_objs(rootId, &n_objs);
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
        for (int var = 0 ; var < n_objs ; var++)
        {
            if (H5Gget_objtype_by_idx(rootId, var) == H5G_GROUP)
            {
                int gridindex;
                char  name[65];
                H5Gget_objname_by_idx(rootId, var, name, 64);
                if (sscanf(name, "Grid%d", &gridindex) == 1 &&
                    gridindex == smallest_grid)
                {
                    rootId = H5Gopen(rootId, name);
                    break;
                }
            }
        }

        // In case we opened a subdirectory, get the num items again.
        H5Gget_num_objs(rootId, &n_objs);
hrchilds's avatar
hrchilds committed
677

678
        // Okay, actually do the parsing work.
hrchilds's avatar
hrchilds committed
679
        for (int var = 0 ; var < n_objs ; var++)
hrchilds's avatar
hrchilds committed
680
        {
hrchilds's avatar
hrchilds committed
681
            if (H5Gget_objtype_by_idx(rootId, var) == H5G_DATASET)
hrchilds's avatar
hrchilds committed
682
            {
hrchilds's avatar
hrchilds committed
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
                char  name[65];
                H5Gget_objname_by_idx(rootId, var, name, 64);

                // NOTE: to do the same diligence as HDF4 here, we should
                // really H5Dopen, H5Dget_space, H5Sget_simple_extent_ndims
                // and make sure it is a 3D (or 2D?) object before assuming
                // it is a mesh variable.  For now, assume away!
                if (strlen(name) > 8 && strncmp(name,"particle",8)==0)
                {
                    // it's a particle variable; skip over coordinate arrays
                    if (strncmp(name,"particle_position_",18) != 0)
                    {
                        particleVarNames.push_back(name);
                    }
                }
hrchilds's avatar
hrchilds committed
698 699 700 701 702 703 704 705 706
                else if (strlen(name) > 16 &&
                         strncmp(name,"tracer_particles",16)==0)
                {
                    // it's a particle variable; skip over coordinate arrays
                    if (strncmp(name,"tracer_particle_position_",25) != 0)
                    {
                        tracerparticleVarNames.push_back(name);
                    }
                }
hrchilds's avatar
hrchilds committed
707 708 709 710
                else
                {
                    varNames.push_back(name);
                }
hrchilds's avatar
hrchilds committed
711 712 713
            }
        }

hrchilds's avatar
hrchilds committed
714 715
        H5Gclose(rootId);
        H5Fclose(fileId);
716 717 718 719 720
#else
        char msg[1024];
        SNPRINTF(msg, sizeof(msg), "The HDF4 library failed to open \"%s\" "
            "and this installation of the Enzo plugin is NOT compiled with "
            "HDF5 support. So, the file may be an HDF5 file but if so, it "
721
            "cannot be opened with this installation.", gridFileName.c_str());
722 723
        EXCEPTION1(InvalidFilesException, msg);
#endif
hrchilds's avatar
hrchilds committed
724
    }
hrchilds's avatar
hrchilds committed
725 726 727
}

// ****************************************************************************
hrchilds's avatar
hrchilds committed
728
//  Method: avtEnzoFileFormat constructor
hrchilds's avatar
hrchilds committed
729 730 731 732
//
//  Programmer: Jeremy Meredith
//  Creation:   January  3, 2005
//
hrchilds's avatar
hrchilds committed
733 734 735 736
//  Modifications:
//    Jeremy Meredith, Fri Feb 11 18:15:49 PST 2005
//    Added HDF5 support.
//
hrchilds's avatar
hrchilds committed
737 738 739
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.
//
740 741 742 743
//    Jeremy Meredith, Mon Apr  6 14:40:37 EDT 2009
//    Save the directory name off; we'll need to add it back on
//    later to open some other files.
//
hrchilds's avatar
hrchilds committed
744 745 746 747 748
// ****************************************************************************

avtEnzoFileFormat::avtEnzoFileFormat(const char *filename)
    : avtSTMDFileFormat(&filename, 1)
{
hrchilds's avatar
hrchilds committed
749
    fileType = ENZO_FT_UNKNOWN;
hrchilds's avatar
hrchilds committed
750
    dimension = 0;
hrchilds's avatar
hrchilds committed
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
    numGrids = 0;
    numLevels = 0;
    curTime = 0;

    string fname(filename);
    string extH(".hierarchy");
    string extB(".boundary");
    if (fname.length() > extH.length() &&
        fname.substr(fname.length()-extH.length()) == extH)
    {
        fname_base = fname.substr(0,fname.length()-extH.length());
        fnameH = fname;
        fnameB = fname_base + extB;
    }
    else if (fname.length() > extB.length() &&
        fname.substr(fname.length()-extB.length()) == extB)
    {
        fname_base = fname.substr(0,fname.length()-extB.length());
        fnameB = fname;
        fnameH = fname_base + extH;
    }
    else
    {
        EXCEPTION2(InvalidFilesException, fname.c_str(),
                   "It was not a .hierarchy or .boundary file.");
    }

778
    fname_dir = StringHelpers::Dirname(fname_base.c_str());
hrchilds's avatar
hrchilds committed
779 780
}

hrchilds's avatar
hrchilds committed
781 782 783 784 785 786 787
// ****************************************************************************
//  Method:  avtEnzoFileFormat destructure
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
// ****************************************************************************
hrchilds's avatar
hrchilds committed
788 789 790 791
avtEnzoFileFormat::~avtEnzoFileFormat()
{
}

hrchilds's avatar
hrchilds committed
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838

// ****************************************************************************
//  Method: avtEnzoFileFormat::UnifyGlobalExtents 
//
//  Purpose:
//    Gets the total spatial extents for the whole problem.  Uses only the
//    root level grids since they are guaranteed to cover the spatial extents.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    August 11, 2005
//
// ****************************************************************************
void
avtEnzoFileFormat::UnifyGlobalExtents()
{
    Grid &root = grids[0];

    root.minSpatialExtents[0] = grids[1].minSpatialExtents[0];
    root.maxSpatialExtents[0] = grids[1].maxSpatialExtents[0];
    root.minSpatialExtents[1] = grids[1].minSpatialExtents[1];
    root.maxSpatialExtents[1] = grids[1].maxSpatialExtents[1];
    if (dimension == 3)
    {
        root.minSpatialExtents[2] = grids[1].minSpatialExtents[2];
        root.maxSpatialExtents[2] = grids[1].maxSpatialExtents[2];
    }
    else
    {
        root.minSpatialExtents[2] = 0;
        root.maxSpatialExtents[2] = 0;
    }
    // now loop over all level zero grids
    for (int g = 2 ; g <= numGrids && grids[g].parentID == 0 ; g++)
    {
        for (int j = 0 ; j < dimension ; j++)
        {
            if (grids[g].minSpatialExtents[j] < root.minSpatialExtents[j])
                root.minSpatialExtents[j] = grids[g].minSpatialExtents[j];
            if (grids[g].maxSpatialExtents[j] > root.maxSpatialExtents[j])
                root.maxSpatialExtents[j] = grids[g].maxSpatialExtents[j];
        }
    }
}

hrchilds's avatar
hrchilds committed
839 840 841 842 843 844 845 846 847 848 849 850
// ****************************************************************************
//  Method:  avtEnzoFileFormat::ReadAllMetaData
//
//  Purpose:
//    Read the metadata if we have not done so yet.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
hrchilds's avatar
hrchilds committed
851 852 853 854 855 856 857
//  Modifications:
//    Jeremy Meredith, Thu Aug 11 16:59:19 PDT 2005
//    Moved the determination of the grid logical extents to here from
//    ReadHierachyFile, because when there are multiple root-
//    level grids, all of the root level grid extents must be unified
//    to determine any individual grid's logical extents.
//
hrchilds's avatar
hrchilds committed
858
// ****************************************************************************
hrchilds's avatar
hrchilds committed
859 860 861 862 863 864 865 866 867 868 869 870 871 872
void
avtEnzoFileFormat::ReadAllMetaData()
{
    // Check to see if we've read it yet
    if (numGrids > 0)
        return;

    // The parameter file 
    ReadParameterFile();

    // Read the hierarchy file, and simultaneously
    // convert spatial extents into logical extents
    ReadHierachyFile();

hrchilds's avatar
hrchilds committed
873 874 875 876
    // We need to get the whole global extents before we
    // can determine logical extents
    UnifyGlobalExtents();

hrchilds's avatar
hrchilds committed
877 878 879
    // Convert the parent logical extents
    for (int i=1; i<grids.size(); i++)
    {
hrchilds's avatar
hrchilds committed
880
        grids[i].DetermineExtentsInParent(grids);
hrchilds's avatar
hrchilds committed
881 882 883 884 885 886 887 888
        grids[i].DetermineExtentsGlobally(numLevels, grids);
    }

    // Open the smallest grid file and determine what variables
    // are in it
    DetermineVariablesFromGridFile();
}

hrchilds's avatar
hrchilds committed
889 890 891 892 893 894 895 896 897 898 899 900 901
// ****************************************************************************
//  Method:  avtEnzoFileFormat::GetCycle
//
//  Purpose:
//    Return the cycle.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    January  6, 2005
//
// ****************************************************************************
hrchilds's avatar
hrchilds committed
902
int
hrchilds's avatar
hrchilds committed
903
avtEnzoFileFormat::GetCycle()
hrchilds's avatar
hrchilds committed
904 905 906 907
{
    return curCycle;
}

hrchilds's avatar
hrchilds committed
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967

// ****************************************************************************
//  Method:  avtEnzoFileFormat::GetCycleFromFilename
//
//  Purpose:
//    Do a better job at guessing the cycle number for an Enzo file.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    July 15, 2005
//
// ****************************************************************************
int avtEnzoFileFormat::GetCycleFromFilename(const char *cfilename) const
{
    string f = cfilename;

    string::size_type last_slash = f.rfind('/');
    if (last_slash != string::npos)
        f = f.substr(last_slash+1);

    string::size_type last_dot = f.rfind('.');
    if (last_dot != string::npos)
        f = f.substr(0, last_dot);

    string::size_type last_nondigit = f.find_last_not_of("0123456789");
    if (last_nondigit != string::npos)
        f = f.substr(last_nondigit+1);

    if (f.empty())
        return 0;

    if (f.length() > 4)
        f = f.substr(f.length() - 4);

    return atoi(f.c_str());
}

// ****************************************************************************
//  Method: avtEnzoFileFormat::ActivateTimestep
//
//  Purpose:
//      This is called by the generic database to signal that this file format
//      is going to be used soon.  It is important that each file format defer
//      as much work as possible, since there can be many (one per timestep),
//      and we won't need all their work at once, if at all.
//
//  Programmer: Jeremy Meredith
//  Creation:   July 15, 2005
//
// ****************************************************************************

void
avtEnzoFileFormat::ActivateTimestep(void)
{
    // Nothing to do
}


hrchilds's avatar
hrchilds committed
968 969 970 971 972 973 974 975 976 977 978 979
// ****************************************************************************
//  Method: avtEnzoFileFormat::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: Jeremy Meredith
//  Creation:   January  4, 2005
//
hrchilds's avatar
hrchilds committed
980 981 982 983
//  Modifications:
//    Brad Whitlock, Mon Apr 3 11:05:13 PDT 2006
//    Added tracerparticleVarNames.
//
hrchilds's avatar
hrchilds committed
984 985 986 987 988 989 990 991
// ****************************************************************************

void
avtEnzoFileFormat::FreeUpResources(void)
{
    grids.clear();
    varNames.clear();
    particleVarNames.clear();
hrchilds's avatar
hrchilds committed
992
    tracerparticleVarNames.clear();
hrchilds's avatar
hrchilds committed
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
    numGrids=0;
    numLevels=0;
}


// ****************************************************************************
//  Method: avtEnzoFileFormat::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: meredith -- generated by xml2avt
//  Creation:   Fri Dec 3 17:19:52 PST 2004
//
hrchilds's avatar
hrchilds committed
1009 1010 1011 1012 1013
//  Modifications:
//
//    Hank Childs, Thu Jan 13 15:31:08 PST 2005
//    Generate domain nesting object.
//
hrchilds's avatar
hrchilds committed
1014 1015 1016
//    Jeremy Meredith, February 23, 2005
//    May have more than one root-level grid.  Unify extents over all of them.
//
hrchilds's avatar
hrchilds committed
1017 1018 1019
//    Jeremy Meredith, Fri Jul 15 15:29:14 PDT 2005
//    Added cycle and time to the metadata.
//
hrchilds's avatar
hrchilds committed
1020 1021 1022 1023
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.  Fixed problem with single-grid files.
//    Fixed dimensionality of point meshes.
//
hrchilds's avatar
hrchilds committed
1024 1025 1026 1027
//    Jeremy Meredith, Thu Aug 11 17:09:22 PDT 2005
//    Moved the unification of the problem spatial extents to a new method.
//    This is because it had to be calculated much earlier in the process.
//
hrchilds's avatar
hrchilds committed
1028 1029 1030
//    Hank Childs, Wed Jan 11 09:40:17 PST 2006
//    Change mesh type to AMR.
//
hrchilds's avatar
hrchilds committed
1031 1032 1033
//    Brad Whitlock, Mon Apr 3 11:07:11 PDT 2006
//    Added tracer particle support.
//
miller86's avatar
miller86 committed
1034 1035 1036 1037
//    Mark C. Miller, Mon Dec  8 22:20:35 PST 2008
//    Fixed obvious typo in particle velocity expression and made attempt
//    (without test data in hand) to ensure expressions get specified
//    correctly on 2D meshes.
brugger's avatar
 
brugger committed
1038 1039 1040 1041
//
//    Jean Favre, Wed Jul 27 09:29:46 PDT 2011
//    Add support for resolution selection contract.
//
hrchilds's avatar
hrchilds committed
1042 1043 1044 1045 1046
// ****************************************************************************

void
avtEnzoFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md)
{
hrchilds's avatar
hrchilds committed
1047
    // read in the metadata if we have not done so yet
hrchilds's avatar
hrchilds committed
1048 1049
    ReadAllMetaData();

hrchilds's avatar
hrchilds committed
1050 1051
    if (!avtDatabase::OnlyServeUpMetaData())
        BuildDomainNesting();
hrchilds's avatar
hrchilds committed
1052 1053 1054

    avtMeshMetaData *mesh = new avtMeshMetaData;
    mesh->name = "mesh";
hrchilds's avatar
hrchilds committed
1055
    mesh->originalName = "mesh";
hrchilds's avatar
hrchilds committed
1056

hrchilds's avatar
hrchilds committed
1057
    mesh->meshType = AVT_AMR_MESH;
hrchilds's avatar
hrchilds committed
1058 1059
    mesh->topologicalDimension = dimension;
    mesh->spatialDimension = dimension;
hrchilds's avatar
hrchilds committed
1060
    mesh->hasSpatialExtents = true;
hrchilds's avatar
hrchilds committed
1061

hrchilds's avatar
hrchilds committed
1062 1063 1064 1065 1066 1067
    mesh->minSpatialExtents[0] = grids[0].minSpatialExtents[0];
    mesh->maxSpatialExtents[0] = grids[0].maxSpatialExtents[0];
    mesh->minSpatialExtents[1] = grids[0].minSpatialExtents[1];
    mesh->maxSpatialExtents[1] = grids[0].maxSpatialExtents[1];
    mesh->minSpatialExtents[2] = grids[0].minSpatialExtents[2];
    mesh->maxSpatialExtents[2] = grids[0].maxSpatialExtents[2];
hrchilds's avatar
hrchilds committed
1068

hrchilds's avatar
hrchilds committed
1069 1070 1071 1072 1073 1074 1075 1076 1077
    // spoof a group/domain mesh
    mesh->numBlocks = numGrids;
    mesh->blockTitle = "Grids";
    mesh->blockPieceName = "grid";
    mesh->numGroups = numLevels;
    mesh->groupTitle = "Levels";
    mesh->groupPieceName = "level";
    vector<int> groupIds(numGrids);
    vector<string> blockPieceNames(numGrids);
1078
    int levels_of_detail = 0;
hrchilds's avatar
hrchilds committed
1079 1080 1081 1082 1083 1084 1085
    for (int i = 1; i <= numGrids; i++)
    {
        char tmpName[64];
        sprintf(tmpName,"level%d,grid%d",grids[i].level, grids[i].ID);

        groupIds[i-1] = grids[i].level;
        blockPieceNames[i-1] = tmpName;
1086
        levels_of_detail = std::max(levels_of_detail, grids[i].level);
hrchilds's avatar
hrchilds committed
1087
    }
1088 1089
    mesh->LODs = levels_of_detail;
    this->resolution = levels_of_detail; // current acceptable res = max res
hrchilds's avatar
hrchilds committed
1090 1091 1092 1093 1094 1095 1096
    mesh->blockNames = blockPieceNames;
    mesh->numGroups = numLevels;
    mesh->groupIds = groupIds;
    md->Add(mesh);

    avtMeshMetaData *pmesh = new avtMeshMetaData;
    pmesh->name = "particles";
hrchilds's avatar
hrchilds committed
1097
    pmesh->originalName = "particles";
hrchilds's avatar
hrchilds committed
1098
    pmesh->meshType = AVT_POINT_MESH;
hrchilds's avatar
hrchilds committed
1099 1100
    pmesh->topologicalDimension = 0;
    pmesh->spatialDimension = dimension;
hrchilds's avatar
hrchilds committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
    pmesh->hasSpatialExtents = false;
    pmesh->numBlocks = numGrids;
    pmesh->blockTitle = "Grids";
    pmesh->blockPieceName = "grid";
    pmesh->numGroups = numLevels;
    pmesh->groupTitle = "Levels";
    pmesh->groupPieceName = "level";
    pmesh->blockNames = blockPieceNames;
    pmesh->numGroups = numLevels;
    pmesh->groupIds = groupIds;
    md->Add(pmesh);

hrchilds's avatar
hrchilds committed
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
    pmesh = new avtMeshMetaData;
    pmesh->name = "tracer_particles";
    pmesh->originalName = "tracer_particles";
    pmesh->meshType = AVT_POINT_MESH;
    pmesh->topologicalDimension = 0;
    pmesh->spatialDimension = dimension;
    pmesh->hasSpatialExtents = false;
    pmesh->numBlocks = numGrids;
    pmesh->blockTitle = "Grids";
    pmesh->blockPieceName = "grid";
    pmesh->numGroups = numLevels;
    pmesh->groupTitle = "Levels";
    pmesh->groupPieceName = "level";
    pmesh->blockNames = blockPieceNames;
    pmesh->numGroups = numLevels;
    pmesh->groupIds = groupIds;
    md->Add(pmesh);

hrchilds's avatar
hrchilds committed
1131
    // grid variables
hrchilds's avatar
hrchilds committed
1132 1133 1134 1135 1136
    for (int v = 0 ; v < varNames.size(); v++)
    {
        AddScalarVarToMetaData(md, varNames[v], "mesh", AVT_ZONECENT);
    }

hrchilds's avatar
hrchilds committed
1137
    // particle variables
hrchilds's avatar
hrchilds committed
1138 1139 1140 1141 1142 1143
    for (int p = 0 ; p < particleVarNames.size(); p++)
    {
        AddScalarVarToMetaData(md, particleVarNames[p], "particles",
                               AVT_NODECENT);
    }

hrchilds's avatar
hrchilds committed
1144 1145 1146 1147 1148 1149 1150
    // tracer particle variables
    for (int tp = 0 ; tp < tracerparticleVarNames.size(); tp++)
    {
        AddScalarVarToMetaData(md, tracerparticleVarNames[tp],
            "tracer_particles", AVT_NODECENT);
    }

hrchilds's avatar
hrchilds committed
1151 1152 1153 1154

    // Add Expressions
    Expression vel;
    vel.SetName("velocity");
miller86's avatar
miller86 committed
1155 1156 1157 1158
    if (dimension == 2)
        vel.SetDefinition("{<x-velocity>,<y-velocity>}");
    else
        vel.SetDefinition("{<x-velocity>,<y-velocity>,<z-velocity>}");
hrchilds's avatar
hrchilds committed
1159 1160 1161 1162
    vel.SetType(Expression::VectorMeshVar);

    Expression pvel;
    pvel.SetName("particle_velocity");
miller86's avatar
miller86 committed
1163 1164 1165 1166
    if (dimension == 2)
        pvel.SetDefinition("{particle_velocity_x,particle_velocity_y}");
    else
        pvel.SetDefinition("{particle_velocity_x,particle_velocity_y,particle_velocity_z}");
hrchilds's avatar
hrchilds committed
1167 1168 1169 1170
    pvel.SetType(Expression::VectorMeshVar);

    md->AddExpression(&vel);
    md->AddExpression(&pvel);
hrchilds's avatar
hrchilds committed
1171 1172 1173 1174 1175 1176

    // Populate cycle and time
    md->SetCycle(timestep, curCycle);
    md->SetTime(timestep, curTime);
    md->SetCycleIsAccurate(true, timestep);
    md->SetTimeIsAccurate(true, timestep);
hrchilds's avatar
hrchilds committed
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
}


// ****************************************************************************
//  Method: avtEnzoFileFormat::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.
//
hrchilds's avatar
hrchilds committed
1195 1196
//  Programmer: Jeremy Meredith
//  Creation:   January  6, 2005
hrchilds's avatar
hrchilds committed
1197
//
hrchilds's avatar
hrchilds committed
1198 1199 1200 1201 1202
//  Modifications:
//    Hank Childs, Thu Jan 13 15:31:08 PST 2005
//    Remove hack where domain boundary nesting structure is removed from
//    cache to accomodate incorrect applications in generic database.
//
hrchilds's avatar
hrchilds committed
1203 1204 1205
//    Jeremy Meredith, Fri Feb 11 18:15:49 PST 2005
//    Added HDF5 support.
//
hrchilds's avatar
hrchilds committed
1206 1207 1208
//    Jeremy Meredith, Wed Aug  3 10:22:36 PDT 2005
//    Added support for 2D files.  Added support for single-level files.
//
hrchilds's avatar
hrchilds committed
1209 1210 1211
//    Jeremy Meredith, Thu Sep  8 12:03:55 PDT 2005
//    Added support for float32 coordinates in HDF4.
//
hrchilds's avatar
hrchilds committed
1212 1213 1214
//    Brad Whitlock, Mon Apr 3 11:00:15 PDT 2006
//    Added support for tracer_particles.
//
1215 1216
//    Mark C. Miller, Fri Mar 20 16:07:14 PST 2009
//    Made HDF5 related code conditionally compiled on HAVE_LIBHDF5
1217 1218 1219 1220 1221 1222 1223
//
//    Jeremy Meredith, Mon Apr  6 14:36:58 EDT 2009
//    Added support for explicit particle and grid file names.
//    Also, try to descend into a top-level Group if its name
//    matches the format for a grid-group in the new format.
//    This is for support for the new "Packed AMR" format.
//
1224 1225 1226 1227
//    Jeremy Meredith, Wed Jan  6 14:57:18 EST 2010
//    Make HDF4 code conditionally compiled so we can support an
//    HDF5-only build for this plugin as well.
//
hrchilds's avatar
hrchilds committed
1228 1229 1230 1231 1232 1233 1234 1235 1236
// ****************************************************************************

vtkDataSet *
avtEnzoFileFormat::GetMesh(int domain, const char *meshname)
{
    ReadAllMetaData();

    if (string(meshname) == "mesh")
    {
hrchilds's avatar
hrchilds committed
1237
        // rectilinear mesh
hrchilds's avatar
hrchilds committed
1238 1239 1240 1241 1242 1243 1244 1245 1246
        vtkFloatArray  *coords[3];
        int i;
        int d = domain+1;
        for (i =