Beispiel #1
0
def calculate(f: sp.Add, var: Tuple[sp.Symbol, sp.Symbol], eps: float = 0.001, debug: bool = False)\
        -> List[Tuple[float, float]]:
    x, y = var
    first_diff = sp.Matrix([sp.diff(f, x), sp.diff(f, y)])

    a = sp.Symbol('a')

    point = sp.Matrix([0.0, 0.0])
    prev_point = sp.Matrix([0.0, 0.0])

    result: List[Tuple[float, float]] = [(point[0], point[1])]

    iteration = 0
    while iteration < 1 or sqrt((point[0] - prev_point[0])**2 + (point[1] - prev_point[1])**2) > eps:
        if debug:
            print()
        prev_point = point
        next_point = point - a * first_diff.subs({x: point[0], y: point[1]})
        step = sp.solve(sp.diff(f.subs({x: next_point[0], y: next_point[1]}), a))[0]
        point = next_point.subs({a: step})
        result.append((point[0], point[1]))

        iteration += 1

    if debug:
        print(f"Method of quick going down found solution of: {(point[0], point[1])}")

    return result
Beispiel #2
0
def newtons_method(
        function: sympy.Add, x0, error, max_iteration
):  # function is a sympy expresion. x0 is the initial point.
    x1 = x0
    x2 = x0
    iteration = 0
    while iteration < max_iteration:
        iteration += 1
        x2 = x1 - (float(function.subs(x, x1)) /
                   float(sympy.diff(function, x).subs(x, x1)))
        x1 = x2
        if abs(float(function.subs(x, x2))) < error:
            break
    print("Newtons method: ", x2, "The answer was found after ", iteration,
          "iterations")
    return x2
Beispiel #3
0
    def atomic_ordering_energy(self, dbe):
        """
        Return the atomic ordering contribution in symbolic form.
        Description follows Servant and Ansara, Calphad, 2001.
        """
        phase = dbe.phases[self.phase_name]
        ordered_phase_name = phase.model_hints.get("ordered_phase", None)
        disordered_phase_name = phase.model_hints.get("disordered_phase", None)
        if phase.name != ordered_phase_name:
            return S.Zero
        disordered_model = self.__class__(dbe, self.components, disordered_phase_name)
        constituents = [
            sorted(set(c).intersection(self.components)) for c in dbe.phases[ordered_phase_name].constituents
        ]

        # Fix variable names
        variable_rename_dict = {}
        for atom in disordered_model.energy.atoms(v.SiteFraction):
            # Replace disordered phase site fractions with mole fractions of
            # ordered phase site fractions.
            # Special case: Pure vacancy sublattices
            all_species_in_sublattice = dbe.phases[disordered_phase_name].constituents[atom.sublattice_index]
            if atom.species == "VA" and len(all_species_in_sublattice) == 1:
                # Assume: Pure vacancy sublattices are always last
                vacancy_subl_index = len(dbe.phases[ordered_phase_name].constituents) - 1
                variable_rename_dict[atom] = v.SiteFraction(ordered_phase_name, vacancy_subl_index, atom.species)
            else:
                # All other cases: replace site fraction with mole fraction
                variable_rename_dict[atom] = self.mole_fraction(
                    atom.species, ordered_phase_name, constituents, dbe.phases[ordered_phase_name].sublattices
                )
        # Save all of the ordered energy contributions
        # This step is why this routine must be called _last_ in build_phase
        ordered_energy = Add(*list(self.models.values()))
        self.models.clear()
        # Copy the disordered energy contributions into the correct bins
        for name, value in disordered_model.models.items():
            self.models[name] = value.xreplace(variable_rename_dict)
        # All magnetic parameters will be defined in the disordered model
        self.TC = self.curie_temperature = disordered_model.TC
        self.TC = self.curie_temperature = self.TC.xreplace(variable_rename_dict)

        molefraction_dict = {}

        # Construct a dictionary that replaces every site fraction with its
        # corresponding mole fraction in the disordered state
        for sitefrac in ordered_energy.atoms(v.SiteFraction):
            all_species_in_sublattice = dbe.phases[ordered_phase_name].constituents[sitefrac.sublattice_index]
            if sitefrac.species == "VA" and len(all_species_in_sublattice) == 1:
                # pure-vacancy sublattices should not be replaced
                # this handles cases like AL,NI,VA:AL,NI,VA:VA and
                # ensures the VA's don't get mixed up
                continue
            molefraction_dict[sitefrac] = self.mole_fraction(
                sitefrac.species, ordered_phase_name, constituents, dbe.phases[ordered_phase_name].sublattices
            )

        return ordered_energy - ordered_energy.subs(molefraction_dict, simultaneous=True)
