def compute_spectrum(
        self,
        filename_phys,
        params,
    ):

        #
        # Get meta information about job
        #

        self.job_metadata_available = False

        try:
            # Step 1) Determine job directory name
            jobdir = os.path.dirname(filename_phys)

            print("Loading data from job directory '" + jobdir + "'")

            # Step 2) Load job meta information
            j = JobData(jobdir=jobdir)

            self.job_metadata_available = True

        except Exception as e:
            print(str(e))
            self.job_metadata_available = False

        if self.job_metadata_available:
            data = j.get_flattened_data()

            if 'runtime.plane_domain_size' not in data:
                raise Exception(
                    "Physical domain size must be specified via runtime parameters in MULE"
                )

            domain_size = data['runtime.plane_domain_size']

            if isinstance(domain_size, list):
                domain_size = domain_size[0]

        #
        # The following code is converted from a development of Pedro Peixoto to fit into the MULE framework
        #

        # some parameter
        mmin = 0

        # Load file
        udata_ = PlaneDataPhysical(filename_phys)
        udata = udata_.data

        #Calculate spectrum
        #-----------------------------------

        print("Physical shape")
        print(udata.shape)

        uspec = np.fft.fft2(udata) / (udata.shape[0] * udata.shape[1])

        print("Spectral shape")
        print(uspec.shape)

        # Calculate amplitude spectrum
        data = np.multiply(uspec, np.conjugate(uspec))
        data = data.real

        n = data.shape[0]

        # Since data u,v data is real, the spectrum has a symmetry and all that matters is the 1st quadrant
        # we multiply by 2 to account for the symmetry
        data = 2 * data[0:int(n / 2) - 1, 0:int(n / 2) - 1]

        # Adjust data size
        n = data.shape[0]

        # m=int(n/2)+1
        m = int(2 * n / 3) + 1  #anti-aliasing cut
        if mmin == 0:
            mmin = m
        else:
            if m > mmin:
                m = mmin

        print("Anti-aliased spectrum region:", m)

        #Calculate energy per shell
        # TODO: convert to linspace
        r = np.arange(0, m + 1, 1)  # radius
        energy = np.zeros(m + 1)
        shell_pattern = np.zeros((m + 1, m + 1))

        print("Generating energy in shells (Each . is 1/", m, ")")
        for i in range(0, m):
            for j in range(0, m):
                k = np.sqrt(pow(float(i), 2) + pow(float(j), 2))
                intk = int(k)
                if intk < m:
                    energy[intk] = energy[intk] + data[i, j]
                    shell_pattern[i, j] = intk
            print(".", end='', flush=True)
            #print(i, j, k, intk, data[i,j], energy[intk], data.shape, energy.shape)

        print(".")

        #Quick check to see if things match
        #print("Energy in shells: ", energy[0:10])
        #print("Energy in first column of data: ", data[0:10,0])
        #print("Shell modes: ", r[0:10])
        #print("Pattern:\n", shell_pattern[0:10,0:10])

        self.spectrum = energy[:]
        self.spectrum_mode = r[:]

        if self.job_metadata_available:
            # Convert wavenumber to wavelength
            self.spectrum_wavelength = np.zeros(m + 1)
            self.spectrum_wavelength[1:] = domain_size * 1000 / r[1:]

        else:
            self.spectrum_wavelength = None
