The VELMOD_AWP.bin file is a binary file that contains the full velocity model in AWP format. The file is written using MPI I/O operations for parallel processing efficiency.  


File Structure

The file is organized in a 3D grid, with dimensions corresponding to the X, Y, and Z axes of the model. For each grid point, there are three values: Vp (P-wave velocity), Vs (S-wave velocity), and Rho (density).

These values are stored consecutively for each grid point.

The order of the grid points in the file is such that the X coordinate varies fastest, then the Z coordinate, and finally the Y coordinate.  The file is written in parallel, with each MPI process writing its own portion of the grid. The offset for each process is calculated to ensure that the data is placed in the correct location in the overall grid.  

Data Types

All data in the file are floating point numbers. 


Python Pseudo code

If we ignore MPI-IO,  the following Python code can output a VM in this format  (Original C code : https://github.com/ucgmsim/Velocity-Model/blob/e7520b0f67347c0ffe9f6712047f47c8ea4d24ac/src/writeCVMData.c#L181 Note that the comment about the order of X,Y,Z coordinates in the original code is misleading, as the function is called inside a loop that iterates over the nY dimension of the grid. This means that for each iteration (each slice along the Y-axis), the writeGlobalQualitiesAWP() function append data to the file (rather than overwriting it), growing the file size with each iteration.

import struct

# Looping over nY dimension of the grid, calling this function at each iteration (ie. iy in range(nY))

def writeGlobalQualitiesAWP(OUTPUT_DIR, PARTIAL_GLOBAL_MESH, GLOBAL_MESH, PARTIAL_GLOBAL_QUALITIES, GEN_EXTRACT_VELO_MOD_CALL, CALCULATION_LOG, iy, rank):


    awpvelmod = f"{OUTPUT_DIR}/Velocity_Model/VELMOD_AWP.bin"

    # this buffer contains the data in AWP format that will be dumped to disk
    buf = []
    minvp = 0

    for iz in range(PARTIAL_GLOBAL_MESH['nZ']):
        for ix in range(PARTIAL_GLOBAL_MESH['nX']):
            vpTemp = PARTIAL_GLOBAL_QUALITIES['Vp'][ix][iz]
            if PARTIAL_GLOBAL_QUALITIES['Vs'][ix][iz] <= GEN_EXTRACT_VELO_MOD_CALL['MIN_VS']: # enforce min Vs
                vsTemp = GEN_EXTRACT_VELO_MOD_CALL['MIN_VS']
                CALCULATION_LOG['nPointsExceedingMinVelo'] += 1

                #force P-wave velocity to be at least sqrt(2) * S-wave velocity
                minvp = (2 ** 0.5) * vsTemp
                if vpTemp < minvp: 
                    vpTemp = minvp
            else:
                vsTemp = PARTIAL_GLOBAL_QUALITIES['Vs'][ix][iz] # else assign from global structure
            rhoTemp = PARTIAL_GLOBAL_QUALITIES['Rho'][ix][iz]

            # x increases fastest, then z
            # just a cross section parallel to Y. y is fixed at iy
            buf.extend([vpTemp, vsTemp, rhoTemp])

    # Write to binary file
    with open(awpvelmod, 'ab') as f: # binary append mode
        for value in buf:
            f.write(struct.pack('f', value))
  • No labels