J'ai du mal à comprendre comment la fonction rhs (u, m, r) du code ci-dessous reçoit les paramètres m et r . Comme il est possible de voir à partir du code, la fonction rhs est appelée à l'intérieur de la fonction euler_step (u, rhs, dt) , mais ni les paramètres m et r sont passés comme arguments à la fonction euler_step et ils ne sont pas des variables globales. Ainsi, quelqu'un peut m'expliquer comment les paramètres m et u arrivent via la fonction rhs .

# model parameters:
mpo = 100.   # initial mass of the rocket propellant in kg
ms = 50.     # mass of the rocket shell in kg
g = 9.81     # gravity in m s^{-2}
rho = 1.091  # average air density in kg/m^{3}
rad = 0.5    # radius of the maximum cross sectional area of the rocket in m
A = numpy.pi*(rad**2)# maximum cross sectional area of the rocket in m^{2}
v_e = 325.   # the exhaust speed in m/s
C_D = 0.15   # drag coefficient
rt = 20.0    # propellant burn rate in kg/s
dtp = 5.0    # time interval to empty the propellant in s

### set initial conditions ###
h0 = 0.0 # start at the zero height [m]
v0 = 0.0 # initial speed [m/s]

def rhs(u, m, r):
    """Returns the right-hand side of the phugoid system of equations.

    Parameters
    ----------
    u : array of float
        array containing the solution at time n.
    mp: float
        mass of the propellant at time t
    mp_rate: float
        propellant burn rate

    Returns
    -------
    dudt : array of float
        array containing the RHS given u.
    """
    print("[m,r]",[m,r])
    [h,v] = u.copy()

    return numpy.array( [ v, -g + pow((ms+m),-1)*(r*v_e - 0.5*rho*v*abs(v)*A*C_D) ] )

def euler_step(u, rhs, dt):
    """Returns the solution at the next time-step using Euler's method.

    Parameters
    ----------
    u : array of float
        solution at the previous time-step.
    rhs : function
        function to compute the right hand-side of the system of equation.
    dt : float
        time-increment.

    Returns
    -------
    u_n_plus_1 : array of float
        approximate solution at the next time step.
    """

    return u + dt * rhs(u, m, r)

if __name__ == "__main__":
    T = 17.0                     # final time
    dt = 0.1                     # time increment
    t = numpy.arange(0.0, T, dt) # time discretization
    N = len(t)                   # number of time-steps

    # initialize the array containing the solution for each time-step
    u = numpy.zeros((N, 2))
    u[0] = numpy.array([h0, v0]) # fill 1st element with initial values
    rate = numpy.zeros(N)
    mp = numpy.zeros(N)
    Np = int(((N)/(T))*dtp) # number of time-steps with propellant burn

    rate[0:Np] = rt # propellant burn rate in kg/s
    mp[0:Np] = mpo - rt*t[0:Np]

    # time loop - Euler method
    for n in range(1,N-1):

        r = rate[n]
        m = mp[n]
        print("[R,M]",[r,m])
        u[n+1] = euler_step(u[n], rhs, dt)

Merci d'avance.

1
Randerson 9 mars 2016 à 19:25

3 réponses

Meilleure réponse

m et n sont globaux.

Cela peut être déroutant car il peut sembler que __main__ était une fonction, mais ce n'est pas le cas. Le if __name__ == "__main__" .... s'exécute sur une portée globale.

4
Juan Leni 9 mars 2016 à 16:32

Ce sont des variables globales. En Python, if, while et for ne pas créent une étendue de variable distincte, de sorte que des valeurs leur sont toujours affectées dans l'étendue globale / module avant la première invocation de euler_step:

if __name__ == "__main__":  # does not start a new variable scope
    ...

    for n in range(1,N-1):  # does not start one either
        # thus these variables are set in global scope.
        r = rate[n]
        m = mp[n]

        # and euler_step is invoked only here, thus it will see
        # r and m being set.
        u[n+1] = euler_step(u[n], rhs, dt)

Voir aussi Brève description des règles de portée?.

3
Community 23 mai 2017 à 11:45

m et r sont définis près du bas de votre script au niveau du module:

r = rate[n]
m = mp[n]

Par conséquent, , ils sont disponibles pour toutes les fonctions du module :

Les blocs suivants sont: un module, un corps de fonction et une définition de classe. Une portée définit la visibilité d'un nom dans un bloc. Si une variable locale est définie dans un bloc, sa portée inclut ce bloc. Si la définition se produit dans un bloc fonction, la portée s'étend à tous les blocs contenus dans celui-ci, à moins qu'un bloc contenu n'introduise une liaison différente pour le nom ... Lorsqu'un nom est utilisé dans un bloc de code, il est résolu en utilisant le portée la plus proche.

1
Matt S 9 mars 2016 à 16:34