# Path: gprMax/constants.py

# 
# Path: gprMax/utilities.py
# def round_value(value, decimalplaces=0):
#     """Rounding function.
# 
#     Args:
#         value (float): Number to round.
#         decimalplaces (int): Number of decimal places of float to represent rounded value.
# 
#     Returns:
#         rounded (int/float): Rounded value.
#     """
# 
#     # Rounds to nearest integer (half values are rounded downwards)
#     if decimalplaces == 0:
#         rounded = int(d.Decimal(value).quantize(d.Decimal('1'), rounding=d.ROUND_HALF_DOWN))
# 
#     # Rounds down to nearest float represented by number of decimal places
#     else:
#         precision = '1.{places}'.format(places='0' * decimalplaces)
#         rounded = float(d.Decimal(value).quantize(d.Decimal(precision), rounding=d.ROUND_FLOOR))
# 
#     return rounded


import os
import sys
import numpy as np
    import pycuda.gpuarray as gpuarray
from struct import pack
from gprMax.constants import floattype
from gprMax.snapshots_ext import calculate_snapshot_fields
from gprMax.utilities import round_value


def gpu_initialise_snapshot_array(G):
    """Initialise array on GPU for to store field data for snapshots.

    Args:
        G (class): Grid class instance - holds essential parameters describing the model.

    Returns:
        snapE_gpu, snapH_gpu (float): numpy arrays of snapshot data on GPU.
    """


    # Get dimensions of largest requested snapshot
    for snap in G.snapshots:
        if snap.nx > Snapshot.nx_max:
            Snapshot.nx_max = snap.nx
        if snap.ny > Snapshot.ny_max:
            Snapshot.ny_max = snap.ny
        if snap.nz > Snapshot.nz_max:
            Snapshot.nz_max = snap.nz

    # GPU - blocks per grid - according to largest requested snapshot
    Snapshot.bpg = (int(np.ceil(((Snapshot.nx_max) * (Snapshot.ny_max) * (Snapshot.nz_max)) / Snapshot.tpb[0])), 1, 1)

    # 4D arrays to store snapshots on GPU, e.g. snapEx(time, x, y, z)
    numsnaps = 1 if G.snapsgpu2cpu else len(G.snapshots)
    snapEx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
    snapEy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
    snapEz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)

# Path: gprMax/constants.py

# 
# Path: gprMax/utilities.py
# def round_value(value, decimalplaces=0):
#     """Rounding function.
# 
#     Args:
#         value (float): Number to round.
#         decimalplaces (int): Number of decimal places of float to represent rounded value.
# 
#     Returns:
#         rounded (int/float): Rounded value.
#     """
# 
#     # Rounds to nearest integer (half values are rounded downwards)
#     if decimalplaces == 0:
#         rounded = int(d.Decimal(value).quantize(d.Decimal('1'), rounding=d.ROUND_HALF_DOWN))
# 
#     # Rounds down to nearest float represented by number of decimal places
#     else:
#         precision = '1.{places}'.format(places='0' * decimalplaces)
#         rounded = float(d.Decimal(value).quantize(d.Decimal(precision), rounding=d.ROUND_FLOOR))
# 
#     return rounded


# Path: gprMax/snapshots.py
import os
import sys
import numpy as np
    import pycuda.gpuarray as gpuarray
from struct import pack
from gprMax.constants import floattype
from gprMax.snapshots_ext import calculate_snapshot_fields
from gprMax.utilities import round_value



def gpu_initialise_snapshot_array(G):
    """Initialise array on GPU for to store field data for snapshots.

    Args:
        G (class): Grid class instance - holds essential parameters describing the model.

    Returns:
        snapE_gpu, snapH_gpu (float): numpy arrays of snapshot data on GPU.
    """


    # Get dimensions of largest requested snapshot
    for snap in G.snapshots:
        if snap.nx > Snapshot.nx_max:
            Snapshot.nx_max = snap.nx
        if snap.ny > Snapshot.ny_max:
            Snapshot.ny_max = snap.ny
        if snap.nz > Snapshot.nz_max:
            Snapshot.nz_max = snap.nz

    # GPU - blocks per grid - according to largest requested snapshot
    Snapshot.bpg = (int(np.ceil(((Snapshot.nx_max) * (Snapshot.ny_max) * (Snapshot.nz_max)) / Snapshot.tpb[0])), 1, 1)

    # 4D arrays to store snapshots on GPU, e.g. snapEx(time, x, y, z)
    numsnaps = 1 if G.snapsgpu2cpu else len(G.snapshots)
    snapEx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
    snapEy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
    snapEz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)

    snapHx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)