Beispiel #1
0
def main():

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    customLegend(folder=folder.outputs)
Beispiel #2
0
def main():

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    # Get Large Eddy Simulation data
    les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc"))

    # Create plots for each snapshot in time
    for n in range(len(les.t)):
        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))
        if not os.path.isdir(folderTime):
            os.makedirs(folderTime)

        snapshot = les.data[n]

        # Which layers of the 3D data set do we want to plot?
        imagesIndices = range(0, min(len(snapshot.x), len(snapshot.y)), 10)

        # Plot slices at fixed locations on the y-axis
        for j in imagesIndices:
            layer = snapshot.y[j] * 1e-3
            title = "y = {:.2f}km (id={})".format(layer, j + 1)
            print "XZ layer {} ({})".format(j + 1, title)

            # Plot with only clouds
            plotThermalContour(snapshot.x * 1e-3,
                               snapshot.z * 1e-3,
                               snapshot.ql.field[:, j, :],
                               showMesh=True,
                               id="{}_xz_mesh+cloud".format(j),
                               title=title,
                               xlabel="x (km)",
                               dpi=500,
                               folder=folderTime)

        # Plot slices at fixed locations on the x-axis
        for i in imagesIndices:
            layer = snapshot.x[i] * 1e-3
            title = "x = {:.2f}km (id={})".format(layer, i + 1)
            print "YZ layer {} ({})".format(i + 1, title)

            # Plot with only clouds
            plotThermalContour(snapshot.y * 1e-3,
                               snapshot.z * 1e-3,
                               snapshot.ql.field[:, :, i],
                               showMesh=True,
                               id="{}_yz_mesh+cloud".format(i),
                               title=title,
                               xlabel="y (km)",
                               dpi=500,
                               folder=folderTime)
def addThetaBackground(folderData="/mnt/c/MONC_ARM",
                       indicatorMONC="plume",
                       timesMONC=[13800]):
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData=folderData)
    files = getFilesInFolder(folder.data1d, extension=".nc")

    dataAll = {}
    for file in files:
        print(f"\nReading file: {file}")

        # Get Large Eddy Simulation data
        data = netCDF4.Dataset(file)
        les = lesDataMonc1D(data)

        # Merge dictionaries dataAll and les
        dataAll = {**dataAll, **les.data}

    # Now update the data sets
    for n, t in enumerate(timesMONC):
        print("Processing timestep {} of {}".format(n + 1, len(timesMONC)))

        # filenameTheta = os.path.join(folder.monc, "time_{}".format(timesMONC[n]), "profilesMean", indicatorMONC, "z_th.npz")
        filenameTheta = os.path.join(folder.monc,
                                     "time_{}".format(timesMONC[n]),
                                     "profilesMean", indicatorMONC,
                                     "z_th_uncorrected.npz")

        dataTheta = np.load(filenameTheta)
        dataTheta = {key: dataTheta[key] for key in dataTheta}

        # Save old profiles for safe-keeping
        np.savez(filenameTheta.replace("z_th.npz", "z_th_uncorrected.npz"),
                 **dataTheta)

        # Add the missing mean profiles to the vertical distributions
        fields = [
            "av", "fluid1", "fluid2", "fluid1Min", "fluid1Max", "fluid2Min",
            "fluid2Max"
        ]
        thetaMoncMean = dataTheta["av"]
        for field in fields:
            dataTheta[field] = dataAll[float(
                t)]["theta_mean"] - thetaMoncMean + dataTheta[field]

        np.savez(filenameTheta.replace("z_th_uncorrected.npz", "z_th.npz"),
                 **dataTheta)
def compareLEMvsMONC(
        indicatorLEM  = "plume", 
        indicatorMONC = "plume", 
        timesLEM  = [14000],
        timesMONC = [13800]
    ):
    # Fetch folders for code structure
    folder = folders(
        folderScripts = os.path.dirname(os.path.realpath(__file__))
    )
    
    variables = ["ql", "qv", "theta", "u", "v", "w"]
    
    # Create plots for each snapshot in time
    for n in range(min(len(timesLEM), len(timesMONC))):
        print("Processing timestep {} of {}".format(n+1, min(len(timesLEM), len(timesMONC))))
        
        folderTimeLEM  = os.path.join(folder.lem,  "time_{}".format(timesLEM[n]),  "profilesMean", indicatorLEM)
        folderTimeMONC = os.path.join(folder.monc, "time_{}".format(timesMONC[n]), "profilesMean", indicatorMONC)
        folderTime = os.path.join(folder.outputs, "lem_{}_monc_{}".format(timesLEM[n], timesMONC[n]), "profilesMean")
        
        '''
        Plot comparisons of vertical profiles
        '''
        plotVolumeFractionComparison(
            folderTimeLEM,
            folderTimeMONC,
            title="Volume fraction", 
            folder=folderTime
        )
        
        plotVerticalProfileComparison(
            "u",
            folderTimeLEM,
            folderTimeMONC,
            title="Horizontal velocity", 
            xlabel="u (m/s)", 
            folder=folderTime,
            plotZero=True
        )
        
        plotVerticalProfileComparison(
            "v", 
            folderTimeLEM,
            folderTimeMONC,
            title="Horizontal velocity", 
            xlabel="v (m/s)", 
            folder=folderTime,
            plotZero=True
        )
        
        plotVerticalProfileComparison(
            "w", 
            folderTimeLEM,
            folderTimeMONC,
            title="Vertical velocity", 
            xlabel="w (m/s)", 
            folder=folderTime,
            plotZero=True
        )
        
        plotVerticalProfileComparison(
            "theta", 
            folderTimeLEM,
            folderTimeMONC,
            title="Potential temperature", 
            xlabel="$\\theta$ (K)", 
            folder=folderTime,
            plotZero=True
        )
        
        plotVerticalProfileComparison(
            "qv", 
            folderTimeLEM,
            folderTimeMONC,
            title="Water vapour", 
            xlabel="$q_v$ (kg/kg)", 
            folder=folderTime,
            plotZero=True
        )
        
        plotVerticalProfileComparison(
            "ql", 
            folderTimeLEM,
            folderTimeMONC,
            title="Liquid water", 
            xlabel="$q_l$ (kg/kg)", 
            folder=folderTime,
            plotZero=True
        )
