Example #1
0
def read(filename, nGhost=0):
    """ Read the parthenon hdf file """
    from phdf import phdf
    f = phdf(filename)
    return f
Example #2
0
    def Analyse(self, parameters):

        sys.path.insert(
            1,
            parameters.parthenon_path +
            "/scripts/python/packages/parthenon_tools/parthenon_tools",
        )

        try:
            import phdf
            from phdf_diff import compare
        except ModuleNotFoundError:
            print("Couldn't find modules to load Parthenon hdf5.")
            return False

        all_pass = True

        # Reflection: First comparing initial condition to final state
        res = compare(
            [
                "advection.reflecting.00000.phdf",
                "advection.reflecting.00004.phdf"
            ],
            check_metadata=False,
            quiet=True,
        )
        if res != 0:
            print("Double reflection test failed: output start != end ")
            all_pass = False

        # Compare that data in between is actually different.
        res = compare(
            [
                "advection.reflecting.00000.phdf",
                "advection.reflecting.00002.phdf"
            ],
            check_metadata=False,
            quiet=True,
        )
        if res == 0:
            print("Double reflection test failed: data identical during sim.")
            all_pass = False

        # Periodic: First comparing initial condition to final state
        res = compare(
            ["advection.periodic.00000.phdf", "advection.periodic.00004.phdf"],
            check_metadata=False,
            quiet=True,
        )
        if res != 0:
            print("Fully periodic test failed: output start != end ")
            all_pass = False

        # Compare that data in between is actually different.
        res = compare(
            ["advection.periodic.00000.phdf", "advection.periodic.00001.phdf"],
            check_metadata=False,
            quiet=True,
        )
        if res == 0:
            print("Fully periodic test failed: data identical during sim.")
            all_pass = False

        # Outflow: Check there's sth in the beginning...
        outflow_data_initial = phdf.phdf("advection.outflow.00000.phdf")
        advected_initial = outflow_data_initial.Get("advected")
        if np.sum(advected_initial) != 60.0:
            print("Unexpected initial data for outflow test.")
            all_pass = False

        # ... and nothing at the end
        outflow_data_final = phdf.phdf("advection.outflow.00004.phdf")
        advected_final = outflow_data_final.Get("advected")
        if np.sum(advected_final) != 0.0:
            print("Some 'advected' did not leave the box in outflow test.")
            all_pass = False

        return all_pass
