Ejemplo n.º 1
0
    def __call__(self, domain, field):
        """
        :param object domain: A domain
        :param object field: Current field
        :return: Field after modification by Gaussian filter
        :rtype: Object
        """
        # Convert field to spectral domain:
        self.field = fft(field)

        delta_nu = domain.nu - domain.centre_nu - self.offset_nu
        factor = power(delta_nu / self.width_nu, (2 * self.m))
        # Frequency values are in order, inverse shift to put in fft order:
        self.shape = exp(-0.5 * ifftshift(factor))

        if domain.channels > 1:
            # Filter is applied only to one channel:
            self.field[self.channel] *= self.shape
        else:
            self.field *= self.shape

        # convert field back to temporal domain:
        if self.type is "reflected":
            return ifft(self.field)
        else:
            return field - ifft(self.field)
Ejemplo n.º 2
0
    def transfer_function(self, nu, centre_nu):
        """
        :param Dvector nu: Spectral domain array.
        :param double centre_nu: Centre frequency.
        :return: Array of values.
        :rtype: Dvector

        Generate an array representing the filter power transfer function.
        """
        if len(nu) < 8:
            raise OutOfRangeError(
                "Require spectral array with at least 8 values")

        delta_nu = nu - centre_nu - self.offset_nu
        factor = power(delta_nu / self.width_nu, (2 * self.m))
        self.shape = exp(-0.5 * factor)

        return abs(self.shape)**2
Ejemplo n.º 3
0
    def __init__(self,
                 name="filter",
                 width_nu=0.1,
                 offset_nu=0.0,
                 m=1,
                 channel=0,
                 using_fwhm=False,
                 type_filt="reflected"):

        if not (1e-6 < width_nu < 1e3):
            raise OutOfRangeError(
                "width_nu is out of range. Must be in (1e-6, 1e3)")

        if not (-200.0 < offset_nu < 200.0):
            raise OutOfRangeError(
                "offset_nu is out of range. Must be in (-200.0, 200.0)")

        if not (0 < m < 50):
            raise OutOfRangeError("m is out of range. Must be in (0, 50)")

        if not (0 <= channel < 2):
            raise OutOfRangeError("channel is out of range. Must be in [0, 2)")

        if int(m) != m:
            raise NotIntegerError("m must be an integer")

        if int(channel) != channel:
            raise NotIntegerError("channel must be an integer")

        self.name = name
        self.width_nu = width_nu
        self.offset_nu = offset_nu
        self.m = m
        self.channel = channel
        self.fwhm_nu = None
        self.type = type_filt

        # For a FWHM filter width, store then convert to a HWIeM filter width:
        if using_fwhm:
            self.fwhm_nu = width_nu  # store fwhm filter width
            self.width_nu *= 0.5 / power(log(2.0), 1.0 / (2 * m))

        self.shape = None
        self.field = None
Ejemplo n.º 4
0
    def generate(self, t):
        """
        :param Dvector t: Temporal domain array
        :return: Array of complex values. *Unit:* :math:`\sqrt{W}`
        :rtype: Cvector

        Generate an array of complex values representing a Gaussian pulse.
        """
        if len(t) < 8:
            raise OutOfRangeError(
                "Require temporal array with at least 8 values")

        # Assume t[0] = t_0 and t[-1] = t_0 + t_range - dt,
        # with dt = t[1] - t[0]
        t_range = t[-1] - t[0] + (t[1] - t[0])
        t_normalised = (t - self.position * t_range) / self.width
        time = power(t_normalised, (2 * self.m))

        phase = self.initial_phase
        phase -= 2.0 * pi * self.offset_nu * t + 0.5 * self.C * time

        return sqrt(self.peak_power) * exp(-0.5 * time + 1j * phase)
