Exemple #1
0
def _EvolveRotationStepRK4(Mstar=None,
                           Age=None,
                           OmegaEnv=None,
                           OmegaCore=None,
                           dAge=None,
                           params=params.paramsDefault,
                           StarEvo=None):
    """Takes basic stellar parameters, evolves by timestep using classical Runge-Kutta method."""

    # Get rates of change
    k1Env, k1Core = phys.dOmegadt(Mstar=Mstar,
                                  Age=Age,
                                  OmegaEnv=OmegaEnv,
                                  OmegaCore=OmegaCore,
                                  params=params,
                                  StarEvo=StarEvo)
    k2Env, k2Core = phys.dOmegadt(Mstar=Mstar,
                                  Age=Age + 0.5 * dAge,
                                  OmegaEnv=OmegaEnv + 0.5 * dAge * k1Env,
                                  OmegaCore=OmegaCore + 0.5 * dAge * k1Core,
                                  params=params,
                                  StarEvo=StarEvo)
    k3Env, k3Core = phys.dOmegadt(Mstar=Mstar,
                                  Age=Age + 0.5 * dAge,
                                  OmegaEnv=OmegaEnv + 0.5 * dAge * k2Env,
                                  OmegaCore=OmegaCore + 0.5 * dAge * k2Core,
                                  params=params,
                                  StarEvo=StarEvo)
    k4Env, k4Core = phys.dOmegadt(Mstar=Mstar,
                                  Age=Age + dAge,
                                  OmegaEnv=OmegaEnv + dAge * k3Env,
                                  OmegaCore=OmegaCore + dAge * k3Core,
                                  params=params,
                                  StarEvo=StarEvo)

    # Do update
    OmegaEnv += dAge * (k1Env + 2.0 * k2Env + 2.0 * k3Env + k4Env) / 6.0
    OmegaCore += dAge * (k1Core + 2.0 * k2Core + 2.0 * k3Core + k4Core) / 6.0

    return (dAge, dAge, OmegaEnv, OmegaCore)
Exemple #2
0
def _JacobianRB(Mstar, Age, X, nVar, params, StarEvo):
    """Calculates Jacobian d(dOmega/dt)/dOmega terms for Rosenbrock solver."""

    # Make array
    Jac = np.zeros((nVar, nVar))

    # Loop over elements and fill in Jacobian
    for iVar in range(0, nVar):

        # Set perturbed X values to X
        X1 = copy.deepcopy(X)
        X2 = copy.deepcopy(X)

        # Perturb this variable
        X1[iVar] = X1[iVar] - params['deltaJac'] * X1[iVar]
        X2[iVar] = X2[iVar] + params['deltaJac'] * X2[iVar]

        # Get rates based on pertubed quantities
        dXdt1 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age,
                          OmegaEnv=X1[0],
                          OmegaCore=X1[1],
                          params=params,
                          StarEvo=StarEvo))
        dXdt2 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age,
                          OmegaEnv=X2[0],
                          OmegaCore=X2[1],
                          params=params,
                          StarEvo=StarEvo))

        # Fill in this column of Jacobian
        Jac[:, iVar] = (dXdt2[:] - dXdt1[:]) / (X2[iVar] - X1[iVar])

    return Jac
Exemple #3
0
def _EvolveRotationStepFE(Mstar=None,
                          Age=None,
                          OmegaEnv=None,
                          OmegaCore=None,
                          dAge=None,
                          params=params.paramsDefault,
                          StarEvo=None):
    """Takes basic stellar parameters, evolves by timestep using forward Euler method."""

    # Get rates of change
    dOmegaEnvdt, dOmegaCoredt = phys.dOmegadt(Mstar=Mstar,
                                              Age=Age,
                                              OmegaEnv=OmegaEnv,
                                              OmegaCore=OmegaCore,
                                              params=params,
                                              StarEvo=StarEvo)

    # Do update
    OmegaEnv += dAge * dOmegaEnvdt
    OmegaCore += dAge * dOmegaCoredt

    return (dAge, dAge, OmegaEnv, OmegaCore)
Exemple #4
0
def _kCoeffRB(Mstar, Age, dAge, X, Jac, nVar, CoefficientsRB, params, StarEvo):
    """Calculates kCoeff for Rosenbrock solver."""

    # Make array for holding result
    kCoeff = np.zeros((nVar, CoefficientsRB['s']))

    #-----------------------------------------------------------------------------
    # Get the function involving the Jacobian, given by (I - dt * gamma_ii * J)
    # note: since all gamma_ii coefficients are equal, this function only needs to
    #       be calculated once and can then be used for all values of i
    # however, it must be recalculated if the timestep is changed

    # Set the function to -dt*J for all elements
    JacFunc = -dAge * CoefficientsRB['gamma'][0, 0] * Jac

    # Loop over diagonal elements and add 1 to each
    for iVar in range(0, nVar):
        JacFunc[iVar, iVar] += 1.0

    #-----------------------------------------------------------------------------

    # Get k1
    dXdt = np.array(
        phys.dOmegadt(Mstar=Mstar,
                      Age=Age + dAge,
                      OmegaEnv=X[0],
                      OmegaCore=X[1],
                      params=params,
                      StarEvo=StarEvo))
    RateFunction = dAge * dXdt
    kCoeff[:, 0] = _GaussianElimination(JacFunc, RateFunction)

    #-----------------------------------------------------------------------------

    # Get k2,...ks
    for i in range(1, CoefficientsRB['s']):

        # Get intermediate values
        Xmid = copy.deepcopy(X)
        for i2 in range(0, i):
            Xmid += CoefficientsRB['alpha'][i, i2] * kCoeff[:, i2]

        # Get intermediate rates
        dXdt = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age + dAge,
                          OmegaEnv=Xmid[0],
                          OmegaCore=Xmid[1],
                          params=params,
                          StarEvo=StarEvo))

        # Get the rate function
        RateFunction = dAge * dXdt
        for i2 in range(0, i):
            for iVar in range(0, nVar):
                RateFunction[iVar] += dAge * CoefficientsRB['gamma'][
                    i, i2] * np.sum(Jac[iVar, :] * kCoeff[:, i2])

        # Get k value for this step
        kCoeff[:, i] = _GaussianElimination(JacFunc, RateFunction)

    #-----------------------------------------------------------------------------

    return kCoeff