Example #3
0
def compare(files, all=False, brief=True, quiet=False, one=False, tol=1.0e-12):
    """ compares two hdf files """

    #**************
    # import Reader
    #**************
    from phdf import phdf

    #**************
    # Reader Help
    #**************
    # for help  on phdf uncomment following line
    # print(help(phdf))


    # Load first file and print info
    try:
        f0 = phdf(files[0])
        if not quiet: print(f0)
    except:
        print("""
        *** ERROR: Unable to open %s as phdf file
        """%files[0])
        return(1)

    # Load second file and print info
    try:
        f1 = phdf(files[1])
        if not quiet:  print(f1)
    except:
        print("""
        *** ERROR: Unable to open %s as phdf file
        """%files[1])
        return(2)

    # rudimentary checks
    if f0.TotalCellsReal != f1.TotalCellsReal:
        # do both simulations have same number of cells?
        print("""
        These simulations have different number of cells.
        Clearly they are different.

        Quitting...
        """)
        return(3)

    # Now go through all variables in first file
    # and hunt for them in second file.
    #
    # Note that indices don't match when blocks
    # are different
    no_diffs = True

    if not brief and not quiet:
        print('____Comparing on a per variable basis with tolerance %.16g'%tol)
    breakOut = False
    oneTenth = f0.TotalCells//10
    if not quiet: print('Mapping indices:')
    print('Tolerance = %g' % tol)
    otherLocations = [None]*f0.TotalCells
    for idx in range(f0.TotalCells):
        if not quiet:
            if idx%oneTenth == 0:
                print('   Mapping %8d (of %d) '%(idx,f0.TotalCells))

        if f0.isGhost[idx%f0.CellsPerBlock]:
            # don't map ghost cells
            continue

        otherLocations[idx] = f0.findIndexInOther(f1,idx)
    if not quiet: print(f0.TotalCells,'cells mapped')

    for var in f0.Variables:
        if var == 'Locations' or var == 'Info':
            continue
        #initialize info values
        same = True
        errMax = -1.0
        maxPos=[0,0,0]

        # Get values from file
        val0 = f0.Get(var)
        val1 = f1.Get(var)
        isVec = np.prod(val0.shape) != f0.TotalCells
        for idx,v in enumerate(val0):
            if f0.isGhost[idx%f0.CellsPerBlock]:
                # only consider real cells
                continue
            [ib,bidx,iz,iy,ix] = f0.ToLocation(idx)

            # find location in other file
            [idx1, ib1, bidx1, iz1, iy1, ix1] = otherLocations[idx]

            # compute error
            errVal = np.abs(v - val1[idx1])
            errMag = np.linalg.norm(errVal)

            # Note that we use norm / magnitude to compute error
            if errMag > errMax:
                errMax = errMag
                errMaxPos = [f0.x[ib,ix], f0.y[ib,iy], f0.z[ib,iz]]

            if np.linalg.norm(errVal) > tol:
                same = False
                no_diffs = False
                if brief or quiet:
                    breakOut=True
                    break

                if isVec:
                    s='['
                    for xd in errVal:
                        if xd == 0.:
                            s += ' 0.0'
                        else:
                            s += ' %10.4g'%xd
                    s+= ']'
                else:
                    s = '%10.4g'%errVal
                if all:
                    print('  %20s: %6d: diff='%(var,idx),s.strip(),
                          'at:f0:%d:%.4f,%.4f,%.4f'%(idx,
                                                     f0.x[ib,ix],
                                                     f0.y[ib,iy],
                                                     f0.z[ib,iz]),
                          ':f1:%d:%.4f,%.4f,%.4f'%(idx1,f1.x[ib1,ix1],f1.y[ib1,iy1],f1.z[ib1,iz1]))
        if breakOut:
            if not quiet: print("")
            print('Files %s and %s are different'%(f0.file, f1.file))
            if not quiet: print("")
            break
        if not quiet:
            if same:
                print('  %20s: no diffs'%var)
            else:
                print('____%26s: MaxDiff=%10.4g at'%(var,errMax),errMaxPos)

        if one and not same:
            break

    if no_diffs:
      return(0)
    else:
      return(4)
Example #4
0
        all = input.a
    files = input.files

    if input.tol is not None:
        tol = float(input.tol)
    else:
        tol = 1.0e-12


    if len(files) != 2:
        Usage()
        exit(1)

    # Load first file and print info
    try:
        f0 = phdf(files[0])
        if not quiet: print(f0)
    except:
        exit(1)

    # Load second file and print info
    try:
        f1 = phdf(files[1])
        if not quiet:  print(f1)
    except:
        print("""
        *** ERROR: Unable to open %s as phdf file
        """%files[1])
        exit(2)

    # rudimentary checks