Beispiel #5
0
def lesCloudContours(id="LEM",
                     caseStudy="ARM",
                     indicatorFunction="plume",
                     netcdfFile=None,
                     interval=1,
                     generateGif=False,
                     greyscale=False,
                     plotCloud=False,
                     plotThermals=True,
                     plotVelocity=False,
                     plotAll=False):
    '''
    Plot cross sections of clouds and their underlying structures.
    
    :param id: The simulation source type, set to either "ARM" or "MONC", str.
    :param caseStudy: The name of the case study to be plot, str.
    :param indicatorFunction: The type of structure to overlay onto the cloud, str.
    :param netcdfFile: Specify the netcdf file to open (all files processed if none selected), str.
    :param interval: Gap between layers to be plotted (1 means every layer plotted), int.
    :param generateGif: Compose all generated images into an animation cycling through the layers, bool.
    :param plotCloud: If True generate plot showing only the clouds, bool.
    :param plotThermals: If True generate plot showing cloud and the chosen indicatorFunction, bool.
    :param plotVelocity: If True generate plot showing cloud and the vertical velocity, bool.
    :param plotAll: If True generate plot showing all the features above, bool.
    '''

    # Fetch folders for code structure
    if id == "LEM":
        folder = folders(id=id,
                         folderScripts=os.path.dirname(
                             os.path.realpath(__file__)),
                         folderData="/mnt/f/Desktop/LES_Data")
    elif id == "MONC":
        folder = folders(id=f"{id}_{caseStudy}",
                         folderScripts=os.path.dirname(
                             os.path.realpath(__file__)),
                         folderData=f"/mnt/c/{id}_{caseStudy}")
    else:
        raise ValueError(f"id {id} is not valid. Use LEM or MONC.")

    if netcdfFile:
        files = [os.path.join(folder.data, netcdfFile)]
    else:
        # Find all NetCFD files in
        files = getFilesInFolder(folder.data, extension=".nc")

    for file in files:
        print(f"\nProcessing file: {file}")

        # Get Large Eddy Simulation data
        les = getLesData(file, id=id, indicatorFunction=indicatorFunction)

        # Create plots for each snapshot in time
        for n in range(len(les.t)):
            print("\nProcessing timestep {} (t = {:.2f}hrs,  t = {:.1f}s)".
                  format(n + 1,
                         float(les.t[n]) / 3600., float(les.t[n])))

            folderTime = os.path.join(folder.outputs,
                                      "time_{}".format(int(les.t[n])))
            if not os.path.isdir(folderTime):
                os.makedirs(folderTime)

            snapshot = les.data[n]

            # Which layers of the 3D data set do we want to plot?
            imagesIndices = range(0, min(len(snapshot.x), len(snapshot.y)),
                                  interval)
            '''# Plot slices at fixed locations on the z-axis
            for k in range(0, len(snapshot.z), 10):
                layer = snapshot.z[k]*1e-3
                title = "z = {:.2f}km (id={})".format(layer, k+1)
                print "XY layer {} ({})".format(k+1, title)
                
                plotThermalContour(
                    snapshot.x*1e-3,
                    snapshot.y*1e-3,
                    snapshot.ql.field[k,:,:],
                    id="{}_xy_cloud+updraft".format(k),
                    title=title,
                    xlabel="x (km)",
                    ylabel="y (km)",
                    xlim=[-10.,10.],
                    ylim=[-10.,10.],
                    velocityVectorsOnly = True,
                    folder=folderTime,
                    I2=snapshot.I2.field[k,:,:],
                    u=(snapshot.u.field-0*np.mean(snapshot.u.av))[k,:,:],
                    w=(snapshot.v.field-0*np.mean(snapshot.v.av))[k,:,:]
                )'''

            # Plot slices at fixed locations on the y-axis
            for j in imagesIndices:
                layer = snapshot.y[j] * 1e-3
                title = f"t = {float(les.t[n])/3600:.2f} hours, y = {layer:.2f} km"
                print(f"XZ layer {j+1} ({title})")

                # Plot with only clouds
                if plotCloud:
                    plotThermalContour(snapshot.x * 1e-3,
                                       snapshot.z * 1e-3,
                                       snapshot.ql.field[:, j, :],
                                       id="{}_xz_cloud".format(j),
                                       title=title,
                                       xlabel="x (km)",
                                       folder=folderTime,
                                       greyscale=greyscale)

                # Plot including structure of thermals below clouds
                if plotThermals:
                    plotThermalContour(
                        snapshot.x * 1e-3,
                        snapshot.z * 1e-3,
                        snapshot.ql.field[:, j, :],
                        id="{}_xz_cloud+thermal".format(j),
                        # title=title,
                        xlabel="x (km)",
                        folder=folderTime,
                        I2=snapshot.I2.field[:, j, :],
                        greyscale=greyscale)

                # Plot including regions of positive vertical velocity (updrafts)
                if plotVelocity:
                    plotThermalContour(
                        snapshot.x * 1e-3,
                        snapshot.z * 1e-3,
                        snapshot.ql.field[:, j, :],
                        id="{}_xz_cloud+updraft".format(j),
                        title=title,
                        xlabel="x (km)",
                        folder=folderTime,
                        # u=(snapshot.v.field-snapshot.v.av[:,None,None])[:,j,:],
                        w=snapshot.w.field[:, j, :],
                        greyscale=greyscale)

                # Plot including clouds, structure of thermals and vertical velocity
                if plotAll:
                    plotThermalContour(
                        snapshot.x * 1e-3,
                        snapshot.z * 1e-3,
                        snapshot.ql.field[:, j, :],
                        id="{}_xz_cloud+thermal+updraft".format(j),
                        title=title,
                        xlabel="x (km)",
                        folder=folderTime,
                        I2=snapshot.I2.field[:, j, :],
                        w=snapshot.w.field[:, j, :],
                        greyscale=greyscale)

        # Remove les data to clear memory
        totalTimesteps = len(les.t)
        del les
        del snapshot

        # Create gif animations for generated plots
        if generateGif:
            for n in range(totalTimesteps):
                folderTime = os.path.join(folder.outputs,
                                          "timestep_{}".format(n))
                imageListContourXZ = []

                for k in imagesIndices:
                    print(k)
                    imageListContourXZ = []
                    imageListContourYZ = []

                    imageListContourXZ.append(
                        os.path.join(os.path.join(folderTime, "contourCloud"),
                                     "contour_{}_xz_cloud.png".format(k)))
                    imageListContourXZ.append(
                        os.path.join(
                            os.path.join(folderTime, "contourCloud"),
                            "contour_{}_xz_cloud+thermal.png".format(k)))
                    imageListContourXZ.append(
                        os.path.join(
                            os.path.join(folderTime, "contourCloud"),
                            "contour_{}_xz_cloud+thermal+updraft.png".format(
                                k)))

                    makeGif("contour_{}_xz.gif".format(k),
                            imageListContourXZ,
                            folder=folderTime,
                            delay=200)
Beispiel #6
0
def cloudFractionContour(generateGif=False, id="LEM", caseStudy="ARM", indicatorFunction="basic", netcdfFile=None):
    
    
    # Fetch folders for code structure
    if id == "LEM":
        folder = folders(
            id = id,
            folderScripts = os.path.dirname(os.path.realpath(__file__)),
            folderData = "/mnt/f/Desktop/LES_Data"
        )
    elif id == "MONC":
        folder = folders(
            id = f"{id}_{caseStudy}",
            folderScripts = os.path.dirname(os.path.realpath(__file__)),
            folderData = f"/mnt/c/{id}_{caseStudy}"
        )
    else:
        raise ValueError(f"id {id} is not valid.")
    
    if netcdfFile:
        files = [os.path.join(folder.data, netcdfFile)]
    else:
        # Get all available NetCFD files
        files = getFilesInFolder(folder.data, extension=".nc")
    
    times = []
    cloudTops = {}
    cloudBases = {}
    cloudCovers = {}
    cloudCovers1 = {}
    cloudCovers2 = {}
    cloudFractions = {}
    cloudFractions1 = {}
    cloudFractions2 = {}
    cloudFractions1sigma1 = {}
    cloudFractions2sigma2 = {}
    
    for i,file in enumerate(files):
        print(f"\nProcessing 3D file: {file} (file {i+1} of {len(files)})")
        
        # Get Large Eddy Simulation data
        les = getLesData(
            file, 
            id = id,
            indicatorFunction = indicatorFunction
        )
    
        # Create plots for each snapshot in time
        for n in range(len(les.t)):
            print("\nProcessing timestep {} (t = {:.2f}hrs,  t = {:.1f}s)".format(n+1, float(les.t[n])/3600., float(les.t[n])))
            
            time = int(les.t[n])
            folderTime = os.path.join(folder.outputs, f"time_{time}")
            if not os.path.isdir(folderTime):
                os.makedirs(folderTime)
            
            snapshot = les.data[n]
            
            z = snapshot.z
            cloud = snapshot.ql.field > 1e-5
            cloudz = np.max(snapshot.ql.field, axis=snapshot.ql.axisXY) > 1e-5
            cloudFraction = horizontalAverage(cloud, axis=snapshot.ql.axisXY)
            cloudFraction1 = conditionalAverage(cloud, np.invert(snapshot.I2.field), axis=snapshot.ql.axisXY)
            cloudFraction2 = conditionalAverage(cloud, snapshot.I2.field, axis=snapshot.ql.axisXY)
            cloudFraction1sigma1 = cloudFraction1*(1-snapshot.I2.av)
            cloudFraction2sigma2 = cloudFraction2*snapshot.I2.av
            
            times.append(time)
            if not True in cloudz:
                cloudTops[time] = 0.
                cloudBases[time] = 0.
            else:
                cloudTops[time] = np.max(z[cloudz])
                cloudBases[time] = np.min(z[cloudz])
            cloudCovers[time]  = calculateCloudCover(cloud, axis=(snapshot.keys.zi))
            cloudCovers1[time] = calculateCloudCover(cloud * np.invert(snapshot.I2.field), axis=(snapshot.keys.zi))
            cloudCovers2[time] = calculateCloudCover(cloud * snapshot.I2.field, axis=(snapshot.keys.zi))
            cloudFractions[time]  = cloudFraction
            cloudFractions1[time] = cloudFraction1
            cloudFractions2[time] = cloudFraction2
            cloudFractions1sigma1[time] = cloudFraction1sigma1
            cloudFractions2sigma2[time] = cloudFraction2sigma2
            
            print("Cloud cover: {:.3f}".format(cloudCovers[time]))
            print("Cloud base: {:.1f}m".format(cloudBases[time]))
            print("Cloud top: {:.1f}m".format(cloudTops[time]))
            
            '''
            plotCloudFraction(
                snapshot.z,
                cloudFraction,
                id = "all",
                folder = folderTime
            )
            
            plotCloudFraction(
                snapshot.z,
                cloudFraction1,
                id = "1",
                folder = folderTime
            )
            
            plotCloudFraction(
                snapshot.z,
                cloudFraction2,
                id = "2",
                folder = folderTime
            )
            '''
            
            
        del les
        del snapshot
    
    cloudTop = np.zeros_like(times, dtype=float)
    cloudBase = np.zeros_like(times, dtype=float)
    cloudCover = np.zeros_like(times, dtype=float)
    cloudCover1 = np.zeros_like(times, dtype=float)
    cloudCover2 = np.zeros_like(times, dtype=float)
    cloudFraction  = np.zeros((len(cloudFractions[times[0]]),  len(times)))
    cloudFraction1 = np.zeros((len(cloudFractions1[times[0]]), len(times)))
    cloudFraction2 = np.zeros((len(cloudFractions2[times[0]]), len(times)))
    cloudFraction1sigma1 = np.zeros((len(cloudFractions1sigma1[times[0]]), len(times)))
    cloudFraction2sigma2 = np.zeros((len(cloudFractions2sigma2[times[0]]), len(times)))
    
    times = sorted(times)
    for n in range(len(times)):
        time = times[n]
        cloudTop[n]  = cloudTops[time]
        cloudBase[n]  = cloudBases[time]
        cloudCover[n]  = cloudCovers[time]
        cloudCover1[n] = cloudCovers1[time]
        cloudCover2[n] = cloudCovers2[time]
        cloudFraction[:,n] = cloudFractions[time]
        cloudFraction1[:,n] = cloudFractions1[time]
        cloudFraction2[:,n] = cloudFractions2[time]
        cloudFraction1sigma1[:,n] = cloudFractions1sigma1[time]
        cloudFraction2sigma2[:,n] = cloudFractions2sigma2[time]
    
    data = {}
    data["t_cloud_fraction"] = np.array(times)
    data["z_cloud_fraction"] = z
    data["cloud_top"]  = cloudTop
    data["cloud_base"]  = cloudBase
    data["cloud_cover"]  = cloudCover
    data["cloud_cover1"] = cloudCover1
    data["cloud_cover2"] = cloudCover2
    data["cloud_fraction"]  = cloudFraction
    data["cloud_fraction1"] = cloudFraction1
    data["cloud_fraction2"] = cloudFraction2
    data["cloud_fraction1_sigma1"] = cloudFraction1sigma1
    data["cloud_fraction2_sigma2"] = cloudFraction2sigma2
    
    folder = os.path.join(folder.outputs, "cloudContour")
    if not os.path.isdir(folder):
        os.makedirs(folder)
    
    savemat(os.path.join(folder, "cloud_fraction.mat"), data)