Example #2
0
    def compute_diff(
        self,
        filename_a,
        filename_b,
        params,
    ):

        # Load first file_b, to avoid wasting time for filename_a if filename_b doesn't exist
        file_b = PlaneDataPhysical(filename_b)
        file_a = PlaneDataPhysical(filename_a)

        self.norm_l1_value = 0.0
        self.norm_l2_value = 0.0
        self.norm_linf_value = 0.0
        self.norm_rms_value = 0.0
        self.N = 0

        size_ref_j = len(file_a.data)
        size_ref_i = len(file_a.data[0])
        size_cmp_j = len(file_b.data)
        size_cmp_i = len(file_b.data[0])

        if size_ref_j == size_cmp_j and size_ref_i == size_cmp_i:  # and False:
            self.info("Using 'default' method (matching resolutions)")

            data_ref = file_a.data
            data_cmp = file_b.data

        elif 'reduce_ref_to_cmp' in params:
            self.info("Using 'ref_reduce' method")

            #
            # Reduce reference solution, assuming that the
            # resolution is integer multiples of the one to compare with
            #

            data_ref = file_a.data
            data_cmp = file_b.data

            multiplier_j = size_ref_j / size_cmp_j
            multiplier_i = size_ref_i / size_cmp_i

            print("Dimensions of reference solution: ", size_ref_i, size_ref_j)
            print("Dimensions of method under analysis: ", size_cmp_i,
                  size_cmp_j)

            if not float(multiplier_i).is_integer() or not float(
                    multiplier_j).is_integer():
                print("Grids are not aligned")
                print("Try to use (TODO) interpolation script")
                print("Dimensions of method under analysis: ", size_cmp_i,
                      size_cmp_j)
                print("Multipliers: ", multiplier_i, multiplier_j)
                raise Exception("Grids not properly aligned")

            multiplier_j = int(multiplier_j)
            multiplier_i = int(multiplier_i)

            print("Using multipliers (int): ", multiplier_i, multiplier_j)

            data_ref_new = np.zeros(shape=data_cmp.shape)
            for j in range(0, size_cmp_j):
                for i in range(0, size_cmp_i):

                    data_ref_new[j, i] = 0.0
                    for sj in range(0, multiplier_j):
                        for si in range(0, multiplier_i):
                            data_ref_new[j,
                                         i] += data_ref[j * multiplier_j + sj,
                                                        i * multiplier_i + si]

                    data_ref_new[j, i] /= multiplier_i * multiplier_j

            data_ref = data_ref_new

        elif ('interpolate' in params and size_ref_j > size_cmp_j
              and size_ref_i > size_cmp_i) or ('interpolate_cmp_to_ref'
                                               in params):
            self.info("Using 'interpolate_cmp_to_ref' method")

            #
            # Interpolate solution to resolution of reference solution.
            # Note, that this can also lead to a reduction in case of a lower resolution of the reference
            #

            # This is the code written by Pedro which uses spline interpolation

            # Comparison via interpolation
            # print("Interpolation")
            # A-grid REFERENCE (file1) - sweet outputs only A grids physical space

            data_ref = file_a.data
            data_cmp = file_b.data

            ny_ref = len(file_a.data)
            nx_ref = len(file_a.data[0])
            print("REF resolution: " + str(nx_ref) + ", " + str(ny_ref))

            ny_cmp = len(file_b.data)
            nx_cmp = len(file_b.data[0])
            print("CMP resolution: " + str(nx_cmp) + ", " + str(ny_cmp))

            dx_ref = 1.0 / (nx_ref)
            dy_ref = 1.0 / (ny_ref)
            x_ref = np.linspace(0, 1, nx_ref, endpoint=False)
            y_ref = np.linspace(0, 1, ny_ref, endpoint=False)
            x_ref += dx_ref / 2  # Make it cell-centered
            y_ref += dy_ref / 2
            X_ref, Y_ref = np.meshgrid(x_ref, y_ref)

            # A-grid cmp file (file2)
            dx_cmp = 1.0 / nx_cmp
            dy_cmp = 1.0 / ny_cmp
            x_cmp = np.linspace(0, 1, nx_cmp, endpoint=False)
            y_cmp = np.linspace(0, 1, ny_cmp, endpoint=False)
            x_cmp += dx_cmp / 2
            y_cmp += dy_cmp / 2
            X_cmp, Y_cmp = np.meshgrid(x_cmp, y_cmp)

            # Create cubic interpolation of comparison
            # Data to be interpolated
            interp_spline = RectBivariateSpline(x_cmp, y_cmp, data_cmp)

            # Compute reduced reference resolution
            # Target grid
            data_cmp_high = interp_spline(x_ref, y_ref)

            data_cmp = data_cmp_high
            data_ref = data_ref

        elif ('interpolate' in params and size_ref_j < size_cmp_j
              and size_ref_i < size_cmp_i) or ('interpolate_ref_to_cmp'
                                               in params):
            self.info("Using 'interpolate_ref_to_cmp' method")

            #
            # Interpolate: REF => resolution(CMP)
            #

            #
            # Interpolate solution to resolution of reference solution.
            # Note, that this can also lead to a reduction in case of a lower resolution of the reference
            #

            # This is the code written by Pedro which uses spline interpolation

            # Comparison via interpolation
            # print("Interpolation")
            # A-grid REFERENCE (file1) - sweet outputs only A grids physical space

            data_ref = file_a.data
            data_cmp = file_b.data

            ny_ref = len(file_a.data)
            nx_ref = len(file_a.data[0])
            print("REF resolution: " + str(nx_ref) + ", " + str(ny_ref))

            ny_cmp = len(file_b.data)
            nx_cmp = len(file_b.data[0])
            print("CMP resolution: " + str(nx_cmp) + ", " + str(ny_cmp))

            dx_ref = 1.0 / nx_ref
            dy_ref = 1.0 / ny_ref
            x_ref = np.linspace(0, 1, nx_ref, endpoint=False)
            y_ref = np.linspace(0, 1, ny_ref, endpoint=False)
            x_ref += dx_ref / 2  # Make it cell-centered, this significantly reduces the errors
            y_ref += dy_ref / 2
            X_ref, Y_ref = np.meshgrid(x_ref, y_ref)

            # A-grid cmp file (file2)
            dx_cmp = 1.0 / nx_cmp
            dy_cmp = 1.0 / ny_cmp
            x_cmp = np.linspace(0, 1, nx_cmp, endpoint=False)
            y_cmp = np.linspace(0, 1, ny_cmp, endpoint=False)
            x_cmp += dx_cmp / 2
            y_cmp += dy_cmp / 2
            X_cmp, Y_cmp = np.meshgrid(x_cmp, y_cmp)

            # Create cubic interpolation of reference file
            interp_spline = RectBivariateSpline(x_ref, y_ref, data_ref)

            # Compute reduced reference resolution
            data_ref_low = interp_spline(x_cmp, y_cmp)

            data_ref = data_ref_low

        #elif 'spectral_ref_to_cmp' in params:
        elif 'spectral_ref_to_cmp' in params or 'spectral' in params:

            self.info("Using 'spectral_ref_to_cmp' method")

            # This is the code written by Pedro which uses spline interpolation

            # Comparison via interpolation
            # print("Interpolation")
            # A-grid REFERENCE (file1) - sweet outputs only A grids physical space

            data_ref = file_a.data
            data_cmp = file_b.data
            """
			#if True:
			if False:
				data_ref = np.zeros((8, 8))
				data_cmp = np.zeros((6, 6))
				for i in range(len(data_ref[0])):
					for j in range(len(data_ref)):
						data_ref[j,i] = 1.0

						a = 1.0
						a *= math.sin(2.0*i*math.pi*2.0/len(data_ref[0]))
						a *= math.cos(2.0*j*math.pi*2.0/len(data_ref))
						data_ref[j,i] += a

						a = 1.0
						a *= math.sin(i*math.pi*2.0/len(data_ref[0]))
						a *= math.cos(j*math.pi*2.0/len(data_ref))
						data_ref[j,i] += a

				for i in range(len(data_cmp[0])):
					for j in range(len(data_cmp)):
						data_cmp[j,i] = 1.0

						a = 1.0
						a *= math.sin(2.0*i*math.pi*2.0/len(data_cmp[0]))
						a *= math.cos(2.0*j*math.pi*2.0/len(data_cmp))
						data_cmp[j,i] += a

						a = 1.0
						a *= math.sin(i*math.pi*2.0/len(data_cmp[0]))
						a *= math.cos(j*math.pi*2.0/len(data_cmp))
						data_cmp[j,i] += a
			"""

            ny_ref = len(data_ref)
            nx_ref = len(data_ref[0])
            res_ref = nx_ref * ny_ref
            print("REF resolution: " + str(nx_ref) + ", " + str(ny_ref))

            ny_cmp = len(data_cmp)
            nx_cmp = len(data_cmp[0])
            res_cmp = nx_cmp * ny_cmp
            print("CMP resolution: " + str(nx_cmp) + ", " + str(ny_cmp))

            if nx_cmp & 1 or ny_cmp & 1:
                raise Exception("Only even resolutions allowed")

            #
            # Spectral rescaling
            #

            shift_ref_i = -1.0 / size_ref_i * 0.5
            shift_ref_j = -1.0 / size_ref_j * 0.5

            shift_cmp_j = 1.0 / size_cmp_j * 0.5
            shift_cmp_i = 1.0 / size_cmp_i * 0.5

            #if False:
            if True:
                #
                # RFFT
                #

                # Convert reference data to spectrum
                data_ref_spec = np.fft.rfft2(data_ref)

                # Dummy transformation to get matching spectral size
                data_ref_new_spec = np.fft.rfft2(
                    np.zeros(shape=data_cmp.shape))

                specx = data_ref_spec.shape[1]
                specy = data_ref_spec.shape[0]

                newspecx = data_ref_new_spec.shape[1]
                newspecy = data_ref_new_spec.shape[0]

                data_ref_new_spec[0:newspecy // 2,
                                  0:newspecx] = data_ref_spec[0:newspecy // 2,
                                                              0:newspecx]

                d = specy - newspecy // 2
                nd = newspecy - newspecy // 2
                data_ref_new_spec[nd:nd + newspecy // 2,
                                  0:newspecx] = data_ref_spec[d:d +
                                                              newspecy // 2,
                                                              0:newspecx]
                """
				print("*"*80)
				print(data_ref_spec)
				print("*"*80)
				print(data_ref_new_spec)
				print("*"*80)
				"""
                def shift(
                        spec_data,  # spectral data
                        sh_x,  # shift in x direction within domain [0;1]
                        sh_y,  # shift in y direction within domain [0;1]
                ):

                    # return data
                    ret_data = np.zeros(spec_data.shape, dtype=complex)

                    for iy in range(spec_data.shape[0]):
                        # compute mode
                        if iy < spec_data.shape[0] // 2:
                            ky = iy
                        else:
                            ky = iy - spec_data.shape[0]

                        for ix in range(spec_data.shape[1]):
                            # compute mode
                            kx = ix

                            ret_data[iy, ix] = spec_data[iy, ix]
                            #ret_data[iy,ix] *= np.exp(1j*2.0*math.pi*kx*sh_x)
                            #ret_data[iy,ix] *= np.exp(1j*2.0*math.pi*ky*sh_y)
                            ret_data[iy, ix] *= np.exp(1j * 2.0 * math.pi *
                                                       (kx * sh_x + ky * sh_y))

                    return ret_data

                # Shift high res reference data to 0,0
                data_ref_new_spec = shift(data_ref_new_spec,
                                          shift_ref_i + shift_cmp_i,
                                          shift_ref_j + shift_cmp_j)

                data_ref_new = np.fft.irfft2(data_ref_new_spec)
                data_ref_new *= res_cmp / res_ref

            else:
                #
                # FFT
                #

                # Convert reference data to spectrum
                data_ref_spec = np.fft.fft2(data_ref)

                # Dummy transformation to get matching spectral size
                data_ref_new_spec = np.fft.fft2(np.zeros(shape=data_cmp.shape))

                specx = data_ref_spec.shape[1]
                specy = data_ref_spec.shape[0]

                newspecx = data_ref_new_spec.shape[1]
                newspecy = data_ref_new_spec.shape[0]

                dy = specy - newspecy // 2
                ndy = newspecy - newspecy // 2

                dx = specx - newspecx // 2
                ndx = newspecx - newspecx // 2

                data_ref_new_spec[0:newspecy // 2, 0:newspecx //
                                  2] = data_ref_spec[0:newspecy // 2,
                                                     0:newspecx // 2]
                data_ref_new_spec[ndy:ndy + newspecy // 2, 0:newspecx //
                                  2] = data_ref_spec[dy:dy + newspecy // 2,
                                                     0:newspecx // 2]

                data_ref_new_spec[0:newspecy // 2, ndx:ndx +
                                  newspecx // 2] = data_ref_spec[0:newspecy //
                                                                 2, dx:dx +
                                                                 newspecx // 2]
                data_ref_new_spec[ndy:ndy + newspecy // 2, ndx:ndx +
                                  newspecx // 2] = data_ref_spec[dy:dy +
                                                                 newspecy // 2,
                                                                 dx:dx +
                                                                 newspecx // 2]

                if False:
                    print("*" * 80)
                    print(data_ref_spec)
                    print("*" * 80)
                    print(data_ref_new_spec)
                    print("*" * 80)

                def shift(
                        spec_data,  # spectral data
                        sh_x,  # shift in x direction within domain [0;1]
                        sh_y,  # shift in y direction within domain [0;1]
                ):

                    # return data
                    ret_data = np.zeros(spec_data.shape, dtype=complex)

                    for iy in range(spec_data.shape[0]):
                        # compute mode
                        if iy < spec_data.shape[0] // 2:
                            ky = iy
                        else:
                            ky = iy - spec_data.shape[0]

                        for ix in range(spec_data.shape[1]):
                            # compute mode
                            if ix < spec_data.shape[1] // 2:
                                kx = ix
                            else:
                                kx = ix - spec_data.shape[1]

                            ret_data[iy, ix] = spec_data[iy, ix]
                            ret_data[iy, ix] *= np.exp(1j * 2.0 * math.pi *
                                                       kx * sh_x)
                            ret_data[iy, ix] *= np.exp(1j * 2.0 * math.pi *
                                                       ky * sh_y)

                    return ret_data

                # Shift high res reference data to 0,0
                data_ref_new_spec = shift(data_ref_new_spec,
                                          shift_ref_i + shift_cmp_i,
                                          shift_ref_j + shift_cmp_j)

                data_ref_new = np.fft.ifft2(data_ref_new_spec)
                data_ref_new *= res_cmp / res_ref

                # Restrict to real data
                data_ref_new = np.real(data_ref_new)

            # The axes might be wrong.
            #
            # Swap axis=1 and axis=0 if there are some errors.
            #
            #f = signal.resample(data_ref, nx_cmp, t=None, axis=0)
            #data_ref_new = signal.resample(f, ny_cmp, t=None, axis=1)

            data_ref = data_ref_new

        else:
            print("")
            print("No supported method provided in '" + (','.join(params)) +
                  "'")
            print("")
            raise Exception("No supported method provided in '" +
                            (','.join(params)) + "'")

        #
        # Grids have same resolution
        #
        for j in range(0, data_cmp.shape[0]):
            for i in range(0, data_cmp.shape[1]):
                value = data_cmp[j, i] - data_ref[j, i]

                # http://mathworld.wolfram.com/L1-Norm.html
                self.norm_l1_value += abs(value)

                # http://mathworld.wolfram.com/L2-Norm.html
                self.norm_l2_value += value * value

                # http://mathworld.wolfram.com/L-Infinity-Norm.html
                self.norm_linf_value = max(abs(value), self.norm_linf_value)

                # http://mathworld.wolfram.com/Root-Mean-Square.html
                self.norm_rms_value += value * value

                self.N += 1

        # Compute sqrt() for Euklidian L2 norm
        self.norm_l2_value = math.sqrt(self.norm_l2_value)

        # RMS final sqrt(N) computation
        self.norm_rms_value = math.sqrt(self.norm_rms_value / float(self.N))

        # resolution normalized L1 value
        self.res_norm_l1_value = self.norm_l1_value / float(self.N)