Пример #1
0
 def on_neighbor (self, match, direction, edge, name, loc) :
     if name == "*" :
         return sympy.Indexed(st.newstar(), direction == "?",
                              edge or sympy.S.true, loc or sympy.S.true)
     else :
         return sympy.Indexed(name,  direction == "?",
                              edge or sympy.S.true, loc or sympy.S.true)
Пример #2
0
    def load_g(self):

        # load all g or recompute or compute new.
        if self.recompute_g or not (lib.files_exist(
                self.g_fnames)):  # generate
            self.g_list, self.gx_list, self.gy_list = ([] for i in range(3))

            print('* Computing...', end=' ')

            for i in range(self.trunc_g + 1):
                print('g_' + str(i), end=', ')
                self.generate_g(i)
            print()

            # save
            for i in range(self.trunc_g + 1):
                np.savetxt(self.g_fnames[i], self.g_list[i])

        else:  # load

            self.g_list, self.gx_list, self.gy_list = self.load_sols(
                self.g_fnames, name='g')

        rulex = {
            sym.Indexed('gx', i): self.gx_list[i](self.t)
            for i in range(len(self.g_fnames))
        }
        ruley = {
            sym.Indexed('gy', i): self.gy_list[i](self.t)
            for i in range(len(self.g_fnames))
        }
        self.rule_g = {**rulex, **ruley}
Пример #3
0
 def on_variable (self, match, name, location=None, forall=None) :
     if forall is not None :
         return sympy.Indexed(st._FORALOC, name, *forall)
     elif not location :
         return sympy.Indexed(st._THISLOC, name)
     elif isinstance(location, list) :
         return sympy.Indexed(st._NEXTLOC, name, *location)
     else :
         return sympy.Indexed(location, name)
Пример #4
0
    def generate_z(self, k, total_iter=5):

        # load kth expansion of g for k >= 1
        rulex = {
            sym.Indexed('zx', i): self.zx_list[i](self.t)
            for i in range(k)
        }
        ruley = {
            sym.Indexed('zy', i): self.zy_list[i](self.t)
            for i in range(k)
        }
        rule = {**rulex, **ruley, **self.rule_g}

        zhx = self.hetx_list[k].subs(rule)
        zhy = self.hety_list[k].subs(rule)

        hetx_lam = lambdify(self.t, zhx)
        hety_lam = lambdify(self.t, zhy)

        if k == 0:
            init = copy.deepcopy(self.z0_init)
            total_iter = 1
        else:
            init = [0, 0]

            # Newton
            for mm in range(total_iter):
                init += lib.get_newton_jac(self.dz, self.tLC, init, hetx_lam,
                                           hety_lam, k)

        zu = odeint(self.dz,
                    init,
                    self.tLC,
                    args=(hetx_lam, hety_lam, k),
                    tfirst=True)

        if k == 0:
            # normalize
            dLC = lib.rhs([np.cos(0), np.sin(0)], 0, self.f)
            print('dLC', dLC, 'zu[0,:]', zu[0, :], 'z0 init', self.z0_init,
                  'np.dot(dLC,zu[0,:])', np.dot(dLC, zu[0, :]))

            zu = self.omega * zu / (np.dot(dLC, zu[0, :]))

        fnx = interp1d(self.tLC, zu[:, 0])
        fny = interp1d(self.tLC, zu[:, 1])
        self.zx_list.append(
            implemented_function('zx_' + str(k), self.myFun(fnx)))
        self.zy_list.append(
            implemented_function('zy_' + str(k), self.myFun(fny)))

        self.zx_callable.append(lambdify(self.t, self.zx_list[k](self.t)))
        self.zy_callable.append(lambdify(self.t, self.zy_list[k](self.t)))

        return zu
Пример #5
0
def calc_R2(model, x_points, y_points):
    display(model)
    # model.replace("x", "sym.Indexed(x, k)")
    model = model.subs(x, sym.Indexed(x, k))
    display(1/len(x_points))
    R2_model = sym.sqrt(1/len(x_points)*sym.Sum(((model) - sym.Indexed(y, k))**2,(k,0,len(x_points) -1)))
    display(R2_model)
    f_R2 = sym.lambdify((x, y), R2_model)
    R2 = f_R2(x_points, y_points)
    display(R2)    
    pass
Пример #6
0
def expansion_slow(maxorder=4):
    """ This is the naive (and very slow) implementation of the
        ("hard mode" part of the) expansion.

        This function is intended to be a debugging tool.
        Do not use this in production code.

        Parameters
        ----------
        maxorder : int
            Highest order of \alpha taken into account in the expansion.

        See also
        --------
        - expansion
    """
    res = 0
    f = sp.IndexedBase('f')

    kres = 0
    for k in range(maxorder):
        kres += dalpha(k)/sp.factorial(k)*((-sp.log(N))**k)

    for i in xrange(maxorder):
        res += sp.Indexed(f, i)*(kres**(i+1))

    return res
Пример #7
0
 def __new__(cls, base, index):
     if isinstance(base, (str, sympy.IndexedBase, sympy.Symbol)):
         return sympy.Indexed(base, index)
     elif not isinstance(base, sympy.Basic):
         raise ValueError("`base` must be of type sympy.Basic")
     obj = sympy.Expr.__new__(cls, base)
     obj._base = base
     obj._index = as_tuple(index)
     return obj