Example #5
0
def compare(
    files,
    brief=False,
    quiet=False,
    one=False,
    tol=1.0e-12,
    check_metadata=True,
    check_input=False,
    relative=False,
):
    """compares two hdf files. Returns 0 if the files are equivalent.

    Error codes:
        1  : Can't open file 0
        2  : Can't open file 1
        3  : Total number of cells differ
        4  : Variable data in files differ

    Metadata Error codes:
        10 : Times in hdf files differ
        11 : Attribute names in Info of hdf files differ
        12 : Values of attributes in Info of hdf files differ
        13 : Attribute names or values in Input of hdf files differ
        14 : Attribute names or values in Params of hdf files differ
        15 : Meta variables (Locations, VolumeLocations, LogicalLocations, Levels) differ
    """

    ERROR_NO_OPEN_F0 = 1
    ERROR_NO_OPEN_F1 = 2
    ERROR_CELLS_DIFFER = 3
    ERROR_DATA_DIFFER = 4

    # **************
    # import Reader
    # **************
    from phdf import phdf

    # **************
    # Reader Help
    # **************
    # for help  on phdf uncomment following line
    # print(help(phdf))

    # Load first file and print info
    f0 = phdf(files[0])
    try:
        f0 = phdf(files[0])
        if not quiet:
            print(f0)
    except:
        print("""
        *** ERROR: Unable to open %s as phdf file
        """ % files[0])
        return ERROR_NO_OPEN_F0

    # Load second file and print info
    try:
        f1 = phdf(files[1])
        if not quiet:
            print(f1)
    except:
        print("""
        *** ERROR: Unable to open %s as phdf file
        """ % files[1])
        return ERROR_NO_OPEN_F1

    # rudimentary checks
    if f0.TotalCellsReal != f1.TotalCellsReal:
        # do both simulations have same number of cells?
        print("""
        These simulations have different number of cells.
        Clearly they are different.

        Quitting...
        """)
        return ERROR_CELLS_DIFFER

    no_diffs = True
    if check_metadata:
        if not quiet:
            print("Checking metadata")
        metadata_status = compare_metadata(f0, f1, quiet, one, check_input)
        if metadata_status != 0:
            if one:
                return metadata_status
            else:
                no_diffs = False
        else:
            if not quiet:
                print("Metadata matches")
    else:
        if not quiet:
            print("Ignoring metadata")

    # Now go through all variables in first file
    # and hunt for them in second file.
    #
    # Note that indices don't match when blocks
    # are different

    if not brief and not quiet:
        print("____Comparing on a per variable basis with tolerance %.16g" %
              tol)
    oneTenth = f0.TotalCells // 10
    print("Tolerance = %g" % tol)

    # Make loc array of locations matching the shape of val0,val1
    loc = f0.GetVolumeLocations(flatten=False)

    for var in set(f0.Variables + f1.Variables):
        var_no_diffs = True
        if var in [
                "Locations",
                "VolumeLocations",
                "LogicalLocations",
                "Levels",
                "Info",
                "Params",
                "SparseInfo",
                "Input",
                "Blocks",
        ]:
            continue

        # Get values from file
        val0 = f0.Get(var, flatten=False)
        val1 = f1.Get(var, flatten=False)

        is_vec = np.prod(val0.shape) != f0.TotalCells

        # Determine arrangement of mesh blocks of f1 in terms of ordering in f0
        otherBlockIdx = list(
            f0.findBlockIdxInOther(f1, i) for i in range(f0.NumBlocks))

        # Rearrange val1 to match ordering of meshblocks in val0
        val1 = val1[otherBlockIdx]

        # compute error at every point
        if relative:
            denom = 0.5 * (np.abs(val0) + np.abs(val1))
            # When val0==0 but val1!=0 or vice versa, use the mean of the
            # entire data set as denom to avoid giving these points an
            # err_val=2.0
            denom[np.logical_or(
                val0 == 0,
                val1 == 0)] = 0.5 * np.mean(np.abs(val0) + np.abs(val1))

            err_val = np.abs(val0 - val1) / denom
            # Set error values where denom==0 to 0
            # Numpy masked arrays would be more robust here, but they are very slow
            err_val[denom == 0] = 0
        else:
            err_val = np.abs(val0 - val1)

        # Compute magnitude of error at every point
        if is_vec:
            # Norm every vector
            err_mag = np.linalg.norm(err_val, axis=-1)
        else:
            # Just plain error for scalars
            err_mag = err_val
        err_max = err_mag.max()

        # Check if the error of any block exceeds the tolerance
        if err_max > tol:
            no_diffs = False
            var_no_diffs = False

            if quiet:
                continue  # Skip reporting the error

            if one:
                # Print the maximum difference only
                bad_idx = np.argmax(err_mag)
                bad_idx = np.array(np.unravel_index(bad_idx, err_mag.shape))

                # Reshape for printing step
                bad_idxs = bad_idx.reshape((1, *bad_idx.shape))
            else:
                # Print all differences exceeding maximum
                bad_idxs = np.argwhere(err_mag > tol)

            for bad_idx in bad_idxs:
                bad_idx = tuple(bad_idx)

                # Find the bad location
                bad_loc = np.array(loc)[:, bad_idx[0], bad_idx[1], bad_idx[2],
                                        bad_idx[3]]

                # TODO(forrestglines): Check that the bkji and zyx reported are the correct order
                print(f"Diff in {var:20s}")
                print(
                    f"    bkji: ({bad_idx[0]:4d},{bad_idx[1]:4d},{bad_idx[2]:4d},{bad_idx[3]:4d})"
                )
                print(
                    f"    zyx: ({bad_loc[0]:4f},{bad_loc[1]:4f},{bad_loc[2]:4f})"
                )
                print(f"    err_mag: {err_mag[bad_idx]:4f}")
                if is_vec:
                    print(f"    f0: " + " ".join(f"{u:.4e}"
                                                 for u in val0[bad_idx]))
                    print(f"    f1: " + " ".join(f"{u:.4e}"
                                                 for u in val1[bad_idx]))
                    print(f"    err: " + " ".join(f"{u:.4e}"
                                                  for u in err_val[bad_idx]))
                else:
                    print(f"    f0: {val0[bad_idx]:.4e}")
                    print(f"    f1: {val1[bad_idx]:.4e}")
        if not quiet:
            if var_no_diffs:
                print(f"  {var:20s}: no diffs")
            else:
                print(f"  {var:20s}: differs")
    if no_diffs:
        return 0
    else:
        return ERROR_DATA_DIFFER