Beispiel #4
0
def _inverse_mellin_transform(F, s, x_, strip, as_meijerg=False):
    """ A helper for the real inverse_mellin_transform function, this one here
        assumes x to be real and positive. """
    from sympy import (expand, expand_mul, hyperexpand, meijerg, And, Or, arg,
                       pi, re, factor, Heaviside, gamma, Add)
    x = _dummy('t', 'inverse-mellin-transform', F, positive=True)
    # Actually, we won't try integration at all. Instead we use the definition
    # of the Meijer G function as a fairly general inverse mellin transform.
    F = F.rewrite(gamma)
    for g in [factor(F), expand_mul(F), expand(F)]:
        if g.is_Add:
            # do all terms separately
            ress = [_inverse_mellin_transform(G, s, x, strip, as_meijerg,
                                              noconds=False) \
                    for G in g.args]
            conds = [p[1] for p in ress]
            ress = [p[0] for p in ress]
            res = Add(*ress)
            if not as_meijerg:
                res = factor(res, gens=res.atoms(Heaviside))
            return res.subs(x, x_), And(*conds)

        try:
            a, b, C, e, fac = _rewrite_gamma(g, s, strip[0], strip[1])
        except IntegralTransformError:
            continue
        G = meijerg(a, b, C / x**e)
        if as_meijerg:
            h = G
        else:
            h = hyperexpand(G)
            if h.is_Piecewise and len(h.args) == 3:
                # XXX we break modularity here!
                h = Heaviside(x - abs(C))*h.args[0].args[0] \
                  + Heaviside(abs(C) - x)*h.args[1].args[0]
        # We must ensure that the intgral along the line we want converges,
        # and return that value.
        # See [L], 5.2
        cond = [abs(arg(G.argument)) < G.delta * pi]
        # Note: we allow ">=" here, this corresponds to convergence if we let
        # limits go to oo symetrically. ">" corresponds to absolute convergence.
        cond += [
            And(Or(len(G.ap) != len(G.bq), 0 >= re(G.nu) + 1),
                abs(arg(G.argument)) == G.delta * pi)
        ]
        cond = Or(*cond)
        if cond is False:
            raise IntegralTransformError('Inverse Mellin', F,
                                         'does not converge')
        return (h * fac).subs(x, x_), cond

    raise IntegralTransformError('Inverse Mellin', F, '')
Beispiel #5
0
def subs_Eqs(eq: Add, eqs: Sequence[Eq]) -> Add:
    """
        TODO: Проверить какой класс является базовым для всех выражений sympy
        @param eq: expression
        @param eqs: Eq
        @return: expression

        Например: x = z+2*y
        Это eq.subs({x: z+2*y})
    """
    for eq in eqs:
        left, right = eq.args[0], eq.args[1]
        eq = eq.subs({left: right})
    return eq