Пример #8
0
def return_indexed(base, indeces, **kw_args):
    if is_sequence(indeces):
        # Special case needed because M[*my_tuple] is a syntax error.
        if base.shape and len(base.shape) != len(indeces):
            raise Exception("Rank mismatch.")
        return op.IndexedArray(base, *indeces, **kw_args)
    else:
        if base.shape and len(base.shape) != 1:
            raise sp.Indexed("Rank mismatch.")
        return op.IndexedArray(base, indeces, **kw_args)
Пример #9
0
 def split(self):
     queries = GetLocQueries(*self.condition, *self.assignment).found
     replace = []
     matches = []
     for q in queries:
         svar, lvar, m = self._qmatch(q)
         replace.append(sympy.Indexed(svar, lvar))
         matches.append(m)
     concrete = self.subs(dict(zip(queries, replace)))
     for prod in product(*matches):
         yield concrete.subs(
             dict(chain.from_iterable(p.items() for p in prod)))
Пример #10
0
    def check(n):
        """
           A simple consistency check for the expansion
        """

        coeff_c_subs_dict = {sp.Indexed(c, i):0 for i in range(n+1)}
        dd = debug_exp(n).subs({b1:0}).subs(coeff_c_subs_dict).removeO()


        for i in range(0, n):
            j = i+1
            #print ese(j)
            #print dd.coeff(y, j)
            print "\torder {:2d} -> {:s}".format(j,
                                                 str(ese(j) == dd.coeff(y, j)))
Пример #11
0
    def __new__(cls, base, index):
        if isinstance(base, (str, sympy.IndexedBase, sympy.Symbol)):
            return sympy.Indexed(base, index)
        try:
            # If an AbstractFunction, pull the underlying Symbol
            base = base.indexed.label
        except AttributeError:
            if not isinstance(base, sympy.Basic):
                raise ValueError("`base` must be of type sympy.Basic")

        index = tuple(sympify(i) for i in as_tuple(index))

        obj = sympy.Expr.__new__(cls, base, *index)
        obj._base = base
        obj._index = index

        return obj
Пример #12
0
 def _expand(self, expr):
     queries = GetLocQueries(expr, match=_FORALOC).found
     if not queries:
         return [expr]
     matches = []
     replace = []
     for q in queries:
         s, l, m = self._qmatch(q)
         if not all(Star.star(k) for d in m for k in d):
             raise CompileError(
                 "Matching node name is forbidden within %r" % txt(q))
         matches.append(m)
         replace.append(sympy.Indexed(s, l))
     concrete = expr.subs(dict(zip(queries, replace)))
     expanded = []
     for match in product(*matches):
         d = dict(chain.from_iterable(m.items() for m in match))
         expanded.append(concrete.subs(d))
     return expanded
Пример #13
0
    def _print_Assignment(self, expr):
        if isinstance(expr.lhs, sp.Array):
            lhs = expr.lhs
            rhs = expr.rhs

            if isinstance(expr.rhs, sp.Piecewise):
                # Here we modify Piecewise so each expression is now
                # an Assignment, and then continue on the print.
                expressions = []
                conditions = []
                for (e, c) in rhs.args:
                    expressions.append(Assignment(lhs, e))
                    conditions.append(c)
                temp = sp.Piecewise(*zip(expressions, conditions))
                return self._print(temp)

            lhs_code = self._print(sp.flatten(lhs.tolist()))
            # TODO: I think this is where I could make it so that the assignment gets pretty robust to multidimensional inputs
            # when I re-wrote the static trimmability function, I just had to apply .T instead of .ravel, that may be sufficient generally
            # since I already flatten the sympy expression that is being generated.... not sure though.
            rhs_code = self._print(rhs) + '.ravel()'
            return self._get_statement("%s = %s" % (lhs_code, rhs_code))

            # I would prefer to have something like this, but isn't clear how
            temp = sp.Dummy()
            lines = [self._print(Assignment(temp, rhs))]
            temp = sp.Indexed(temp.name, lhs.shape)
            for idx, el in enumerate(lhs):
                lines.append('{}[{}]'.format(self._print(temp), 0))
        else:
            if expr.rhs.func == sp.Piecewise:
                # The sympy/printing/codeprinter.py CodePrinter._print_Assignment explicitly
                # folds the assignments into each case, which is never over-written for the NumPyPrinter
                lhs_code = self._print(expr.lhs)
                rhs_code = self._print(expr.rhs)
                return self._get_statement("%s = %s" % (lhs_code, rhs_code))
            return super()._print_Assignment(expr)
Пример #14
0
 def ese(n):
     """ Even More Debug Stuff """
     n = n-1
     rese = sp.Sum((b0*sp.log(N))**y*sp.Indexed('f', n-y)*sp.binomial(n, y),
                   (y, 0, n)).doit()
     return rese