Exemple #5
0
def _EvolveRotationStepRKF(Mstar=None,
                           Age=None,
                           OmegaEnv=None,
                           OmegaCore=None,
                           dAgeMax=None,
                           dAge=None,
                           params=params.paramsDefault,
                           StarEvo=None):
    """Takes basic stellar parameters, evolves by timestep using Runge-Kutta-Fehlberg method."""

    # Start with dAge as timestep
    dAgeNew = dAge

    # Setup array to hold integration values
    X = np.array([OmegaEnv, OmegaCore])

    # Start iterating until got accuracy desired
    while True:

        # Set dAge
        dAge = dAgeNew

        # k1
        k1 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age,
                          OmegaEnv=X[0],
                          OmegaCore=X[1],
                          params=params,
                          StarEvo=StarEvo))

        # k2
        Age2 = Age + (1.0 / 5.0) * dAge
        X2 = X + (1.0 / 5.0) * dAge * k1
        k2 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age2,
                          OmegaEnv=X2[0],
                          OmegaCore=X2[1],
                          params=params,
                          StarEvo=StarEvo))

        # k3
        Age3 = Age + (3.0 / 10.0) * dAge
        X3 = X + (3.0 / 40.0) * dAge * k1 + (9.0 / 40.0) * dAge * k2
        k3 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age3,
                          OmegaEnv=X3[0],
                          OmegaCore=X3[1],
                          params=params,
                          StarEvo=StarEvo))

        # k4
        Age4 = Age + (3.0 / 5.0) * dAge
        X4 = X + (3.0 / 10.0) * dAge * k1 - (9.0 / 10.0) * dAge * k2 + (
            6.0 / 5.0) * dAge * k3
        k4 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age4,
                          OmegaEnv=X4[0],
                          OmegaCore=X4[1],
                          params=params,
                          StarEvo=StarEvo))

        # k5
        Age5 = Age + dAge
        X5 = X - (11.0 / 54.0) * dAge * k1 + (5.0 / 2.0) * dAge * k2 - (
            70.0 / 27.0) * dAge * k3 + (35.0 / 27.0) * dAge * k4
        k5 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age5,
                          OmegaEnv=X5[0],
                          OmegaCore=X5[1],
                          params=params,
                          StarEvo=StarEvo))

        # k6
        Age6 = Age + (7.0 / 8.0) * dAge
        X6 = X + (1631.0 / 55296.0) * dAge * k1 + (
            175.0 / 512.0) * dAge * k2 + (575.0 / 13824.0) * dAge * k3 + (
                44275.0 / 110592.0) * dAge * k4 + (253.0 / 4096.0) * dAge * k5
        k6 = np.array(
            phys.dOmegadt(Mstar=Mstar,
                          Age=Age6,
                          OmegaEnv=X6[0],
                          OmegaCore=X6[1],
                          params=params,
                          StarEvo=StarEvo))

        # Calculate candidate update
        Xnew = X + (37.0 / 378.0) * dAge * k1 + (250.0 / 621.0) * dAge * k3 + (
            125.0 / 594.0) * dAge * k4 + (512.0 / 1771.0) * dAge * k6

        # Calculate forth order update
        Xforth = X + (2825.0 / 27648.0) * dAge * k1 + (
            18575.0 /
            48384.0) * dAge * k3 + (13525.0 / 55296.0) * dAge * k4 + (
                277.0 / 14336.0) * dAge * k5 + (1.0 / 4.0) * dAge * k6

        # Get error in this timestep for each species and grid point
        Delta = Xnew - Xforth

        # Get the factor by which to change dt
        # Need to take care here if Delta=0 since this can happen if dX/dt=0 over the entire timestep
        if (np.min(np.abs(Delta)) == 0.0):
            dAgeFactor = 1.5
        else:
            dAgeFactor = np.min(np.abs(params['DeltaDesired'] * X / Delta))

        # Get new dt
        dAgeNew = 0.9 * dAge * dAgeFactor**0.2

        # Make sure dt is not too big
        dAgeNew = min(dAgeNew, dAgeMax)

        # Check for stopping of iteration
        if (dAgeFactor > 1.0):
            break

    # Save new estimate
    OmegaEnv = Xnew[0]
    OmegaCore = Xnew[1]

    return dAge, dAgeNew, OmegaEnv, OmegaCore