Beispiel #7
0
def main():
    # indicatorFunction="basic"
    # indicatorFunction="plume"
    indicatorFunction = "plumeEdge"

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    lesDiagnostics = getScmData(os.path.join(folder.data, "LES_transfers.mat"))

    for key in lesDiagnostics:
        print(key)

    # Create plots for each snapshot in time
    t = [8.89 * 3600]
    for n in range(len(t)):
        print("Processing timestep {} (t = {:.2f}hrs, {}s)".format(
            n + 1,
            float(t[n]) / 3600., t[n]))

        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))
        '''
        Plot comparisons of vertical profiles
        '''
        plotVerticalProfileComparison("u",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Horizontal velocity",
                                      xlabel="u (m/s)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("v",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Horizontal velocity",
                                      xlabel="v (m/s)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("w",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Vertical velocity",
                                      xlabel="w (m/s)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("theta",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Potential temperature",
                                      xlabel="$\\theta$ (K)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("qv",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Water vapour",
                                      xlabel="$q_v$ (kg/kg)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("ql",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Liquid water",
                                      xlabel="$q_l$ (kg/kg)",
                                      folder=folderTime,
                                      plotZero=True)
        '''
        Plot the transferred properties during entrainment and detrainment - the b_ij coefficients
        '''
        plotTransferredProperties("u",
                                  "plume",
                                  "plumeEdge",
                                  title="Horizontal velocity",
                                  xlabel="$b_{ij}$ for u",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("v",
                                  "plume",
                                  "plumeEdge",
                                  title="Horizontal velocity",
                                  xlabel="$b_{ij}$ for v",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("w",
                                  "plume",
                                  "plumeEdge",
                                  title="Vertical velocity",
                                  xlabel="$b_{ij}$ for w",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("theta",
                                  "plume",
                                  "plumeEdge",
                                  title="Potential temperature",
                                  xlabel="$b_{ij}$ for $\\theta$",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("qv",
                                  "plume",
                                  "plumeEdge",
                                  title="Water vapour",
                                  xlabel="$b_{ij}$ for $q_v$",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("ql",
                                  "plume",
                                  "plumeEdge",
                                  title="Liquid water",
                                  xlabel="$b_{ij}$ for $q_l$",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)
Beispiel #8
0
def lesVerticalProfiles(id="LEM",
                        caseStudy="ARM",
                        indicatorFunction="basic",
                        netcdfFile=None,
                        thetaMean=None):
    '''
    Plot the vertical profiles of various fields in the Large Eddy Simulation (LES) data
    for comparison with Single Column Models (SCMs).
    
    :param id: The simulation source type, set to either "ARM" or "MONC", str.
    :param caseStudy: The name of the case study to be plot, str.
    :param indicatorFunction: The type of structure to overlay onto the cloud, str.
    :param netcdfFile: Specify the netcdf file to open (all files processed if none selected), str.
    :param thetaMean: Specify a background profile to add to the potential temperature, float np.ndarray.
    '''

    # Fetch folders for code structure
    if id == "LEM":
        folder = folders(id=id,
                         folderScripts=os.path.dirname(
                             os.path.realpath(__file__)),
                         folderData="/mnt/f/Desktop/LES_Data")
    elif id == "MONC":
        folder = folders(id=f"{id}_{caseStudy}",
                         folderScripts=os.path.dirname(
                             os.path.realpath(__file__)),
                         folderData=f"/mnt/c/{id}_{caseStudy}")

        thetaMean = get1dProfiles(folder.data1d, key="theta_mean")
    else:
        raise ValueError(f"id {id} is not valid.")

    if netcdfFile:
        files = [os.path.join(folder.data, netcdfFile)]
    else:
        # Get all available NetCFD files
        files = getFilesInFolder(folder.data, extension=".nc")

    for i, file in enumerate(files):
        print(f"\nProcessing 3D file: {file} (file {i+1} of {len(files)})")

        # Get Large Eddy Simulation data
        les = getLesData(file,
                         id=id,
                         indicatorFunction=indicatorFunction,
                         thetaMeanProfiles=thetaMean)

        # Create plots for each snapshot in time
        for n in range(len(les.t)):
            print("\nProcessing timestep {} (t = {:.2f}hrs,  t = {:.1f}s)".
                  format(n + 1,
                         float(les.t[n]) / 3600., float(les.t[n])))

            folderTime = os.path.join(folder.outputs,
                                      "time_{}".format(int(les.t[n])))
            if not os.path.isdir(folderTime):
                os.makedirs(folderTime)

            snapshot = les.data[n]

            # Volume fraction of fluid 2
            plotVolumeFraction(snapshot.z,
                               snapshot.I2,
                               folder=folderTime,
                               id=indicatorFunction)

            # Mean profiles
            plotVerticalProfile(snapshot.z,
                                snapshot.u,
                                title="Horizontal velocity",
                                xlabel="u (m/s)",
                                folder=folderTime,
                                id=indicatorFunction,
                                plotZero=True)

            plotVerticalProfile(snapshot.z,
                                snapshot.v,
                                title="Horizontal velocity",
                                xlabel="v (m/s)",
                                folder=folderTime,
                                id=indicatorFunction,
                                plotZero=True)

            plotVerticalProfile(snapshot.z,
                                snapshot.w,
                                title="Vertical velocity",
                                xlabel="w (m/s)",
                                folder=folderTime,
                                id=indicatorFunction,
                                plotZero=True)

            plotVerticalProfile(snapshot.z,
                                snapshot.th,
                                title="Potential temperature",
                                xlabel="$\\theta$ (K)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.thv,
                                title="Virtual potential temperature",
                                xlabel="$\\theta_v$ (K)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.b,
                                title="Buoyancy",
                                xlabel="b (m s$^2$)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.q,
                                title="Water vapour",
                                xlabel="$q_t$ (kg/kg)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.qv,
                                title="Water vapour",
                                xlabel="$q_v$ (kg/kg)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.ql,
                                title="Liquid water",
                                xlabel="$q_l$ (kg/kg)",
                                folder=folderTime,
                                id=indicatorFunction)

            plotVerticalProfile(snapshot.z,
                                snapshot.qr,
                                title="Radioactive tracer",
                                xlabel="$q_r$ (kg/kg)",
                                folder=folderTime,
                                id=indicatorFunction)

            # Variances
            plotVerticalVariances(snapshot.z,
                                  snapshot.u,
                                  title="Horizontal velocity variance",
                                  xlabel="$\\overline{u'u'}$ (m$^2$/s$^2$)",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.v,
                                  title="Horizontal velocity variance",
                                  xlabel="$\\overline{v'v'}$ (m$^2$/s$^2$)",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.w,
                                  title="Horizontal velocity variance",
                                  xlabel="$\\overline{w'w'}$ (m$^2$/s$^2$)",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(
                snapshot.z,
                snapshot.th,
                title="Potential temperature variance",
                xlabel="$\\overline{\\theta'\\theta'}$ (K$^2$)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalVariances(
                snapshot.z,
                snapshot.thv,
                title="Virtual potential temperature variance",
                xlabel="$\\overline{\\theta_v'\\theta_v'}$ (K$^2$)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.b,
                                  title="Buoyancy variance",
                                  xlabel="$\\overline{b'b'}$ (m$^2$/s$^4$)",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.q,
                                  title="Total moisture variance",
                                  xlabel="$\\overline{q'q'}$",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.qv,
                                  title="Water vapour variance",
                                  xlabel="$\\overline{q_v'q_v'}$",
                                  folder=folderTime,
                                  id=indicatorFunction)
            plotVerticalVariances(snapshot.z,
                                  snapshot.ql,
                                  title="Liquid water variance",
                                  xlabel="$\\overline{q_l'q_l'}$",
                                  folder=folderTime,
                                  id=indicatorFunction)

            # Vertical fluxes
            plotVerticalFluxes(
                snapshot.z,
                snapshot.u,
                title="Horizontal velocity fluxes",
                xlabel="$\\sigma_i \\overline{w'u'}$ (m$^2$/s$^2$)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.v,
                title="Horizontal velocity fluxes",
                xlabel="$\\sigma_i \\overline{w'v'}$ (m$^2$/s$^2$)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.th,
                title="Potential temperature fluxes",
                xlabel="$\\sigma_i \\overline{w'\\theta'}$ (K m/s)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.thv,
                title="Virtual potential temperature fluxes",
                xlabel="$\\sigma_i \\overline{w'\\theta_v'}$ (K m/s)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.b,
                title="Buoyancy fluxes",
                xlabel="$\\sigma_i \\overline{w'b'}$ (m$^2$/s$^3$)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.q,
                title="Total moisture fluxes",
                xlabel="$\\sigma_i \\overline{w'q'}$ (kg/kg m/s)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.qv,
                title="Water vapour fluxes",
                xlabel="$\\sigma_i \\overline{w'q_v'}$ (kg/kg m/s)",
                folder=folderTime,
                id=indicatorFunction)
            plotVerticalFluxes(
                snapshot.z,
                snapshot.ql,
                title="Liquid water fluxes",
                xlabel="$\\sigma_i \\overline{w'q_l'}$ (kg/kg m/s)",
                folder=folderTime,
                id=indicatorFunction)
Beispiel #9
0
def main():

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    # Get Large Eddy Simulation data
    les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc"))
    # les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc"), indicatorFunction="basic")

    # Create plots for each snapshot in time
    for n in range(len(les.t)):
        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))
        if not os.path.isdir(folderTime):
            os.makedirs(folderTime)

        snapshot = les.data[n]

        # Create plots for each layer in the vertical
        for k in range(len(snapshot.z)):
            layer = snapshot.z[k] * 1e-3
            title = "z = {:.2f}km (id={})".format(layer, k + 1)
            print "Layer {} ({:.3f}km)".format(k + 1, layer)

            # Histogram for vertical velocity, w
            plotLayerHistogram(snapshot.w,
                               snapshot.I2,
                               layer,
                               k,
                               title=title,
                               folder=os.path.join(folderTime,
                                                   snapshot.w.name))

            # Histogram for potential temperature, theta
            plotLayerHistogram(snapshot.theta,
                               snapshot.I2,
                               layer,
                               k,
                               title=title,
                               folder=os.path.join(folderTime,
                                                   snapshot.theta.name))

            # Histogram for water vapour, qv
            plotLayerHistogram(snapshot.qv,
                               snapshot.I2,
                               layer,
                               k,
                               title=title,
                               folder=os.path.join(folderTime,
                                                   snapshot.qv.name))

            # Histogram for liquid water, ql
            plotLayerHistogram(snapshot.ql,
                               snapshot.I2,
                               layer,
                               k,
                               title=title,
                               folder=os.path.join(folderTime,
                                                   snapshot.ql.name))

    # Remove les data to clear memory
    totalTimesteps = len(les.t)
    totalImages = min(len(snapshot.z), 150)
    del les
    del snapshot

    # Create gif animations for generated plots
    for n in range(totalTimesteps):
        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))
        imageListW = []
        imageListTheta = []
        imageListQv = []
        imageListQl = []

        for k in range(totalImages):
            imageListW.append(
                os.path.join(os.path.join(folderTime, "w"),
                             "histogram_w_{}.png".format(k + 1)))
            imageListTheta.append(
                os.path.join(os.path.join(folderTime, "theta"),
                             "histogram_theta_{}.png".format(k + 1)))
            imageListQv.append(
                os.path.join(os.path.join(folderTime, "qv"),
                             "histogram_qv_{}.png".format(k + 1)))
            imageListQl.append(
                os.path.join(os.path.join(folderTime, "ql"),
                             "histogram_ql_{}.png".format(k + 1)))

        makeGif("histogram_w.gif", imageListW, folder=folderTime, delay=8)
        makeGif("histogram_theta.gif",
                imageListTheta,
                folder=folderTime,
                delay=8)
        makeGif("histogram_qv.gif", imageListQv, folder=folderTime, delay=8)
        makeGif("histogram_ql.gif", imageListQl, folder=folderTime, delay=8)
def calculateFields(id="default",
                    gratingType="triangle",
                    beamRadius=1.2,
                    gaussian=True,
                    imperfection=False,
                    resolution=100,
                    rangeX=[-0.55, 0.55],
                    rangeY=[-0.55, 0.55],
                    rangeZ=[0., 1.1],
                    precisionCoords=4,
                    precisionData=2):
    '''
    Generate the acceleration and radiation profiles for a neutral atom in a 
    Magneto-Optical Trap with one laser pointed down on a horizontal surface where
    a reflection grating is located.
    
    Args
    id:               Data id used for the naming of output files
    gratingType:      Shape of grating etches/grooves. Valid parameters are "triangle" and "square"
    beamRadius:       The incident laser beam radius in cm.
    gaussian:         Is the beam profile Gaussian or uniform? Boolean only.
    imperfection:     If True, some of the laser beam will be diffracted to 0th order (reflection)
    resolution:       Resolution of the data in all 3 axes. resolution x 2 = computation x 8.
    rangeX:           Range of x values to be evaluated in cm.
    rangeY:           Range of x values to be evaluated in cm.
    rangeZ:           Range of x values to be evaluated in cm.
    precisionCoords:  Precision of coordinate data when writen to output file.
    precisionData:    Precision of field data when writen to output file.
    '''

    print(f"\nGenerating fields for configuration: {id}")

    folder = folders(id=id,
                     folderScripts=os.path.dirname(os.path.realpath(__file__)))

    # Get grating geometry and properties
    if gratingType == "square":
        gratings = makeSquareGrating()
    elif gratingType == "triangle":
        gratings = makeTriangleGrating()
    else:
        gratings = makeSquareGrating()

    # 3D Coordinate and Acceleration vector fields.
    axisX = np.linspace(rangeX[0], rangeX[1], resolution)
    axisY = np.linspace(rangeY[0], rangeY[1], resolution)
    axisZ = np.linspace(rangeZ[0], rangeZ[1], resolution)
    z, y, x = np.meshgrid(axisZ, axisY, axisX, indexing='ij')
    coords = np.stack((x, y, z), axis=-1)

    # Data arrays
    a = np.zeros(coords.shape)
    radPressure = np.zeros(coords.shape)
    waveVector = np.zeros(coords.shape)

    print("Generating fields from incident beam")

    # Compute acceleration or radiation pressure from incident laser beam.
    intensity = np.ones(x.shape)
    if gaussian == True:
        intensity *= np.e**(-(x**2 + y**2) / 2.)

    k = np.array([0., 0., -1.])
    waveVector[...] = k

    a += acceleration(waveVector, coords, I=intensity)
    radPressure[...] += intensity[..., None] * waveVector

    # Ignore regions not within the beam radius
    conditionBeam = x**2 + y**2 <= beamRadius**2
    a *= conditionBeam[..., None]
    radPressure *= conditionBeam[..., None]

    # Compute acceleration or radiation pressure from 0th order beam.
    if imperfection == True:
        print("Generating fields from 0th-order diffracted beam")

        intensity = 0.01
        if gaussian == True:
            intensity *= np.exp(-(0.5 * x)**2)

        k = np.array([0., 0., 1.])
        waveVector[...] = k

        a += acceleration(waveVector, coords, I=intensity, factor=-1.)
        radPressure[...] += intensity[..., None] * waveVector

    switch = True
    for grating in gratings:
        print("Generating fields from grating segment")

        if switch == True:
            switch = False
            factor = -1
        else:
            factor = 1

        # Compute acceleration or radiation pressure from kth grating 1st order beam.
        intensity = grating.reflectivity * grating.intensity(
            coords, factor, beamRadius, gaussian=gaussian)
        # Unit vector of diffracted beam
        waveVector[...] = grating.k
        radPressure += waveVector * intensity[..., None]
        a += acceleration(waveVector, coords, I=intensity, factor=-1.)

        # Compute acceleration or radiation pressure from kth grating 1st order beam in other direction.
        intensity = grating.reflectivity * grating.intensity(
            coords, -factor, beamRadius, gaussian=gaussian)
        # Unit vector of diffracted beam
        waveVector[...] = grating.k
        radPressure += waveVector * intensity[..., None]
        a += acceleration(waveVector, coords, I=intensity, factor=-1.)

    # Store the acceleration magnitude and the components of the acceleration.
    aMag = np.sqrt(np.sum(a * a, axis=(a.ndim - 1)))
    radPressureMag = np.sqrt(
        np.sum(radPressure * radPressure, axis=(radPressure.ndim - 1)))

    # Save fields for future use
    np.savez_compressed(
        os.path.join(folder.outputs, "fieldData.npz"),
        id=id,
        gratingType=gratingType,
        beamRadius=beamRadius,
        gaussian=gaussian,
        imperfection=imperfection,
        resolution=resolution,
        rangeX=rangeX,
        rangeY=rangeY,
        rangeZ=rangeZ,
        axisX=axisX,
        axisY=axisY,
        axisZ=axisZ,
        x=x.round(decimals=precisionCoords),
        y=y.round(decimals=precisionCoords),
        z=z.round(decimals=precisionCoords),
        a=a.round(decimals=precisionData),
        aMag=aMag.round(decimals=precisionData),
        radPressure=radPressure.round(decimals=precisionData),
        radPressureMag=radPressureMag.round(decimals=precisionData))
def main():
    # indicatorFunction="basic"
    # indicatorFunction="plume"
    indicatorFunction = "plumeEdge"

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    lesDiagnostics = getScmData(os.path.join(folder.data, "LES_transfers.mat"))

    for key in lesDiagnostics:
        print(key)

    # Create plots for each snapshot in time
    t = [8.89 * 3600]
    for n in range(len(t)):
        print("Processing timestep {} (t = {:.2f}hrs, {}s)".format(
            n + 1,
            float(t[n]) / 3600., t[n]))

        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))

        id = "particlesEntrainDetrain"
        folderVertical = os.path.join(folderTime, "profilesMean")
        if id != "":
            folderVertical = os.path.join(folderVertical, id)
        if not os.path.isdir(folderVertical):
            os.makedirs(folderVertical)

        # Save vertical profiles for future use
        indexTime = np.argmin(np.abs(lesDiagnostics["times_t"][0] - t[n]))
        print("Time")
        print(indexTime)
        print(lesDiagnostics["times_t"][0][indexTime])
        np.savez(os.path.join(folderVertical, "z_profile_w.npz"),
                 z=lesDiagnostics["z_lev"][0][:-1] / 1000.,
                 fluid1=lesDiagnostics["w_hat_up"][:, indexTime],
                 fluid2=lesDiagnostics["w_det_up"][:, indexTime],
                 fluid1Std=0 * lesDiagnostics["w_hat_up"][:, indexTime],
                 fluid2Std=0 * lesDiagnostics["w_det_up"][:, indexTime],
                 fluid1Min=np.min(lesDiagnostics["w_hat_up"][:, indexTime]),
                 fluid1Max=np.max(lesDiagnostics["w_hat_up"][:, indexTime]),
                 fluid2Min=np.min(lesDiagnostics["w_det_up"][:, indexTime]),
                 fluid2Max=np.max(lesDiagnostics["w_det_up"][:, indexTime]))
        np.savez(os.path.join(folderVertical, "z_profile_qv.npz"),
                 z=lesDiagnostics["z_lev"][0][:-1] / 1000.,
                 fluid1=lesDiagnostics["qv_hat_up"][:, indexTime],
                 fluid2=lesDiagnostics["qv_det_up"][:, indexTime],
                 fluid1Std=0 * lesDiagnostics["qv_hat_up"][:, indexTime],
                 fluid2Std=0 * lesDiagnostics["qv_det_up"][:, indexTime],
                 fluid1Min=np.min(lesDiagnostics["qv_hat_up"][:, indexTime]),
                 fluid1Max=np.max(lesDiagnostics["qv_hat_up"][:, indexTime]),
                 fluid2Min=np.min(lesDiagnostics["qv_det_up"][:, indexTime]),
                 fluid2Max=np.max(lesDiagnostics["qv_det_up"][:, indexTime]))
        np.savez(os.path.join(folderVertical, "z_profile_theta.npz"),
                 z=lesDiagnostics["z_lev"][0][:-1] / 1000.,
                 fluid1=lesDiagnostics["th_hat_up"][:, indexTime],
                 fluid2=lesDiagnostics["th_det_up"][:, indexTime],
                 fluid1Std=0 * lesDiagnostics["th_hat_up"][:, indexTime],
                 fluid2Std=0 * lesDiagnostics["th_det_up"][:, indexTime],
                 fluid1Min=np.min(lesDiagnostics["th_hat_up"][:, indexTime]),
                 fluid1Max=np.max(lesDiagnostics["th_hat_up"][:, indexTime]),
                 fluid2Min=np.min(lesDiagnostics["th_det_up"][:, indexTime]),
                 fluid2Max=np.max(lesDiagnostics["th_det_up"][:, indexTime]))

        plotVerticalProfileComparison("w",
                                      "plume",
                                      "particlesEntrainDetrain",
                                      title="Vertical velocity",
                                      xlabel="w (m/s)",
                                      folder=folderTime,
                                      plotZero=True)

        plotVerticalProfileComparison("qv",
                                      "plume",
                                      "particlesEntrainDetrain",
                                      title="Water vapour",
                                      xlabel="$q_v$",
                                      folder=folderTime,
                                      plotZero=True)

        # plotVerticalProfileComparison(
        # "theta", "plume", "particlesEntrainDetrain",
        # title="Potential Temperature",
        # xlabel="$\\theta$ (K)",
        # folder=folderTime,
        # plotZero=True
        # )

        plotTransferredProperties("w",
                                  "plume",
                                  "particlesEntrainDetrain",
                                  title="Vertical velocity",
                                  xlabel="$b_{ij}$ for w",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        plotTransferredProperties("qv",
                                  "plume",
                                  "particlesEntrainDetrain",
                                  title="Water vapour",
                                  xlabel="$b_{ij}$ for $q_v$",
                                  yMarkers=[1., 2.8],
                                  folder=folderTime,
                                  plotZero=True)

        indexTime = np.argmin(np.abs(lesDiagnostics["times_t"][0] - t[n]))
        zLes = lesDiagnostics["z_lev"][0][:-1] / 1000.
        w2Les = lesDiagnostics["w_up"][:, indexTime]
        w12Les = lesDiagnostics["w_det_up"][:, indexTime]
        w21Les = lesDiagnostics["w_hat_up"][:, indexTime]
        th2Les = lesDiagnostics["th_up"][:, indexTime]
        th12Les = lesDiagnostics["th_det_up"][:, indexTime]
        th21Les = lesDiagnostics["th_hat_up"][:, indexTime]
        qv2Les = lesDiagnostics["qv_up"][:, indexTime]
        qv12Les = lesDiagnostics["qv_det_up"][:, indexTime]
        qv21Les = lesDiagnostics["qv_hat_up"][:, indexTime]

        plotVerticalProfileComparison(
            "w",
            "plume",
            "plumeEdge",
            id3="plumeEdgeEntrain",
            id4="plumeEdgeDetrain",
            title="Vertical velocity",
            xlabel="w (m/s)",
            folder=folderTime,
            plotZero=True,
            # additionalLines=[[w12Les,zLes,"r"],[w21Les,zLes,"b"]]
            # additionalLines=[[w2Les,zLes,"k"]]
        )

        plotVerticalProfileComparison(
            "theta",
            "plume",
            "plumeEdge",
            id3="plumeEdgeEntrain",
            id4="plumeEdgeDetrain",
            title="Potential temperature",
            xlabel="$\\theta$ (K)",
            folder=folderTime,
            plotZero=True,
            additionalLines=[[th12Les, zLes, "k"], [th21Les, zLes, "#888888"]])

        plotVerticalProfileComparison("qv",
                                      "plume",
                                      "plumeEdge",
                                      id3="plumeEdgeEntrain",
                                      id4="plumeEdgeDetrain",
                                      title="Water vapour",
                                      xlabel="$q_v$ (kg/kg)",
                                      folder=folderTime,
                                      plotZero=True,
                                      additionalLines=[[qv12Les, zLes, "r"],
                                                       [qv21Les, zLes, "b"]])
Beispiel #12
0
def simulateAtoms(id="default"):
    '''
    Generate plots for the acceleration and radiation profiles for a neutral atom in a 
    Magneto-Optical Trap with one laser pointed down on a horizontal surface where
    a reflection grating is located.
    
    NOTE: plotContour must be run before using plotFields
    
    Args
    id:             Data id used for the input data filename and the output files
    '''

    print(f"\nPlotting fields for configuration: {id}")

    folder = folders(id=id,
                     folderScripts=os.path.dirname(os.path.realpath(__file__)))

    # Save fields for future use
    data = np.load(os.path.join(folder.outputs, "fieldData.npz"))

    x = data["x"]
    y = data["y"]
    z = data["z"]
    a = data["a"]
    aMag = data["aMag"]
    axisX = data["axisX"]
    axisY = data["axisY"]
    axisZ = data["axisZ"]
    coords = np.stack((x, y, z), axis=-1)

    # Generate particles
    particles = []
    nParticles = 50
    for i in range(nParticles):
        particles.append(
            particle([
                0.5 * random.uniform(data["axisX"][0], data["axisX"][-1]),
                0.5 * random.uniform(data["axisY"][0], data["axisY"][-1]),
                random.uniform(data["axisZ"][0], data["axisZ"][-1])
            ], [0, 0, 0],
                     dragCoefficient=10.))

    timestep = 5e-4
    timesteps = 500
    for i in range(nParticles):
        print("Simulating trajectory of particle {}".format(i + 1))
        for n in range(timesteps):
            indexX = np.argmin(np.abs(axisX - particles[i].position[0]))
            indexY = np.argmin(np.abs(axisY - particles[i].position[1]))
            indexZ = np.argmin(np.abs(axisZ - particles[i].position[2]))

            acceleration = a[indexZ][indexY][indexX]

            particles[i].move(acceleration, timestep)

    # Generate 3D trajectory plots
    fig = plt.figure()
    ax = plt.axes(projection='3d')

    # Draw grating chip
    xGrating = [-1., -1., 1., 1.]
    yGrating = [-1., 1., 1., -1.]
    zGrating = [0., 0., 0., 0.]
    verts = [list(zip(xGrating, yGrating, zGrating))]
    poly = Poly3DCollection(verts, facecolors=[[0.5, 0.5, 0.5, 1.]])
    poly.set_sort_zpos(50)
    ax.add_collection3d(poly)

    # Draw laser radius
    theta = np.linspace(0, 2 * np.pi, 100)
    radius = 1.2
    xLaser = radius * np.cos(theta)
    yLaser = radius * np.sin(theta)
    zLaser = np.zeros_like(xLaser) + 0.01
    verts = [list(zip(xLaser, yLaser, zLaser))]
    poly = Poly3DCollection(verts, facecolors=[[1., 0., 0., 0.5]])
    poly.set_sort_zpos(100)
    ax.add_collection3d(poly)

    # Highlight region with weakest force-field (where particles should converge to)
    # cutOff = np.min(aMag) + 0.01*(np.mean(aMag)-np.min(aMag))
    # condition = aMag < cutOff
    # ax.plot(x[condition], y[condition], z[condition], ".", color="#888888")

    # Draw trajectories
    for i in range(nParticles):
        pos = np.array(particles[i].positions)
        zorder = 10000

        # Deal with particles that have gone through the ground
        if np.min(pos[:, 2]) < 0.:
            pos[:, 2] = np.maximum(pos[:, 2], 0 * pos[:, 2])

        ax.plot(pos[..., 0], pos[..., 1], pos[..., 2], zorder=zorder)
        ax.plot(pos[..., 0][-1],
                pos[..., 1][-1],
                pos[..., 2][-1],
                "ko",
                zorder=zorder)

    ax.set_xlim([axisX[0], axisX[-1]])
    ax.set_ylim([axisY[0], axisY[-1]])
    ax.set_zlim([axisZ[0], axisZ[-1]])

    ax.set_xlabel("x (cm)")
    ax.set_ylabel("y (cm)")
    ax.set_zlabel("z (cm)")

    # Save images from different perspectives
    for i in np.linspace(0, 1, 25):
        elevation = 90 * i
        angle = 90 + 360 * i
        ax.view_init(elev=elevation, azim=angle)
        plt.savefig(os.path.join(
            folder.outputs, "trajectories_{}_{}.png".format(id, int(360 * i))),
                    dpi=200)

    plt.close()
def prepareData(indicator="plume",
                id="MONC",
                caseStudy="ARM",
                times=[30000],
                cloudData=True):
    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)))

    variables = ["sigma", "q", "ql", "qv", "th", "thv", "b", "u", "v", "w"]
    # variables = ["ql", "qv", "th", "u", "w"]

    dataAll = dict(times=[])
    # dataAll = dict(LES_times=times)

    # Create plots for each snapshot in time
    for i, t in enumerate(times):
        print("Processing t={}s (timestep {} of {})".format(
            t, i + 1, len(times)))

        # idCaseStudy = f"{id}"
        idCaseStudy = f"{id}_{caseStudy}"
        folderTimeMean = os.path.join(folder.outputs, idCaseStudy,
                                      "time_{}".format(times[i]),
                                      "profilesMean", indicator)
        folderTimeVariances = os.path.join(folder.outputs, idCaseStudy,
                                           "time_{}".format(times[i]),
                                           "profilesVariances", indicator)
        folderTimeFluxes = os.path.join(folder.outputs, idCaseStudy,
                                        "time_{}".format(times[i]),
                                        "profilesFluxes", indicator)

        if os.path.isdir(folderTimeMean):
            dataAll["times"].append(t)

            data = {}
            for variable in variables:
                dataMean = loadProfiles(f"z_{variable}.mat", folderTimeMean)
                dataVariances = loadProfiles(f"z_{variable}{variable}.mat",
                                             folderTimeVariances)
                dataFluxes = loadProfiles(f"z_w{variable}.mat",
                                          folderTimeFluxes)

                # Small correction to the key naming convention
                key1 = f"{variable}1"
                key2 = f"{variable}2"
                key1New = f"{variable}_1"
                key2New = f"{variable}_2"
                for key in list(dataMean.keys()):
                    if key1 in key:
                        dataMean[key.replace(key1,
                                             key1New)] = dataMean.pop(key)
                    if key2 in key:
                        dataMean[key.replace(key2,
                                             key2New)] = dataMean.pop(key)
                        # print(f"Replaced {key} with {key.replace(key2, key2New)}")

                data = {**data, **dataMean, **dataVariances, **dataFluxes}

            # Additional diagnostics
            data["e_res1"] = 0.5 * (data["uu_res1"] + data["vv_res1"] +
                                    data["ww_res1"])
            data["e_res2"] = 0.5 * (data["uu_res2"] + data["vv_res2"] +
                                    data["ww_res2"])
            data["e_sg1"] = 0.5 * (data["uu_sg1"] + data["vv_sg1"] +
                                   data["ww_sg1"])
            data["e_sg2"] = 0.5 * (data["uu_sg2"] + data["vv_sg2"] +
                                   data["ww_sg2"])
            data["e_1"] = data["e_res1"] + data["e_sg1"]
            data["e_2"] = data["e_res2"] + data["e_sg2"]
            data["e_res"] = data["sigma_1"] * data["e_res1"] + data[
                "sigma_2"] * data["e_res2"]
            data["e_sg"] = data["sigma_1"] * data["e_sg1"] + data[
                "sigma_2"] * data["e_sg2"]
            data["e"] = data["e_res"] + data["e_sg"]

            # Add data
            for profile in data.keys():
                if "__" not in profile:

                    # Remove any ridiculous values from data set
                    data[profile][np.abs(data[profile]) > 1e10] = np.nan

                    profile_name = profile
                    # profile_name = f"LES_{profile}"
                    if profile_name not in dataAll:
                        dataAll[profile_name] = data[profile][0].reshape(
                            (len(data[profile][0]), 1))
                        # if profile != "z":
                        # dataAll[profile_name] *= 0
                    elif profile != "z":
                        # elif profile != "LES_z":
                        dataAll[profile_name] = np.concatenate(
                            (dataAll[profile_name], data[profile][0].reshape(
                                (len(data[profile][0]), 1))),
                            axis=-1)

    if cloudData:
        print("Adding cloud timeseries as well")
        folderCloud = os.path.join(folder.outputs, idCaseStudy, "cloudContour")
        dataCloud = loadProfiles("cloud_fraction.mat", folder=folderCloud)

        for profile in dataCloud.keys():
            if "__" not in profile:
                profile_name = profile
                # profile_name = f"LES_{profile}"
                if profile_name not in dataAll:
                    dataAll[profile_name] = dataCloud[profile]

    print("Data preparation complete for variables: {}".format(
        list(dataAll.keys())))

    folderOutput = os.path.join(folder.outputs, idCaseStudy, indicator)
    if not os.path.isdir(folderOutput):
        os.makedirs(folderOutput)
    savemat(os.path.join(folderOutput, "profiles.mat"), dataAll)