Пример #15
0
    def generate_i(self, k, total_iter=5):

        # load kth expansion of g for k >= 1
        rulex = {
            sym.Indexed('zx', i): self.ix_list[i](self.t)
            for i in range(k)
        }
        ruley = {
            sym.Indexed('zy', i): self.iy_list[i](self.t)
            for i in range(k)
        }
        rule = {**rulex, **ruley, **self.rule_g}

        ihx = self.hetx_list[k].subs(rule)
        ihy = self.hety_list[k].subs(rule)

        hetx_lam = lambdify(self.t, ihx)
        hety_lam = lambdify(self.t, ihy)

        if k == 0:
            init = copy.deepcopy(self.i0_init)
            total_iter = 0
        else:
            init = [0, 0]

            # Newton
            for mm in range(total_iter):

                if False and k == 1:
                    fig = plt.figure()
                    ax = fig.add_subplot(111)

                    iu = odeint(self.di,
                                init,
                                self.tLC,
                                args=(hetx_lam, hety_lam, k),
                                tfirst=True)

                    ax.plot(iu[:, 0])
                    ax.plot(iu[:, 1])

                    ax.set_title('mm=' + str(mm) + ', k=' + str(k))

                    plt.show(block=True)

                init += lib.get_newton_jac(self.di, self.tLC, init, hetx_lam,
                                           hety_lam, k)

        iu = odeint(self.di,
                    init,
                    self.tLC,
                    args=(hetx_lam, hety_lam, k),
                    tfirst=True)

        if k == 1:  # normalize

            gx = lambdify(self.t, self.gx_list[1](self.t))
            gy = lambdify(self.t, self.gy_list[1](self.t))

            zx = lambdify(self.t, self.zx_list[0](self.t))
            zy = lambdify(self.t, self.zy_list[0](self.t))

            ix = lambdify(self.t, self.ix_list[0](self.t))
            iy = lambdify(self.t, self.iy_list[0](self.t))

            F = lib.rhs([np.cos(0), np.sin(0)], 0, self.f)
            g1 = np.array([gx(0), gy(0)])
            z0 = np.array([zx(0), zy(0)])
            i0 = np.array([ix(0), iy(0)])

            J = self.jacLC(0)
            i1 = iu[0, :]

            ijg = np.dot(i0, np.dot(J, g1))
            be = (self.kappa - ijg - np.dot(i1, F)) / (np.dot(z0, F))

            init = iu[0, :] + be * z0
            iu = odeint(self.di,
                        init,
                        self.tLC,
                        args=(hetx_lam, hety_lam, k),
                        tfirst=True)

        fnx = interp1d(self.tLC, iu[:, 0])
        fny = interp1d(self.tLC, iu[:, 1])
        self.ix_list.append(
            implemented_function('ix_' + str(k), self.myFun(fnx)))
        self.iy_list.append(
            implemented_function('iy_' + str(k), self.myFun(fny)))

        self.ix_callable.append(lambdify(self.t, self.ix_list[k](self.t)))
        self.iy_callable.append(lambdify(self.t, self.iy_list[k](self.t)))

        return iu
Пример #16
0
    def generate_het(self):
        """
        Generate heterogeneous terms for integrating the Z_i and I_i terms.

        Returns
        -------
        None.

        """

        self.hetx_list, self.hety_list = ([] for i in range(2))
        # get the general expression for h in z before plugging in g,z.

        # column vectors ax ay for use in matrix A = [ax ay]
        self.ax = Matrix([[0], [0]])
        self.ay = Matrix([[0], [0]])

        for j in range(1, self.trunc_gh + 1):
            p1 = lib.kProd(j, self.dx)
            p2 = kp(p1, sym.eye(2))

            d1 = lib.vec(lib.df(self.NIC1, self.x, j + 1))
            d2 = lib.vec(lib.df(self.NIC2, self.x, j + 1))

            self.ax += (1 / math.factorial(j)) * p2 * d1
            self.ay += (1 / math.factorial(j)) * p2 * d2

        self.A = sym.zeros(2, 2)

        self.A[:, 0] = self.ax
        self.A[:, 1] = self.ay

        self.z_expansion = Matrix([[self.zx], [self.zy]])
        het = self.A * self.z_expansion

        # expand all terms
        self.hetx = sym.expand(het[0].subs([(self.dx1, self.gx),
                                            (self.dx2, self.gy)]))
        self.hety = sym.expand(het[1].subs([(self.dx1, self.gx),
                                            (self.dx2, self.gy)]))

        # collect all psi terms into factors of pis^k
        self.hetx_powers = sym.collect(self.hetx, self.psi, evaluate=False)
        self.hety_powers = sym.collect(self.hety, self.psi, evaluate=False)

        self.hetx_list = []
        self.hety_list = []

        counter = 0
        while (counter <= self.trunc_g + 1):

            # save current term
            self.hetx_list.append(self.hetx_powers[self.psi**counter])
            self.hety_list.append(self.hety_powers[self.psi**counter])

            counter += 1

        # substitute limit cycle
        for i in range(len(self.ghx_list)):
            self.hetx_list[i] = self.hetx_list[i].subs({
                self.x1:
                sym.cos(2 * sym.pi * self.t),
                self.x2:
                sym.sin(2 * sym.pi * self.t),
                sym.Indexed('gx', 0):
                s(0),
                sym.Indexed('gy', 0):
                s(0)
            })
            self.hety_list[i] = self.hety_list[i].subs({
                self.x1:
                sym.cos(2 * sym.pi * self.t),
                self.x2:
                sym.sin(2 * sym.pi * self.t),
                sym.Indexed('gx', 0):
                s(0),
                sym.Indexed('gy', 0):
                s(0)
            })