Beispiel #6
0
def _inverse_mellin_transform(F, s, x_, strip, as_meijerg=False):
    """ A helper for the real inverse_mellin_transform function, this one here
        assumes x to be real and positive. """
    from sympy import (expand, expand_mul, hyperexpand, meijerg, And, Or,
                       arg, pi, re, factor, Heaviside, gamma, Add)
    x = _dummy('t', 'inverse-mellin-transform', F, positive=True)
    # Actually, we won't try integration at all. Instead we use the definition
    # of the Meijer G function as a fairly general inverse mellin transform.
    F = F.rewrite(gamma)
    for g in [factor(F), expand_mul(F), expand(F)]:
        if g.is_Add:
            # do all terms separately
            ress = [_inverse_mellin_transform(G, s, x, strip, as_meijerg,
                                              noconds=False) \
                    for G in g.args]
            conds = [p[1] for p in ress]
            ress = [p[0] for p in ress]
            res = Add(*ress)
            if not as_meijerg:
                res = factor(res, gens=res.atoms(Heaviside))
            return res.subs(x, x_), And(*conds)

        try:
            a, b, C, e, fac = _rewrite_gamma(g, s, strip[0], strip[1])
        except IntegralTransformError:
            continue
        G = meijerg(a, b, C/x**e)
        if as_meijerg:
            h = G
        else:
            h = hyperexpand(G)
            if h.is_Piecewise and len(h.args) == 3:
                # XXX we break modularity here!
                h = Heaviside(x - abs(C))*h.args[0].args[0] \
                  + Heaviside(abs(C) - x)*h.args[1].args[0]
        # We must ensure that the intgral along the line we want converges,
        # and return that value.
        # See [L], 5.2
        cond = [abs(arg(G.argument)) < G.delta*pi]
        # Note: we allow ">=" here, this corresponds to convergence if we let
        # limits go to oo symetrically. ">" corresponds to absolute convergence.
        cond += [And(Or(len(G.ap) != len(G.bq), 0 >= re(G.nu) + 1),
                     abs(arg(G.argument)) == G.delta*pi)]
        cond = Or(*cond)
        if cond is False:
            raise IntegralTransformError('Inverse Mellin', F, 'does not converge')
        return (h*fac).subs(x, x_), cond

    raise IntegralTransformError('Inverse Mellin', F, '')
Beispiel #7
0
    def atomic_ordering_energy(self, dbe):
        """
        Return the atomic ordering contribution in symbolic form.
        Description follows Servant and Ansara, Calphad, 2001.
        """
        phase = dbe.phases[self.phase_name]
        ordered_phase_name = phase.model_hints.get('ordered_phase', None)
        disordered_phase_name = phase.model_hints.get('disordered_phase', None)
        if phase.name != ordered_phase_name:
            return S.Zero
        disordered_model = self.__class__(dbe, sorted(self.components),
                                          disordered_phase_name)
        constituents = [sorted(set(c).intersection(self.components)) \
                for c in dbe.phases[ordered_phase_name].constituents]

        # Fix variable names
        variable_rename_dict = {}
        for atom in disordered_model.energy.atoms(v.SiteFraction):
            # Replace disordered phase site fractions with mole fractions of
            # ordered phase site fractions.
            # Special case: Pure vacancy sublattices
            all_species_in_sublattice = \
                dbe.phases[disordered_phase_name].constituents[
                    atom.sublattice_index]
            if atom.species == 'VA' and len(all_species_in_sublattice) == 1:
                # Assume: Pure vacancy sublattices are always last
                vacancy_subl_index = \
                    len(dbe.phases[ordered_phase_name].constituents)-1
                variable_rename_dict[atom] = \
                    v.SiteFraction(
                        ordered_phase_name, vacancy_subl_index, atom.species)
            else:
                # All other cases: replace site fraction with mole fraction
                variable_rename_dict[atom] = \
                    self.mole_fraction(
                        atom.species,
                        ordered_phase_name,
                        constituents,
                        dbe.phases[ordered_phase_name].sublattices
                        )
        # Save all of the ordered energy contributions
        # This step is why this routine must be called _last_ in build_phase
        ordered_energy = Add(*list(self.models.values()))
        self.models.clear()
        # Copy the disordered energy contributions into the correct bins
        for name, value in disordered_model.models.items():
            self.models[name] = value.xreplace(variable_rename_dict)
        # All magnetic parameters will be defined in the disordered model
        self.TC = self.curie_temperature = disordered_model.TC
        self.TC = self.curie_temperature = self.TC.xreplace(variable_rename_dict)

        molefraction_dict = {}

        # Construct a dictionary that replaces every site fraction with its
        # corresponding mole fraction in the disordered state
        for sitefrac in ordered_energy.atoms(v.SiteFraction):
            all_species_in_sublattice = \
                dbe.phases[ordered_phase_name].constituents[
                    sitefrac.sublattice_index]
            if sitefrac.species == 'VA' and len(all_species_in_sublattice) == 1:
                # pure-vacancy sublattices should not be replaced
                # this handles cases like AL,NI,VA:AL,NI,VA:VA and
                # ensures the VA's don't get mixed up
                continue
            molefraction_dict[sitefrac] = \
                self.mole_fraction(sitefrac.species,
                                   ordered_phase_name, constituents,
                                   dbe.phases[ordered_phase_name].sublattices)

        return ordered_energy - ordered_energy.subs(molefraction_dict,
                                                    simultaneous=True)