Ejemplo n.º 5
0
    def __call__(self, domain, field):
        """
        :param object domain: A domain
        :param object field: Current field
        :return: Field after modification by Gaussian
        :rtype: Object
        """
        self.field = field

        t_normalised = \
            (domain.t - self.position * domain.window_t) / self.width
        time = power(t_normalised, (2 * self.m))

        phase = self.initial_phase
        phase -= 2.0 * pi * self.offset_nu * domain.t + 0.5 * self.C * time

        magnitude = sqrt(self.peak_power) * exp(-0.5 * time)

        if domain.channels > 1:
            self.field[self.channel] += magnitude * exp(1j * phase)
        else:
            self.field += magnitude * exp(1j * phase)

        return self.field
Ejemplo n.º 6
0
def fib_closed(num):
    return (power(a, num) - power(b, num)) / (a - b)
Ejemplo n.º 7
0
 def calculate_fwhm(self):
     """ Convert a HWIeM width to a FWHM width. """
     if self.fwhm_nu is not None:
         return self.fwhm_nu
     else:
         return self.width_nu * 2.0 * power(log(2.0), 1.0 / (2 * self.m))
Ejemplo n.º 8
0
def bin_spinode(L,x=None,T=None):
    """
    Calculates a binary spinodal at either a fixed composition or temperature.
    If x is given, the corresponding T_spinodal is returned. If T is given, the
    two corresponding x_spinodal are returned.
    """
    from numpy.lib.scimath import power
    if x != None:
        T_sp = 2*x*(1-x)*(L[0]+3*L[1]*(1-2.*x))/BoltzConst
        return T_sp
    elif T != None:
        # Coefficients of cubic equation a*x**3+b*x**2+c*x+d
        a = 6.*L[1]
        b = -(L[0]+9.*L[1])
        c = L[0]+3.*L[1]
        d = -T*BoltzConst/2.
        discrim = 18.*a*b*c*d-4.*b**3*d+b**2*c**2-4*a*c**3-27.*a**2*d**2
        if discrim >= 0.:
            temp = 2.*b**3-9.*a*b*c+27.*a**2*d
            x1 = (power(0.5*(temp + power(-27.*a**2*discrim,1./2.)),1./3.)
                + power(0.5*(temp - power(-27.*a**2*discrim,1./2.)),1./3.)
                + b)/(-3.*a)
            x2 = (power(0.5*(temp + power(-27.*a**2*discrim,1./2.)),1./3.)
                    *(1.+np.sqrt(3)*j)
                + power(0.5*(temp - power(-27.*a**2*discrim,1./2.)),1./3.)
                    *(1.-np.sqrt(3)*j)
                - 2.*b)/(6.*a)
            x3 = (power(0.5*(temp + power(-27.*a**2*discrim,1./2.)),1./3.)
                    *(1.-np.sqrt(3)*j)
                + power(0.5*(temp - power(-27.*a**2*discrim,1./2.)),1./3.)
                    *(1.+np.sqrt(3)*j)
                - 2.*b)/(6.*a)
            x_sp = sorted([x1,x2,x3])
            return x_sp[0],x_sp[1]
        else:
            # There exists 1 real root and 2 complex roots
            print "There exists only 1 real root!"
            return