def main():
    
    # Fetch folders for code structure
    folder = folders(
        folderScripts=os.path.dirname(os.path.realpath(__file__)),
        folderData="/mnt/f/Desktop/LES_Data"
    )
    
    # Spacial and temporal discretisation
    dt = np.linspace(0.,2.,21)
    dt = np.linspace(0.,2.,51)
    xf = np.linspace(0.,1.,21)[:-1]
    xc = xf + (xf[1]-xf[0])/2.
    
    # Choose whether to have co-located grid (A-grid) or staggered grid (C-grid)
    velocity_face = False
    
    # Set resolution of parameter space to sample. 
    # Note that processing time scales as resolution^3
    resolution = 50
    resolution = 11

    eta1_arr = np.linspace(0.01,2.,resolution)
    u1_arr = np.linspace(0.,2.,resolution)
    S10_arr = np.linspace(0.,1.,resolution)

    eta1_arr = np.linspace(1e-8,2.,resolution)
    u1_arr = np.linspace(-150.,150.,resolution)
    S10_arr = np.linspace(0.,1.,resolution)
    # S10_arr = np.array([1.])

    # Placeholder arrays which will be multiplied by a factor later on
    eta0 = np.ones(len(xc))
    eta1 = np.ones(len(xc))
    theta0 = 300.*np.ones(len(xc))
    theta1 = 301.*np.ones(len(xc))
    u0 = np.ones(len(xf))
    u1 = np.ones(len(xf))
    S01 = np.ones(len(xc))
    S10 = np.ones(len(xc))
    
    # Make transfers like a square wave to test stability at steep gradients
    # Only necessary for staggered grids.
    for j in xrange(len(S01)):
        if xc[j] < 0.2 or xc[j] > 0.8:
            S01[j] = 0.
            S10[j] = 0.

    # Allowed numerical schemes
    # test_cases = [["flux","n","n",0,0],["flux","n+1","n+1",1,1]]
    test_cases = [["advective","n","n",0,1],["advective","n","n+1",0,0],["advective","n+1","n",1,1],["advective","n+1","n+1",1,0]]
    
    delta_ke_list = []
    for test_case in test_cases:
        momentum_eq = test_case[0]
        q = test_case[1]
        r = test_case[2]
        
        delta_ke_min =  1e+16*np.ones((2,2,len(dt)))
        delta_ke_max = -1e+16*np.ones((2,2,len(dt)))
        delta_ke_mean = np.zeros((2,2,len(dt)))
        delta_f_min =  1e+16*np.ones((2,2,len(dt)))
        delta_f_max = -1e+16*np.ones((2,2,len(dt)))
        delta_f_mean = np.zeros((2,2,len(dt)))
        
        # Try different timesteps. Explicit schemes tend to become unstable for large dt.
        for n in xrange(len(dt)):
            print dt[n]
            
            # Cycle over all parameter space
            for ie in eta1_arr:
                for iu in u1_arr:
                    for iS in S10_arr:
                        # eta = [(1-eta1_arr[ie])*eta0.copy(), eta1_arr[ie]*eta1.copy()]
                        eta = [eta0.copy(), ie*eta1.copy()]
                        theta = [theta0.copy(), theta1.copy()]
                        u = [u0.copy(),iu*u1.copy()]
                        S = [[0*S01,S01],[iS*S10,0*S10]]
                        
                        # Canculate energy, momentum and velocity changes
                        delta_ke_00,delta_f_00,u_new_00 = deltaE(eta, theta, u, dt[n], S, 0, 0, 0, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq)
                        delta_ke_01,delta_f_01,u_new_01 = deltaE(eta, theta, u, dt[n], S, 0, 1, 1, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq)
                        delta_ke_10,delta_f_10,u_new_10 = deltaE(eta, theta, u, dt[n], S, 1, 0, 0, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq)
                        delta_ke_11,delta_f_11,u_new_11 = deltaE(eta, theta, u, dt[n], S, 1, 1, 1, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq)
                        
                        # Update maximum recorded maxima and minima
                        delta_ke_min[0][0][n] = min(delta_ke_min[0][0][n], np.min(delta_ke_00))
                        delta_ke_max[0][0][n] = max(delta_ke_max[0][0][n], np.max(delta_ke_00))
                        delta_ke_mean[0][0][n] += np.mean(delta_ke_00)/(1.*resolution**3)
                        
                        delta_ke_min[0][1][n] = min(delta_ke_min[0][1][n], np.min(delta_ke_01))
                        delta_ke_max[0][1][n] = max(delta_ke_max[0][1][n], np.max(delta_ke_01))
                        delta_ke_mean[0][1][n] += np.mean(delta_ke_01)/(1.*resolution**3)
                        
                        delta_ke_min[1][0][n] = min(delta_ke_min[1][0][n], np.min(delta_ke_10))
                        delta_ke_max[1][0][n] = max(delta_ke_max[1][0][n], np.max(delta_ke_10))
                        delta_ke_mean[1][0][n] += np.mean(delta_ke_10)/(1.*resolution**3)
                        
                        delta_ke_min[1][1][n] = min(delta_ke_min[1][1][n], np.min(delta_ke_11))
                        delta_ke_max[1][1][n] = max(delta_ke_max[1][1][n], np.max(delta_ke_11))
                        delta_ke_mean[1][1][n] += np.mean(delta_ke_11)/(1.*resolution**3)
                        
                        delta_f_min[0][0][n] = min(delta_f_min[0][0][n], np.min(delta_f_00))
                        delta_f_max[0][0][n] = max(delta_f_max[0][0][n], np.max(delta_f_00))
                        delta_f_mean[0][0][n] += np.mean(delta_f_00)/(1.*resolution**3)
                        
                        delta_f_min[0][1][n] = min(delta_f_min[0][1][n], np.min(delta_f_01))
                        delta_f_max[0][1][n] = max(delta_f_max[0][1][n], np.max(delta_f_01))
                        delta_f_mean[0][1][n] += np.mean(delta_f_01)/(1.*resolution**3)
                        
                        delta_f_min[1][0][n] = min(delta_f_min[1][0][n], np.min(delta_f_10))
                        delta_f_max[1][0][n] = max(delta_f_max[1][0][n], np.max(delta_f_10))
                        delta_f_mean[1][0][n] += np.mean(delta_f_10)/(1.*resolution**3)
                        
                        delta_f_min[1][1][n] = min(delta_f_min[1][1][n], np.min(delta_f_11))
                        delta_f_max[1][1][n] = max(delta_f_max[1][1][n], np.max(delta_f_11))
                        delta_f_mean[1][1][n] += np.mean(delta_f_11)/(1.*resolution**3)
                        
                        
                        
        
        # Define colors and linestyles necessary to distinguish between similar profiles
        colors = [["#7a7a7a","b"],["r","k"]]
        linestyles = ["-","--",":","-."]
        linestyles = ["-","-","-","-"]
        
        # plt.figure(figsize=(5,5))
        plt.figure(figsize=(9,4))
        
        spread = np.zeros((4))
        for i in xrange(2):
            for j in xrange(2):
                spread[2*i+j] = np.max(delta_ke_max[i][j]-delta_ke_min[i][j])
        spread_index = spread.argsort()[::-1]
        
        # Fill region between maximum and minimum regions
        for n in spread_index:
            j = n%2
            i = (n-j)/2
            
            delta_ke_min[i][j] = delta_ke_min[i][j].clip(min=-1e2)
            delta_ke_max[i][j] = delta_ke_max[i][j].clip(max= 1e2)
            for k in xrange(len(delta_ke_min[i][j])):
                if delta_ke_min[i][j][k] < 1e-13 and delta_ke_min[i][j][k] > -1e-13:
                    delta_ke_min[i][j][k] = 0.
                if delta_ke_max[i][j][k] < 1e-13 and delta_ke_max[i][j][k] > -1e-13:
                    delta_ke_max[i][j][k] = 0.
            
            y1 = delta_ke_min[i][j]
            y2 = delta_ke_max[i][j]
            if i == j:
                plt.fill_between(dt, y1, y2, where= y2 >= y1, facecolor=colors[i][j], interpolate=True, linewidth=0., alpha = 0.5)
                
                
        
        for n in xrange(len(spread_index)):
            j = spread_index[n]%2
            i = (spread_index[n]-j)/2
            
            # If maximum value is 0 (to numerical precision), indicate the energy-diminishing properties
            linewidth = 3.
            linestyle = "--"
            if np.max(delta_ke_max[i][j]) < 1e-13:
                linestyle = "-"

            if i == j:
                plt.plot(dt,delta_ke_min[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth)
                plt.plot(dt,delta_ke_max[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth)
                
        
        plt.plot(dt,0*dt,":",color="w")
        
        # Labels and formating
        plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20)
        plt.ylabel("Rel. Energy change, $\\Delta E_{REL}$",fontsize=20)
        plt.xlim(dt[0],dt[-1])
        plt.ylim(-3.9999e-2,3.9999e-2)
        plt.xscale("sqrt2")
        plt.yscale("sqrt2")
        
        filename = "conservation_ke_{}_q_{}_r_{}.png".format(test_case[0],q.replace("+","p"),r.replace("+","p"))
        plt.savefig( 
            os.path.join(folder.outputs,  filename), 
            bbox_inches='tight', 
            dpi=200
        )
        plt.close()
        
        
        # Save profiles for final energy plot
        if q == "n" and r == "n":
            delta_ke_list.append( [delta_ke_min[0][1], delta_ke_max[0][1], "b"] )
        if q == "n+1" and r == "n":
            delta_ke_list.append( [delta_ke_min[1][1], delta_ke_max[1][1], "k"] )
        if q == "n" and r == "n+1":
            delta_ke_list.append( [delta_ke_min[0][0], delta_ke_max[0][0], "#7a7a7a"] )
        if q == "n+1" and r == "n+1":
            delta_ke_list.append( [delta_ke_min[1][0], delta_ke_max[1][0], "r"] )
        
        
        # plt.figure(figsize=(5,5))
        plt.figure(figsize=(9,4))
        
        spread = np.zeros((4))
        for i in xrange(2):
            for j in xrange(2):
                spread[2*i+j] = np.max(delta_f_max[i][j]-delta_f_min[i][j])
        spread_index = spread.argsort()[::-1]
        
        for n in spread_index:
            j = n%2
            i = (n-j)/2
            
            delta_f_min[i][j] = delta_f_min[i][j].clip(min=-1e2)
            delta_f_max[i][j] = delta_f_max[i][j].clip(max= 1e2)
            for k in xrange(len(delta_f_min[i][j])):
                if delta_f_min[i][j][k] < 1e-13 and delta_f_min[i][j][k] > -1e-13:
                    delta_f_min[i][j][k] = 0.
                if delta_f_max[i][j][k] < 1e-13 and delta_f_max[i][j][k] > -1e-13:
                    delta_f_max[i][j][k] = 0.
            
            y1 = delta_f_min[i][j]
            y2 = delta_f_max[i][j]
            plt.fill_between(dt, y1, y2, facecolor=colors[i][j], interpolate=True, alpha = 0.5, linewidth=0.)
            
        for n in xrange(len(spread_index)):
            j = spread_index[n]%2
            i = (spread_index[n]-j)/2
            
            linewidth = 3.
            if n == 0:
                linewidth = 4.
            
            # Indicate whether a scheme conserves momentum to numerical precision
            linestyle = "--"
            if np.max(delta_f_max[i][j]) <= 1e-2 and np.min(delta_f_min[i][j]) >= -1e-2:
                linestyle = "-"

            plt.plot(dt,delta_f_min[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth)
            plt.plot(dt,delta_f_max[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth)
        
        plt.plot(dt,0*dt,":",color="w")
        
        # Labels and formating
        plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20)
        plt.ylabel("Rel. mom. change, $\\Delta F_{REL}$",fontsize=20)
        plt.xlim(dt[0],dt[-1])
        plt.ylim(-40.,40.)
        plt.xscale("sqrt2")
        plt.yscale("sqrt2")
        
        filename = "conservation_f_{}_q_{}_r_{}.png".format(test_case[0],q.replace("+","p"),r.replace("+","p"))
        plt.savefig( 
            os.path.join(folder.outputs,  filename), 
            bbox_inches='tight', 
            dpi=200
        )
        plt.close()
    
    
    
    # Plot energy profiles of hand-selected schemes
    plt.figure(figsize=(9,4))
    
    for n in xrange(len(delta_ke_list)):
        y1 = delta_ke_list[n][0]
        y2 = delta_ke_list[n][1]
        plt.fill_between(dt, y1, y2, facecolor=delta_ke_list[n][2], interpolate=True, linewidth=0., alpha = 0.5)
            
            

    for n in xrange(len(delta_ke_list)):
        linestyle = "--"
        if np.max(delta_ke_list[n][1]) < 1e-13:
            linestyle = "-"
        plt.plot(dt,delta_ke_list[n][0],color=delta_ke_list[n][2], linestyle=linestyle, linewidth=3.)
        plt.plot(dt,delta_ke_list[n][1],color=delta_ke_list[n][2], linestyle=linestyle, linewidth=3.)
            

    plt.plot(dt,0*dt,":",color="w")

    plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20)
    plt.ylabel("Rel. Energy change, $\\Delta E_{REL}$",fontsize=20)

    plt.xlim(dt[0],dt[-1])
    plt.ylim(-3.9999e-2,3.9999e-2)
    plt.xscale("sqrt2")
    plt.yscale("sqrt2")

    plt.savefig(os.path.join(folder.outputs, "conservation_ke.png") , bbox_inches='tight', dpi=200)
    plt.close()
def main():
    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)))

    # Import the mesh for the fluid solver
    mesh = cubeMesh2D(xPeriodic=True)
    x = mesh.x
    z = mesh.z

    # Import finite volume operations using mesh geometry
    fvc = finiteVolumeFunctions(mesh)

    # Initialise the simulation
    simulation = runSettings(
        dt=0.01,  # Timestep for simulation
        tEnd=1000,  # End time (s) of simulation
        plotInterval=10.  # Plot every [plotInterval] seconds
    )

    # Constants
    T = 300
    R = 8.31
    g = mesh.volVectorField.copy()
    # g[:,:,1] = -9.81
    '''
    INITIAL CONDITIONS
    '''
    # Velocity field
    u = mesh.volVectorField.copy()
    u += 10.
    u[:49, :] = -10.
    u[:51, 50:150] = -10.

    # Density field
    rho = 0 * mesh.volScalarField.copy() + 1

    tracer = mesh.volScalarField.copy()
    tracer += 0.999
    tracer[:49, :] = 0.001
    tracer[:51, 50:150] = 0.001

    dt = simulation.dt

    # Plot initial conditions
    plotContour(x, z, tracer, "kelvinHelmholtz_0.png", folder=folder.outputs)

    # Run simulation until end time is reached
    while simulation.updateTime():
        sys.stdout.write("\rRunning simulation, t={}s".format(
            simulation.currentTime))
        sys.stdout.flush()

        pressure = rho * R * T

        # Continuity equation
        rho = rho - dt * fvc.div(rho, u, "upwind")
        rho = fvc.setBoundaryConditions(rho)

        # Momentum equation
        u = u - dt * fvc.uDotGradU(u, "upwind") + dt * g - dt * fvc.grad(
            pressure, "linear") / rho[:, :, None]
        u = fvc.setBoundaryConditions(u)

        # Advection of tracers which follow the flow
        tracer = tracer - dt * dot(u, fvc.grad(tracer, "upwind", u=u))

        if simulation.plotFigures():
            print "\nPlotting profiles at t={}s".format(simulation.currentTime)

            fileId = "kelvinHelmholtz_{}.png".format(
                simulation.currentTimeIndex)
            plotContour(x, z, tracer, fileId, folder=folder.outputs)