Пример #17
0
    def __init__(
        self,
        SIG=0.08,
        RHO=0.12,
        P=2 * np.pi,
        trunc_g=6,
        trunc_gh=3,
        TN=2000,
        dir='dat',
        recompute_monodromy=True,
        recompute_gh=False,
        recompute_g=False,
        recompute_het=False,
        recompute_z=False,
        recompute_i=False,
    ):
        """
        recompute_gh : recompute het. terms for Floquet e.funs g
        
        
        """

        # Model parameters
        self.SIG = SIG
        self.RHO = RHO
        self.P = P

        # Simulation/method parameters
        self.trunc_g = trunc_g  # max power term in psi of Floquet e.fun g
        self.trunc_gh = trunc_gh  # max in summation for heterogeneous term

        self.recompute_monodromy = recompute_monodromy
        self.recompute_gh = recompute_gh
        self.recompute_g = recompute_g

        self.recompute_het = recompute_het
        self.recompute_z = recompute_z
        self.recompute_i = recompute_i

        # find limit cycle or load
        self.T = 1
        self.omega = 2 * np.pi
        self.TN = TN
        # find limit cycle -- easy for this problem but think of general methods
        # see Dan's code for general method
        self.tLC = np.linspace(0, self.T, self.TN)
        #LC_arr = odeint(rhs,[1,0],tLC,args=(f,))

        # make interpolated version of LC
        #LC_interp_x = interp1d(tLC,LC_arr[:,0])
        #LC_interp_y = interp1d(tLC,LC_arr[:,1])

        # filenames and directories
        self.dir = 'dat/'

        if (not os.path.exists(self.dir)):
            os.makedirs(self.dir)

        self.model_params = '_sig=' + str(self.SIG) \
                            + '_rho=' + str(self.RHO) \
                            + '_P=' + str(self.P)
        self.sim_params = '_TN=' + str(self.TN)

        self.monodromy_fname = self.dir + 'monodromy_' + self.model_params + self.sim_params + '.txt'

        self.ghx_fnames = [
            self.dir + 'ghx_' + str(i) + self.model_params + self.sim_params +
            '.d' for i in range(self.trunc_g + 1)
        ]
        self.ghy_fnames = [
            self.dir + 'ghy_' + str(i) + self.model_params + self.sim_params +
            '.d' for i in range(self.trunc_g + 1)
        ]
        self.g_fnames = [
            self.dir + 'g_' + str(i) + self.model_params + self.sim_params +
            '.txt' for i in range(self.trunc_g + 1)
        ]

        self.hetx_fnames = [
            self.dir + 'hetx_' + str(i) + self.model_params + self.sim_params +
            '.d' for i in range(self.trunc_g + 1)
        ]
        self.hety_fnames = [
            self.dir + 'hety_' + str(i) + self.model_params + self.sim_params +
            '.d' for i in range(self.trunc_g + 1)
        ]
        self.A_fname = self.dir + 'A_' + self.model_params + self.sim_params + '.d'

        self.z_fnames = [
            self.dir + 'z_' + str(i) + self.model_params + self.sim_params +
            '.txt' for i in range(self.trunc_g + 1)
        ]
        self.i_fnames = [
            self.dir + 'i_' + str(i) + self.model_params + self.sim_params +
            '.txt' for i in range(self.trunc_g + 1)
        ]

        # Symbolic variables and functions
        self.eye = np.identity(2)

        self.psi = sym.symbols('psi')
        self.x1, self.x2, self.x3, self.t = symbols('x1 x2,x3, t')
        self.dx1, self.dx2, self.dx3 = symbols('dx1 dx2 dx3')

        self.dx = Matrix([[self.dx1, self.dx2]])
        self.x = Matrix([[self.x1, self.x2]])

        R2 = self.x1**2 + self.x2**2
        self.NIC1 = self.P * (self.SIG * self.x1 * (1 - R2) - self.x2 *
                              (1 + self.RHO * (R2 - 1)))
        self.NIC2 = self.P * (self.SIG * self.x2 * (1 - R2) + self.x1 *
                              (1 + self.RHO * (R2 - 1)))
        #self.rhs_sym = Matrix([self.NIC1,self.NIC2])

        # symbol J on LC.
        self.jacLC_symbolic = Matrix(
            [[diff(self.NIC1, self.x1),
              diff(self.NIC1, self.x2)],
             [diff(self.NIC2, self.x1),
              diff(self.NIC2,
                   self.x2)]]).subs([(self.x1, sym.cos(2 * pi * self.t)),
                                     (self.x2, sym.sin(2 * pi * self.t))])

        # make RHS and Jacobian callable functions
        self.f = lambdify((self.x1, self.x2), [self.NIC1, self.NIC2])

        #jac = sym.lambdify((x1,x2),Jac)
        self.jacLC = lambdify((self.t), self.jacLC_symbolic)

        # assume gx is the first coordinate of Floquet eigenfunction g
        # brackets denote Taylor expansion functions
        # now substitute Taylor expansion dx = gx[0] + gx[1] + gx[2] + ...
        i_sym = sym.symbols('i_sym')  # summation index
        self.gx = sym.Sum(self.psi**i_sym * sym.Indexed('gx', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()
        self.gy = sym.Sum(self.psi**i_sym * sym.Indexed('gy', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()

        self.zx = sym.Sum(self.psi**i_sym * sym.Indexed('zx', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()
        self.zy = sym.Sum(self.psi**i_sym * sym.Indexed('zy', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()

        self.ix = sym.Sum(self.psi**i_sym * sym.Indexed('ix', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()
        self.iy = sym.Sum(self.psi**i_sym * sym.Indexed('iy', i_sym),
                          (i_sym, 0, self.trunc_g)).doit()

        # Run method
        self.load_monodromy()  # get monodromy matrix
        self.load_gh()  # get heterogeneous terms for g
        self.load_g()  # get g

        #t0 = time.time()
        self.load_het()
        self.load_z()
        self.load_i()
Пример #18
0
    def generate_g(self, k, total_iter=4):
        # load kth expansion of g for k >= 0

        if k == 0:
            # g0 is 0

            self.g_list.append(np.zeros((self.TN, 2)))
            self.gx_list.append(implemented_function('gx_0', lambda t: 0))
            self.gy_list.append(implemented_function('gy_0', lambda t: 0))

            return

        rulex = {
            sym.Indexed('gx', i): self.gx_list[i](self.t)
            for i in range(k)
        }
        ruley = {
            sym.Indexed('gy', i): self.gy_list[i](self.t)
            for i in range(k)
        }
        rule = {**rulex, **ruley}

        # apply replacement
        self.ghx_list[k] = self.ghx_list[k].subs(rule)
        self.ghy_list[k] = self.ghy_list[k].subs(rule)

        # lambdify heterogeneous terms for use in integration
        hetx_lam = lambdify(self.t, self.ghx_list[k])
        hety_lam = lambdify(self.t, self.ghy_list[k])

        self.method = 'RK45'
        self.rtol = 1e-4
        self.atol = 1e-8

        # find intial condtion
        if k == 1:
            #init = [0,0]
            init = copy.deepcopy(self.g1_init)
            total_iter = 1
        else:
            init = [0, 0]
            # Newton
            for mm in range(total_iter):
                out = lib.get_newton_jac(self, self.dg, -self.tLC, init,
                                         hetx_lam, hety_lam, k)
                print(out)
                init += out

        # get full solution
        gu = odeint(self.dg,
                    init,
                    -self.tLC,
                    args=(hetx_lam, hety_lam, k),
                    tfirst=True)

        gu = gu[::-1, :]
        # save soluton as lambda functions
        self.g_list.append(gu)

        fnx = interp1d(self.tLC, gu[:, 0], fill_value='extrapolate')
        fny = interp1d(self.tLC, gu[:, 1], fill_value='extrapolate')

        self.gx_list.append(
            implemented_function('gx_' + str(k), self.myFun(fnx)))
        self.gy_list.append(
            implemented_function('gy_' + str(k), self.myFun(fny)))

        if True and k == 1:

            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(self.tLC, gu)
            ax.set_title('g1')
            plt.show(block=True)

        if True and k == 2:
            t = np.linspace(0, 1, 100)
            #fig = plt.figure()
            #ax = fig.add_subplot(111)
            #ax.plot(t,hetx_lam(t))
            #ax.set_title('hetx_lam')
            #plt.show(block=True)

            fn = lambdify(self.t, self.gx_list[1](self.t))

            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(t, fn(t))
            y = self.g_list[1][:, 0]
            ax.plot(np.linspace(0, 1, len(y)), y)
            ax.set_title('gx_list[1]')
            plt.show(block=True)
Пример #19
0
kpc = 1e3  # in units of pc
autocm = 1.4960e13  #1 AU in cm
pi = np.pi

# Define starting coordinates on source plane (x,y) in dimensionless coordinates (u_x, u_y)
# where u_x = (x / a_x) and a_x is the characteristic length scale (same goes for u_y).
# This is done using Sympy
u_x, u_y = sym.symbols('u_x u_y')
A, B = 1.5e-2, 5

#Use Sympy to find derivatives of the potential
N, j, theta, phi, sigma = sym.symbols('N j theta phi sigma')  #name variables

# Define various lens geometries

gaussrand = sigma * sym.sqrt(2/N) * sym.Sum(sym.cos(u_y*sym.cos(sym.Indexed(theta, j)) + \
                            u_x*sym.sin(sym.Indexed(theta, j)) + sym.Indexed(phi, j)), (j, 1, N))
#gaussrand = 2 * sym.sqrt(2) * sym.cos(u_y*sym.cos(0.25*np.pi) + u_x*sym.sin(0.25*np.pi) + 2*np.pi)
gauss = sym.exp(-u_x**2 - u_y**2)  #gaussian
ring = 2.7182 * (u_x**2 + u_y**2) * gauss  #ring
rectgauss = sym.exp(-u_x**4 - u_y**4)
stgauss = gauss * (1. - A *
                   (sym.sin(B * (u_x)) + sym.sin(B * (u_y - 2 * pi * 0.3)))
                   )  #rectangular gaussian
asymgauss = sym.exp(-u_x**2 - u_y**4)  #asymmetrical gaussian
supergauss2 = sym.exp(-(u_x**2 + u_y**2)**2)  #gaussian squared
supergauss3 = sym.exp(-(u_x**2 + u_y**2)**3)  #gaussian cubed
superlorentz = 1. / (
    (u_x**2 + u_y**2)**2 + 1.)  #lorentzian with width (gamma) of 2

# Define preferred lens geometry (use gauss as test case)
Пример #20
0
    def generate_gh(self):
        """
        generate heterogeneous terms for the Floquet eigenfunctions g.

        Returns
        -------
        list of symbolic heterogeneous terms in self.ghx_list, self.ghy_list.

        """

        self.ghx_list = []
        self.ghy_list = []

        # get the general expression for h before plugging in g.
        self.hx = 0
        self.hy = 0

        for i in range(2, self.trunc_gh + 1):
            # all x1,x2 are evaluated on limit cycle x=cos(t), y=sin(t)
            p = lib.kProd(i, self.dx)
            d1 = lib.vec(lib.df(self.NIC1, self.x, i))
            d2 = lib.vec(lib.df(self.NIC2, self.x, i))

            self.hx += (1 / math.factorial(i)) * np.dot(p, d1)
            self.hy += (1 / math.factorial(i)) * np.dot(p, d2)

        self.hx = sym.Matrix(self.hx)
        self.hy = sym.Matrix(self.hy)

        # expand all terms
        self.hx = sym.expand(
            self.hx.subs([(self.dx1, self.gx), (self.dx2, self.gy)]))
        self.hy = sym.expand(
            self.hy.subs([(self.dx1, self.gx), (self.dx2, self.gy)]))

        # collect all psi terms into list of some kind
        self.tempx = sym.collect(self.hx[0], self.psi, evaluate=False)
        self.tempy = sym.collect(self.hy[0], self.psi, evaluate=False)

        counter = 0
        while (counter <= self.trunc_g + 1):
            # save current term
            self.ghx_list.append(self.tempx[self.psi**counter])
            self.ghy_list.append(self.tempy[self.psi**counter])

            counter += 1

        # substitute limit cycle. maybe move elsewhere.
        for i in range(len(self.ghx_list)):
            self.ghx_list[i] = self.ghx_list[i].subs({
                self.x1:
                sym.cos(2 * sym.pi * self.t),
                self.x2:
                sym.sin(2 * sym.pi * self.t),
                sym.Indexed('gx', 0):
                s(0),
                sym.Indexed('gy', 0):
                s(0)
            })
            self.ghy_list[i] = self.ghy_list[i].subs({
                self.x1:
                sym.cos(2 * sym.pi * self.t),
                self.x2:
                sym.sin(2 * sym.pi * self.t),
                sym.Indexed('gx', 0):
                s(0),
                sym.Indexed('gy', 0):
                s(0)
            })
Пример #21
0
def calc_R2(model, x_points, y_points):  # Calculate R^2
    model = model.subs(x, sym.Indexed(x, k))
    R2_model = sym.sqrt(1 / len(x_points) * sym.Sum(
        ((model) - sym.Indexed(y, k))**2, (k, 0, len(x_points) - 1)))
    f_R2 = sym.lambdify((x, y), R2_model)
    return f_R2(x_points, y_points)
Пример #22
0
def fit_model(str_model, x_points,
              y_points):  # Fit a model to a dataset of (x, y) points
    # Interpret and evaluate the given model
    still_searching = True
    model = str_model.replace('x', 'sym.Indexed(x, k)')
    free_vars = []
    free_vars_indices = []
    while still_searching:
        match = re.search(r"v_\d+", model)
        if not match:
            still_searching = False
            continue
        matching_text = match.group()
        var_num = re.search(r"\d+", matching_text).group()
        model = model[:match.span()[0]] + "sym.Indexed(v," + \
            str(var_num) + ")" + model[match.span()[1]:]
        free_vars.append(eval("sym.Indexed(v," + str(var_num) + ")"))
        free_vars_indices.append(int(var_num))

    model = eval(model)
    # Symbols used but this time declared inside function
    j, k, n, v, x, y, a = sym.symbols('j k n v x y, a')

    # Number of free variables in the model
    num_free_vars = len(free_vars)

    # To be minimized
    E = sym.Sum((model - sym.Indexed(y, k))**2, (k, 0, len(x_points) - 1))

    solved_eqs = []  # List of partially solved equations
    # to_display("Starting now", "debug")
    for var_num in free_vars_indices:
        print("v_" + str(var_num))  # Print this iteration number
        eq = E.diff(sym.Indexed(v, var_num))  # Find the derivative
        # Lambdify the newly created equation
        f = sym.lambdify((x, y, *free_vars), eq)
        # Solve the equation as much as possible
        solved_eq = f(x_points, y_points, *free_vars)
        # Add the soved equation to the list of solved equations
        solved_eqs.append(solved_eq)

    # Solve all the equations for all the free variables
    solved = sym.solve((solved_eqs), (free_vars), simplify=False)

    # Create list of evenly distibuted x-points
    x_list = np.linspace(np.min(x_points) - 1, np.max(x_points) + 1, 10000)

    # Find variables in model str and replace with solved[sym.Indexed(v,n)]
    still_searching = True
    solved_model = str_model
    while still_searching:
        match = re.search(r"v_\d+", solved_model)
        if not match:
            still_searching = False
            continue
        matching_text = match.group()
        var_num = pattern = r"\d+"
        var_num = re.search(r"\d+", matching_text).group()
        if not sym.Indexed(v, var_num) in solved:
            print("excluding {}".format(var_num))
            solved_model = solved_model[:match.span(
            )[0]] + "0" + solved_model[match.span()[1]:]
            continue
        solved_model = solved_model[:match.span(
        )[0]] + "solved[sym.Indexed(v," + str(
            var_num) + ")]" + solved_model[match.span()[1]:]

    # Evaluating the solved model
    solved_model_eval = eval(solved_model)

    # Generate y-coords for each x-coord
    y_generator = sym.lambdify((x), solved_model_eval)
    y_list = y_generator(x_list)

    # Setup figure
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    fig = ax.set_xlim((np.min(x_points) - 0.02, np.max(x_points) + 0.02))
    fig = ax.set_ylim((np.min(y_points) - 0.02, np.max(y_points) + 0.02))

    # R^2
    print("R^2:")
    print(calc_R2(solved_model_eval, x_points, y_points), "R2")

    # Return model
    return (x_list, y_list)
def fit_model(str_model, x_points, y_points):
    still_searching = True
    model = str_model.replace('x', 'sym.Indexed(x, k)')
    free_vars = []
    free_vars_indices = []
    while still_searching:
        match = re.search(r"v_\d+", model)
        if not match:
            still_searching = False
            continue
        matching_text = match.group()
        var_num = re.search(r"\d+", matching_text).group()
        model = model[:match.span()[0]] + "sym.Indexed(v," + str(
            var_num) + ")" + model[match.span()[1]:]
        free_vars.append(eval("sym.Indexed(v," + str(var_num) + ")"))
        free_vars_indices.append(int(var_num))
    # print(model)

    model = eval(model)
    # Symbols used
    j, k, n, v, x, y, a = sym.symbols('j k n v x y, a')

    # Model to use
    num_free_vars = len(free_vars)
    # model = sym.Indexed(v, 1) * sym.sin(sym.Indexed(x, k)) + sym.Indexed(v,2) * sym.cos(sym.Indexed(x, k))
    # model = Indexed(v, 5)*Indexed(x, k)**4 + Indexed(v, 4)*Indexed(x, k)**3 + Indexed(v, 3)*Indexed(x, k)**2 + Indexed(v, 2)*Indexed(x, k)**1 + Indexed(v, 1)*Indexed(x, k)**0
    to_display("Model to fit:", "text")
    to_display(model, "math")

    # To be minimized
    E = sym.Sum((model - sym.Indexed(y, k))**2, (k, 0, len(x_points) - 1))
    to_display("Equation to minimize:", "text")
    to_display(E, "math")

    # List of variables to solve for
    to_display("Free variables to solve for:", "text")
    to_display(free_vars, "math")

    solved_eqs = []
    print("Starting now")
    for var_num in free_vars_indices:
        print(var_num)
        to_display("Solving for: ", "text")
        to_display(sym.Indexed(v, var_num), "math")
        eq = E.diff(sym.Indexed(v, var_num))
        to_display(eq, "math")
        f = sym.lambdify((x, y, *free_vars), eq)
        solved_eq = f(x_points, y_points, *free_vars)
        to_display(solved_eq, "math")
        solved_eqs.append(solved_eq)

    # Solve n equations with n unknowns
    solved = sym.solve((solved_eqs), (free_vars), quick=True)

    # Create list of evenly distibuted x-points
    x_list = np.linspace(np.min(x_points) - 1, np.max(x_points) + 1, 10000)
    # solved_model = solved[sym.Indexed(v, 1)] * sym.sin(x) + solved[sym.Indexed(v,2)] * sym.cos(x)
    still_searching = True
    solved_model = str_model
    while still_searching:
        match = re.search(r"v_\d+", solved_model)
        if not match:
            still_searching = False
            continue
        matching_text = match.group()
        var_num = pattern = r"\d+"
        var_num = re.search(r"\d+", matching_text).group()
        if not sym.Indexed(v, var_num) in solved:
            print("excluding {}".format(var_num))
            solved_model = solved_model[:match.span(
            )[0]] + "0" + solved_model[match.span()[1]:]
            continue
        solved_model = solved_model[:match.span(
        )[0]] + "solved[sym.Indexed(v," + str(
            var_num) + ")]" + solved_model[match.span()[1]:]

    solved_model_eval = eval(solved_model)
    to_display("Solved model evaluated:", "text")
    to_display(solved_model_eval, "math")
    # Generate y-coords for each x-coord
    y_generator = sym.lambdify((x), solved_model_eval)
    y_list = y_generator(x_list)

    # Setup figure
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    fig = ax.set_xlim((np.min(x_points) - 2, np.max(x_points) + 2))
    fig = ax.set_ylim((np.min(y_points) - 2, np.max(y_points) + 2))
    # Display figure
    fig = ax.scatter(x_points, y_points, color='black')
    fig = ax.plot(x_list, y_list)
    if not should_display["diagram"]:
        plt.close()  # Don't display
    plt.show()
    # R^2
    to_display(calc_R2(solved_model_eval, x_points, y_points), "R2")
Пример #24
0
def expansion(maxorder=4):
    """
        A function to compute the expansion of finite volume
        correction parameters f_i(N) in terms of f_i, c_i,  N, and the beta
        function of the theory.

        Parameters
        ----------
        maxorder : int
            Highest order of \alpha taken into account in the expansion.

        References
        ----------
        For details see, e.g.,
        'Bali et al.,  PRD  89, 054505 (2014)'
    """
    res = 0
    #_ii = sp.symbols("_ii")
    f = sp.IndexedBase('f')
    kres = 0

    # "hard mode" expansion (coefficients f[i] )
    #---------------------------------------------------------------------------
    for k in range(maxorder):
        kres += dalpha(k)/sp.factorial(k)*((-sp.log(N))**k)

    # Use a simpler symbol for alpha once we have the expansion
    kres = kres.subs(alpha(x), y).expand()
    #kres = kres.removeO()

    for i in xrange(maxorder):

        order_cutoff = maxorder+1
        if i > 0:
            order_cutoff = maxorder + 1 - i

        if DEBUG_FLAG:
            print "\tterm:{:02d}/{:02d}".format(i+1, maxorder)

        # Remove powers that, when kres is raised to power i, will be
        # of order larger than maxorder
        kres_to_order = kres + sp.O(y**order_cutoff)

        # Make aux an expansion up to order (maxorder)
        aux = kres_to_order.removeO()
        # The previous line is necessary!
        # (spympy.O(x**n)+sympy.O(x**m) =  spympy.O(x**min(n, m)))
        aux = aux + sp.O(y**(maxorder+1))

        aux = rec_power(aux, (i+1))
        # Make aux an expansion up to order (maxorder) again
        # spympy.O(x**n)*sympy.O(x**m) = sympy.O(x**(n+m))
        aux = aux + sp.O(y**(maxorder+1))
        aux = aux.expand(y)

        res += sp.Indexed(f, i)*(aux)

    res = res.expand()

    # "soft mode" expansion (coefficients c[i])
    #---------------------------------------------------------------------------
    hard_exp = 1
    for i in xrange(maxorder-1):
        hard_exp += sp.Indexed(c, i)*y**(i+1)

    res = res*hard_exp
    res = res.expand()

    return res
Пример #25
0
def fit_func_b1_c(xx, NN, i, ORD, bb0, bb1, known, *args):
    """ 
        Fit function describing the finite volume effects for a given order for a
        symmetric lattice with V=L*L. 

        This function is specialised for the case where the c_i coefficients are
        fit parameters and the \beta-function coefficients \beta_0 and \beta_1 are
        set to their physical values. All \beta_j with j>1 are set to zero. 

        WARNING!!!
        ----------
        Note that the coeffs in the PCM calculation are indexed differently
        (c_n corresponds to order \alpha^n , not \alpha^(n+1)

        
        Parameters
        ---------- 
        xx : float 
            The linear lattice extend L (V=L*L). 
        NN : int 
            The rank N of the SU(N) matrices of the Principal Chiral model. 
        i : int 
            The expansion order. 
        ORD : int 
            The highest expansion order considered in the calculation. This is
            has to be known to calculate the total number of free parameters in 
            the fits. 
        bb0 : float 
            The value of the \beta_0 coefficient of the \beta-function of the
            Principal Chiral model. 
        bb1 : float 
            The value of the \beta_1 coefficient of the \beta-function of the
            Principal Chiral model. 
        known : int  
            The number of known infinite volume expansion coefficients used as
            input for the fits.  
        args : array_type 
            An array that holds all the fit coefficients

        Returns
        ------- 
        The fit function for given order i, rank N and lattice size xx. 
          
    """ 
    # Check if logsum already computed ...
    try:
        logsum = logsum_b1_c_dict[(i, ORD)]

    # ... and compute if unknown
    except KeyError:
        #print expansion_coefficient(i)
        # Symbols for lambdify
        lgN, f = sp.symbols("lgN, f")
        global c
        # c[ORD/2-2] and f[ORD/2-1] are not distinguishable in fits
        log_exp = expansion_coefficient(i-1)
        log_exp = log_exp.subs({sp.log(N):lgN,
                                sp.Indexed(c, int(np.floor(ORD/2.))-2):0})
        #Generate logsum function of given order i
        logsum = sp.lambdify((b0, b1, lgN, f, c), log_exp, modules="numpy")

        # Update the global dict
        logsum_b1_c_dict[(i, ORD)] = logsum

    numfitcoef = int(np.floor(ORD/2.)) + 1 - known
    idx_c_coef = int(np.floor(ORD/2.)) + numfitcoef

    xx = np.array(xx)
    xx_log = np.log(xx)


    if i < known:
        return pcm.coef(2*i, NN) + logsum(bb0, bb1, xx_log,
                                          args[numfitcoef:idx_c_coef],
                                          args[idx_c_coef:])/xx**2
    else:
        return args[int(i)-known] + logsum(bb0, bb1, xx_log,
                                           args[numfitcoef:idx_c_coef],
                                           args[idx_c_coef:])/xx**2
Пример #26
0
def epc_string(n, bb1=False, c_coeffs=False, ToFloat=True):
    """ Return a string of expansion coefficient n for use in output *.dat
        files.

        Numerical expressions are evaluated as far as possible and N
        is replaced by x (for plotting in gnuplot). Moreover f[j] is replaced
        by f_b0_j or f_b1_j, depending on the value of bb1.
        Results are cached for later use.

        Parameters
        ----------
        n : int
            Desired coefficient order. Keep in mind the index convention of
            the expansion_coefficient function!

        bb1 : bool
            Flag to toggle inclusion/exclusion of beta_1 terms.
            Default is False.

        c_coeffs : bool
            Flag to toggle inclusion/exclusion of c_i coefficients.
            Default is False.

        ToFloat : bool
            If True numerical expressions (like ratios) are evaluates as far
            as possible. Default is True.

        Returns
        -------
        The expansion coefficient of order n converted to a string.

    """

    try:

        ep_str = epc_strings[(n, bb1, c_coeffs, ToFloat)]

        return ep_str

    except KeyError:

        ep_n = expansion_coefficient(n)
        ep_n = ep_n.subs(N, x)

        if ToFloat:
            ep_n = sp.N(ep_n)
            #print ep_n

        if not bb1:
            ep_n = ep_n.subs(b1, 0)

        if not c_coeffs:
            coeff_c_subs_dict = {sp.Indexed(c, i):0 for i in range(n)}
            ep_n = ep_n.subs(coeff_c_subs_dict)


        ep_n = str(ep_n)


        # Update global dict
        if bb1:
            ep_n = re.sub(r'f\[(\d*)\]', r'f_b1_\1', ep_n)
            ep_n = re.sub(r'c\[(\d*)\]', r'c_b1_\1', ep_n)

        else:
            ep_n = re.sub(r'f\[(\d*)\]', r'f_b0_\1', ep_n)
            ep_n = re.sub(r'c\[(\d*)\]', r'c_b0_\1', ep_n)

        epc_strings[(n, bb1, c_coeffs, ToFloat)] = ep_n


        return ep_n