Ejemplo n.º 9
0
    def __init__(self,
                 name="gaussian",
                 position=0.0,
                 width=10.0,
                 peak_power=1e-3,
                 offset_nu=0.0,
                 m=1,
                 C=0.0,
                 initial_phase=0.0,
                 channel=0,
                 using_fwhm=False):

        if not (-0.5 <= position <= 0.5):
            raise OutOfRangeError(
                "position is out of range. Must be in [-0.5, 0.5]")

        if not (1e-3 < width < 1e3):
            raise OutOfRangeError(
                "width is out of range. Must be in (1e-3, 1e3)")

        if not (0.0 <= peak_power < 1e9):
            raise OutOfRangeError(
                "peak_power is out of range. Must be in [0.0, 1e9)")

        if not (-300.0 < offset_nu < 300.0):
            raise OutOfRangeError(
                "offset_nu is out of range. Must be in (-300.0, 300.0)")

        if not (0 < m < 50):
            raise OutOfRangeError("m is out of range. Must be in (0, 50)")

        if not (-1e3 < C < 1e3):
            raise OutOfRangeError("C is out of range. Must be in (-1e3, 1e3)")

        if not (0.0 <= initial_phase < 2.0 * pi):
            raise OutOfRangeError(
                "initial_phase is out of range. Must be in [0.0, 2.0 * pi)")

        if not (0 <= channel < 2):
            raise OutOfRangeError("channel is out of range. Must be in [0, 2)")

        if int(m) != m:
            raise NotIntegerError("m must be an integer")

        if int(channel) != channel:
            raise NotIntegerError("channel must be an integer")

        self.name = name
        self.position = position
        self.width = width  # ps
        self.peak_power = peak_power  # W
        self.offset_nu = offset_nu  # THz
        self.m = m
        self.C = C  # rad
        self.initial_phase = initial_phase  # rad
        self.channel = channel
        self.fwhm = None

        # For a FWHM pulse width, store then convert to a HWIeM pulse width:
        if using_fwhm:
            self.fwhm = width  # store fwhm pulse width
            self.width *= 0.5 / power(log(2.0), 1.0 / (2 * m))

        self.field = None
Ejemplo n.º 10
0
def getDist(point1, point2):
    sumVal = 0
    for i in xrange(len(point1)):
        sumVal += power(point1[i]+point2[i],2)
    return sqrt(sumVal)