def plotFields(id="default"):
    '''
    Generate plots for the acceleration and radiation profiles for a neutral atom in a 
    Magneto-Optical Trap with one laser pointed down on a horizontal surface where
    a reflection grating is located.
    
    NOTE: plotContour must be run before using plotFields
    
    Args
    id:             Data id used for the input data filename and the output files
    '''

    print(f"\nPlotting fields for configuration: {id}")

    folder = folders(id=id,
                     folderScripts=os.path.dirname(os.path.realpath(__file__)))

    # Save fields for future use
    data = np.load(os.path.join(folder.outputs, "fieldData.npz"))

    slices = {}
    slices["XZ"] = {
        "xAxis":
        "x",
        "yAxis":
        "z",
        "xIndex":
        0,
        "yIndex":
        2,
        "location":
        "y = {:.2f} cm".format(data["axisY"][int(data["resolution"] / 2)]),
        "slice":
        np.s_[:, int(data["resolution"] / 2), :]
    }
    slices["YZ"] = {
        "xAxis":
        "y",
        "yAxis":
        "z",
        "xIndex":
        1,
        "yIndex":
        2,
        "location":
        "x = {:.2f} cm".format(data["axisX"][int(data["resolution"] / 2)]),
        "slice":
        np.s_[:, :, int(data["resolution"] / 2)]
    }
    slices["XY"] = {
        "xAxis":
        "x",
        "yAxis":
        "y",
        "xIndex":
        0,
        "yIndex":
        1,
        "location":
        "z = {:.2f} cm".format(data["axisZ"][int(data["resolution"] / 2)]),
        "slice":
        np.s_[int(data["resolution"] / 2), :, :]
    }

    for slice in slices:
        print("Plotting data for slice {}".format(slice))
        s = slices[slice]

        plotContour(data["axis" + s["xAxis"].upper()],
                    data["axis" + s["yAxis"].upper()],
                    data["radPressureMag"][s["slice"]],
                    id=id + "_radPressure_" + slice.lower(),
                    folder=folder.outputs,
                    xlabel="{} (cm)".format(s["xAxis"]),
                    ylabel="{} (cm)".format(s["yAxis"]),
                    ylabelCBar="Relative radiation pressure",
                    title="Radiation pressure field, {}".format(s["location"]),
                    u=data["radPressure"][s["slice"]][..., s["xIndex"]],
                    v=data["radPressure"][s["slice"]][..., s["yIndex"]],
                    vectorScale=10)

        plotContour(data["axis" + s["xAxis"].upper()],
                    data["axis" + s["yAxis"].upper()],
                    data["aMag"][s["slice"]],
                    id=id + "_a_" + slice.lower(),
                    folder=folder.outputs,
                    cmap="jet_r",
                    xlabel="{} (cm)".format(s["xAxis"]),
                    ylabel="{} (cm)".format(s["yAxis"]),
                    ylabelCBar="Relative acceleration",
                    title="Acceleration field, {}".format(s["location"]),
                    u=data["a"][s["slice"]][..., s["xIndex"]],
                    v=data["a"][s["slice"]][..., s["yIndex"]],
                    vectorScale=2e5)