Example #6
0
def compare_analytic(filename,
                     analytic_components,
                     err_func=norm_err_func,
                     tol=1e-12,
                     quiet=False):
    """Compares data in filename to analytic gold data in analytic_components.

    Arguments:
    filename: string
        Filename of ".phdf" file to compare data
    analytic_components: dictionary
        Dictionary keying component names to analytic functions.
        Each analytic function in the dictionary takes the arguments:

        def analytic_func(Z,Y,X,t)

        where Z,Y,X comprise arrays of z,y,x coords to compute the analytic solution
        for a component at time t

    Keyword Arguments:
    err_func=norm_err_func: function(gold,test)
        Error function that accepts the analytic solution and
        data and returns an error metric. The default is the L2 norm of the
        difference between the gold and test data. Other order norms and
        relative error functions can be constructed from norm_err_func or can be
        created from scratch
    tol=1e-12: float
        Tolerance of error metric.
    quiet=False: boolean
        Set to true to supress printing errors exceeding tol

    Returns True if the error of all components is under the tolerance, otherwise
    returns False.
    """

    try:
        import phdf
    except ModuleNotFoundError:
        print("Couldn't find module to read Parthenon hdf5 files.")
        return False

    datafile = phdf.phdf(filename)

    # Dictionary of component_name:component[grid_idx,k,j,i]
    file_components = datafile.GetComponents(analytic_components.keys(),
                                             flatten=False)

    # Generate location arrays for each grid
    Z, Y, X = datafile.GetVolumeLocations()

    # Check all components for which an analytic version exists
    all_ok = True
    for component in analytic_components.keys():

        # Compute the analytic component at Z,Y,X
        analytic_component = analytic_components[component](Z, Y, X,
                                                            datafile.Time)

        # Compute the error between the file and analytic component
        err = err_func(analytic_component, file_components[component].ravel())

        if err > tol:
            if not quiet:
                print(
                    f"Component {component} in {filename} error {err} exceeds tolerance {tol}"
                )
            all_ok = False

    return all_ok