Ejemplo n.º 11
0
    def calc_roots_of_low_order_polynomial(C):
        """
        Calculates the (complex) roots of polynomials up to order 3 in parallel.
        The coefficients of the polynomials are in the first dimension of C and repeated in the following dimensions,
        one for each polynomial to determine the roots of. The coefficients are
        input for low to high order in each column. In other words, the polynomial is:
        ``np.sum(C * (x**range(C.size))) == 0``

        :param C: The coefficients of the polynomial, per polynomial.
        :return: The zeros in the complex plane, per polynomial.
        """
        nb_terms = C.shape[0]
        output_shape = np.array(C.shape)
        output_shape[0] -= 1

        # A few helper functions
        def sign(arr):  # signum without the zero
            return 2 * (arr >= 0) - 1

        def is_significant(arr):
            return np.abs(arr) > np.sqrt(np.finfo(arr.dtype).eps)

        def add_roots(coeffs):
            """
            Checks if this is a lower-order polynomial in disguise and adds zero roots to match the order of the array

            :param coeffs: The polynomial coefficient array
            :return: A, nb_roots_added The non-degenerate polynomial coefficient array, A, and the number of roots added
            """
            # Although the coefficients are integers, the calculations may be real and complex.
            coeffs = np.array(coeffs, dtype=np.complex128)
            coeffs = coeffs[..., np.newaxis]  # add a singleton dimension to avoid problems with vectors
            roots_added = np.zeros(coeffs[0].shape, dtype=np.uint8)
            for outer_dim_idx in range(coeffs.shape[0]):
                lower_order = np.where(coeffs[-1] == 0)
                for dim_idx in np.arange(coeffs.shape[0]-1, 0, -1):
                    coeffs[dim_idx][lower_order] = coeffs[dim_idx-1][lower_order]
                coeffs[0][lower_order] = 0
                roots_added[lower_order] += 1
            coeffs[-1][lower_order] = 1  # all zeros

            return coeffs[..., 0], roots_added[..., 0]

        def remove_roots(roots, roots_added):
            """
            Removes dummy roots at ``x == 0`` and replaces them with nan at the end of the vector of roots.
            The roots are sorted with np.sort (real first, imaginary second).

            :param roots: The array of all calculated roots.
            :param roots_added: The number of dummy roots added to the problem.
            :return: The array with the dummy roots placed at the end and replaced by nan.
            """
            roots = roots[..., np.newaxis]  # add a singleton dimension to avoid problems with vectors
            roots_added = roots_added[..., np.newaxis]  # add a singleton dimension to avoid problems with vectors
            for dim_idx in np.arange(roots.shape[0]-1, -1, -1):
                is_zero = np.bitwise_not(is_significant(roots[dim_idx]))
                remove_zero = np.where(is_zero & (roots_added > 0))
                roots[dim_idx][remove_zero] = np.nan
                roots_added[remove_zero] -= 1
            roots = np.sort(roots, axis=0)
            return roots[..., 0]

        if nb_terms < 2:
            X = np.empty((0, *C[1:]), dtype=C.dtype)
        elif nb_terms == 2:  # linear
            # C[0] + C[1]*X == 0
            C, nb_roots_added = add_roots(C)
            X = -C[np.newaxis, 0] / C[np.newaxis, 1]
            X = remove_roots(X, nb_roots_added)
        elif nb_terms == 3:  # quadratic
            # C[0] + C[1]*X + C[2]*X**2 == 0
            C, nb_roots_added = add_roots(C)
            d = C[1] ** 2 - 4.0 * C[2] * C[0]
            sqrt_d = sm.sqrt(d)
            q = -0.5 * (C[1] + sign((np.conj(C[1]) * sqrt_d).real) * sqrt_d)
            X = np.array((q / C[2], C[0] / (q + (1 - is_significant(C[0])) * (1 - is_significant(q)))))
            X = remove_roots(X, nb_roots_added)
        elif nb_terms == 4:  # cubic
            C, nb_roots_added = add_roots(C)

            a = C[2] / C[3] / 3
            b = C[1] / C[3]
            c = C[0] / C[3]

            Q = a ** 2 - b / 3
            R = a ** 3 + (- a * b + c) / 2
            del b, c

            S2 = R ** 2 - Q ** 3
            complex_root = True  #TODO: fix numerical issues with real roots.  is_significant(R.imag) | is_significant(Q.imag) | (S2 >= 0)
            not_around_origin = is_significant(Q)  # avoiding division by zero in case the roots are centered around zero
            RQm32 = sm.power(R, 1/3) / (not_around_origin * sm.sqrt(Q) + (1 - not_around_origin))
            AB_all_real_roots = -sm.sqrt(Q) * (RQm32 + 1j * sm.sqrt(1.0 - RQm32**2))
            S = sm.sqrt(S2)  # S**2 = R**2 - Q**3 => Q**3 == R**2 - S**2 = (R-S)*(R+S)
            A_complex_root = -sm.power(R + sign(np.real(np.conj(R) * S)) * S, 1/3)
            # Combine the different calculations for A
            A = complex_root * A_complex_root + (1 - complex_root) * AB_all_real_roots
            # choose sign of sqrt so that real(conj(R) * sqrt(R**2 - Q**3)) >= 0
            A_significant = is_significant(A)
            # if A insignificant, then R + np.sign(np.real(np.conj(R) * S)) * S == 0
            #  and can be divided out of Q^3 = R^2 - S^2 = (R-S)*(R+S)
            B_complex_roots = Q / (A + (1 - A_significant))  # avoiding division by zero
            B_complex_roots_origin = - sm.power(R - np.sign(np.real(np.conj(R) * S)) * S, 1/3)

            # Combine the different calculations for B
            B = complex_root * (A_significant * B_complex_roots + (1 - A_significant) * B_complex_roots_origin) \
                + (1 - complex_root) * (-AB_all_real_roots)
            complex_triangle = utils.to_dim(np.exp(2j * const.pi * np.array([-1, 0, 1]) / 3), output_shape.size, 0)
            X = A[np.newaxis, ...] * complex_triangle + B[np.newaxis, ...] * np.conj(complex_triangle)
            X -= a[np.newaxis, ...]

            X = remove_roots(X, nb_roots_added)
        else:
            message = 'Orders above 3 not implemented!'
            log.critical(message)
            raise Exception(message)

        return X
Ejemplo n.º 12
0
def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2)))