def main():

    # Fetch folders for code structure
    folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)),
                     folderData="/mnt/f/Desktop/LES_Data")

    # Get Large Eddy Simulation data and Single Column Model data
    les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc"))
    scm = getScmData(os.path.join(folder.data, "SCM_results.mat"))

    # Create plots for each snapshot in time
    for n in range(len(les.t)):
        folderTime = os.path.join(folder.outputs, "timestep_{}".format(n))
        if not os.path.isdir(folderTime):
            os.makedirs(folderTime)

        snapshot = les.data[n]

        # Create plots for each layer in the vertical
        for k in range(len(snapshot.z)):
            layer = snapshot.z[k] * 1e-3
            title = "z = {:.2f}km (id={})".format(layer, k + 1)
            print "Layer {} ({:.3f}km)".format(k + 1, layer)

            scmGaussian = {}
            scmGaussian["sigma1"] = interpolateFromArray(
                scm["SCM_zw"][0], snapshot.z[k], scm["SCM_sigma1w"][:, 2])
            scmGaussian["sigma2"] = interpolateFromArray(
                scm["SCM_zw"][0], snapshot.z[k], scm["SCM_sigma2w"][:, 2])
            scmGaussian["w1"] = interpolateFromArray(scm["SCM_zw"][0],
                                                     snapshot.z[k],
                                                     scm["SCM_w_1"][:, 2])
            scmGaussian["w2"] = interpolateFromArray(scm["SCM_zw"][0],
                                                     snapshot.z[k],
                                                     scm["SCM_w_2"][:, 2])
            scmGaussian["wVar1"] = interpolateFromArray(
                scm["SCM_zw"][0], snapshot.z[k], scm["SCM_ww1"][:, 2])
            scmGaussian["wVar2"] = interpolateFromArray(
                scm["SCM_zw"][0], snapshot.z[k], scm["SCM_ww2"][:, 2])

            # Histogram for vertical velocity, w
            plotHistogramWithGaussian(snapshot.w,
                                      snapshot.I2,
                                      layer,
                                      k,
                                      title=title,
                                      folder=os.path.join(
                                          folderTime, snapshot.w.name),
                                      scmGaussian=scmGaussian)

            # Histogram for water vapour, qv
            # plotHistogramWithGaussian(
            # snapshot.qv,
            # snapshot.I2,
            # layer,
            # k,
            # title=title,
            # folder=os.path.join(folderTime, snapshot.qv.name)
            # )

            # Histogram for liquid water, ql
            # plotHistogramWithGaussian(
            # snapshot.ql,
            # snapshot.I2,
            # layer,
            # k,
            # title=title,
            # folder=os.path.join(folderTime, snapshot.ql.name)
            # )

    # Remove les data to clear memory
    totalTimesteps = len(les.t)
    totalImages = min(len(snapshot.z), 150)
    del les
    del snapshot