def eq_x1_hypo_x0_optimize(ix0, iE, x1EQ, zEQ, x0, K, w, yc, Iext1, a=A_DEF, b=B_DEF, d=D_DEF, slope=SLOPE_DEF):

    x1EQ, zEQ, yc, Iext1, K, a, b, d, slope = assert_arrays([x1EQ, zEQ, yc, Iext1, K, a, b, d, slope], (x1EQ.size, ))

    x0 = assert_arrays([x0],  (len(ix0, )))

    w = assert_arrays([w], (x1EQ.size, x1EQ.size))

    xinit = numpy.zeros(x1EQ.shape, dtype=x1EQ.dtype)

    #Set initial conditions for the optimization algorithm, by ignoring coupling (=0)
    # fz = 4 * (x1 - x0_values) - z -coupling = 0
    #x0init = x1 - z/4
    xinit[iE] = calc_x0(x1EQ[iE], zEQ[iE], K=0.0, w=0.0, zmode=numpy.array("lin"), z_pos=True, shape=None)
    #x1eqinit = x0 + z / 4
    xinit[ix0] = x0 + zEQ[ix0] / 4.0

    #Solve:
    sol = root(eq_x1_hypo_x0_optimize_fun, xinit,
               args=(ix0, iE, x1EQ, zEQ, x0, K, w, yc, Iext1, a, b, d, slope),
               method='lm', jac=eq_x1_hypo_x0_optimize_jac, tol=10**(-12), callback=None, options=None) #method='hybr'

    if sol.success:
        x1EQ[ix0] = sol.x[ix0]
        x0sol = sol.x[iE]
        if numpy.any([numpy.any(numpy.isnan(sol.x)), numpy.any(numpy.isinf(sol.x))]):
            raise_value_error("nan or inf values in solution x\n" + sol.message)
        else:
            return x1EQ, x0sol
    else:
        raise_value_error(sol.message)
def calc_eq_x1(yc, Iext1, x0, K, w, a=A_DEF, b=B_DEF, d=D_DEF, zmode=numpy.array("lin"), model="6d"):

    x0, K, yc, Iext1, a, b, d = assert_arrays([x0, K, yc, Iext1, a, b, d])

    n = x0.size
    shape = x0.shape

    x0, K, yc, Iext1, a, b, d = assert_arrays([x0, K, yc, Iext1, a, b, d], (n,))
    w = assert_arrays([w], (n, n))

    # if SYMBOLIC_CALCULATIONS_FLAG:
    #
    #     fx1z, v = symbol_eqtn_fx1z(n, model, zmode)[1:]  # , x1_neg=True, z_pos=True
    #     fx1z = fx1z.tolist()
    #
    #     for iv in range(n):
    #         fx1z[iv] = fx1z[iv].subs([(v["x0_values"][iv], x0_values[iv]), (v["K"][iv], K[iv]), (v["y1"][iv], yc[iv]),
    #                                       (v["Iext1"][iv], Iext1[iv]), (v["a"][iv], a[iv]), (v["b"][iv], b[iv]),
    #                                       (v["d"][iv], d[iv]), (v["tau1"][iv], 1.0), (v["tau0"][iv], 1.0)])
    #         for jv in range(n):
    #             fx1z[iv] = fx1z[iv].subs(v["w"][iv, jv], w[iv, jv])
    #
    #     # TODO: solve symbolically if possible...
    #     # xeq = list(solve(fx1z, v["x1"].tolist()))
    #
    # else:

    fx1z = lambda x1: calc_fx1z(x1, x0, K, w, yc, Iext1, a=a, b=b, d=d, tau1=1.0, tau0=1.0, model=model, zmode=zmode,
                                shape=(Iext1.size, ))

    jac = lambda x1: calc_fx1z_diff(x1, K, w, a, b, d, tau1=1.0, tau0=1.0, model=model, zmode=zmode)

    sol = root(fx1z, -1.5*numpy.ones((Iext1.size, )), jac=jac, method='lm', tol=10 ** (-12), callback=None, options=None)
    #args=(y2eq[ii], zeq[ii], g_eq[ii], Iext2[ii], s, tau1, tau2, x2_neg)  method='hybr'

    if sol.success:

        if numpy.any([numpy.any(numpy.isnan(sol.x)), numpy.any(numpy.isinf(sol.x))]):
            raise_value_error("nan or inf values in solution x\n" + sol.message)

        x1eq = sol.x

    else:
        raise_value_error(sol.message)

    x1eq = numpy.reshape(x1eq, shape)

    if numpy.any(x1eq > 0.0):
        raise_value_error("At least one x1eq is > 0.0!")

    return x1eq
def eq_x1_hypo_x0_optimize(ix0, iE, x1EQ, zEQ, x0, x0cr, r, yc, Iext1, K, w):

    x1EQ, zEQ, x0cr, r, yc, Iext1, K = assert_arrays(
        [x1EQ, zEQ, x0cr, r, yc, Iext1, K], (x1EQ.size, ))

    x0 = assert_arrays([x0], (len(ix0, )))

    w = assert_arrays([w], (x1EQ.size, x1EQ.size))

    xinit = numpy.zeros(x1EQ.shape, dtype=x1EQ.dtype)

    #Set initial conditions for the optimization algorithm, by ignoring coupling (=0)
    # fz = 4 * (x1 - r * x0 + x0cr) - z -coupling = 0
    #x0init = (x1 + x0cr -z/4) / r
    xinit[iE] = calc_x0(x1EQ[iE],
                        zEQ[iE],
                        0.0,
                        0.0,
                        x0cr[iE],
                        r[iE],
                        model="2d",
                        zmode=numpy.array("lin"),
                        z_pos=True,
                        shape=None)
    #x1eqinit = r * x0 - x0cr + z / 4
    xinit[ix0] = r[ix0] * x0 - x0cr[ix0] + zEQ[ix0] / 4

    #Solve:
    sol = root(eq_x1_hypo_x0_optimize_fun,
               xinit,
               args=(ix0, iE, x1EQ, zEQ, x0, x0cr, r, yc, Iext1, K, w),
               method='lm',
               jac=eq_x1_hypo_x0_optimize_jac,
               tol=10**(-12),
               callback=None,
               options=None)  #method='hybr'

    if sol.success:
        x1EQ[ix0] = sol.x[ix0]
        x0sol = sol.x[iE]
        if numpy.any(
            [numpy.any(numpy.isnan(sol.x)),
             numpy.any(numpy.isinf(sol.x))]):
            raise ValueError("nan or inf values in solution x\n" + sol.message)
        else:
            return x1EQ, x0sol
    else:
        raise ValueError(sol.message)
Ejemplo n.º 4
0
 def __init__(self,
              a=1.0,
              b=3.0,
              c=1.0,
              d=5.0,
              aa=6.0,
              r=0.00035,
              kvf=0.0,
              kf=0.0,
              ks=1.5,
              tau=10.0,
              iext=3.1,
              iext2=0.45,
              slope=0.0,
              x0=-2.1,
              tt=1.0):
     a, b, c, d, aa, r, kvf, kf, ks, tau, iext, iext2, slope, x0, tt = \
         assert_arrays([a, b, c, d, aa, r, kvf, kf, ks, tau, iext, iext2, slope, x0, tt])
     # TODO: add desired shape as argument in assert_arrays
     self.nvar = 6
     self.a = a
     self.b = b
     self.c = c
     self.d = d
     self.aa = aa
     self.r = r
     self.Kvf = kvf
     self.Kf = kf
     self.Ks = ks
     self.tau = tau
     self.Iext = iext
     self.Iext2 = iext2
     self.slope = slope
     self.x0 = x0
     self.tt = tt
def eq_x1_hypo_x0_optimize_fun(x, ix0, iE, x1EQ, zEQ, x0, K, w, yc, Iext1, a=A_DEF, b=B_DEF, d=D_DEF, slope=SLOPE_DEF):

    x1_type = x1EQ.dtype

    Iext1, slope, a, b, d = assert_arrays([Iext1, slope, a, b, d])

    # Construct the x1 and z equilibria vectors, comprising of the current x1EQ, zEQ values for i_e regions,
    # and the unknown equilibria x1 and respective z values for the i_x0 regions
    x1EQ[ix0] = numpy.array(x[ix0])
    zEQ[ix0] = numpy.array(calc_eq_z(x1EQ[ix0], yc[ix0], Iext1[ix0], "2d", slope=slope[ix0], a=a[ix0], b=b[ix0],
                                     d=d[ix0]))

    # Construct the x0_values vector, comprising of the current x0_values values for i_x0 regions,
    # and the unknown x0_values values for the i_e regions
    x0_dummy = numpy.array(x0)
    x0 = numpy.empty_like(x1EQ)
    x0[iE] = numpy.array(x[iE])
    x0[ix0] = numpy.array(x0_dummy)
    del x0_dummy

    fun = calc_fz(x1EQ, zEQ, x0, K, w, tau1=1.0, tau0=1.0, zmode=numpy.array("lin"), z_pos=True, ).astype(x1_type)

    # if numpy.any([numpy.any(numpy.isnan(x)), numpy.any(numpy.isinf(x)),
    #               numpy.any(numpy.isnan(fun)), numpy.any(numpy.isinf(fun))]):
    #     raise_value_error("nan or inf values in x or fun")

    return fun
Ejemplo n.º 6
0
def eqtn_fx1z_2d_zpos_jac(x1, r, K, w, ix0, iE, a, b, tau1, tau0):

    p = x1.shape

    x1, r, K, a, b, tau1, tau0 = assert_arrays([x1, r, K, a, b, tau1, tau0],
                                               (1, x1.size))

    no_x0 = len(ix0)
    no_e = len(iE)

    i_x0 = np.ones((no_x0, 1), dtype="float32")
    i_e = np.ones((no_e, 1), dtype="float32")

    tau = np.divide(tau1, tau0)

    jac_e_x0e = np.diag(np.multiply(tau[:, iE], (-4 * r[:, iE])).flatten())
    jac_e_x1o = -np.dot(np.dot(i_e, np.multiply(tau[:, iE], K[:, iE])),
                        w[iE][:, ix0])
    jac_x0_x0e = np.zeros((no_x0, no_e), dtype="float32")
    jac_x0_x1o = (np.diag(
        np.multiply(tau[:, ix0],
                    (4 + 3 * np.multiply(a[:, ix0], np.power(x1[:, ix0], 2)) -
                     2 * np.multiply(b[:, ix0], x1[:, ix0]) + np.multiply(
                         K[:, ix0], np.sum(w[ix0], axis=1)))).flatten()) -
                  np.multiply(
                      np.dot(i_x0, np.multiply(tau[:, ix0], K[:, ix0])).T,
                      w[ix0][:, ix0]))

    jac = np.empty((x1.size, x1.size), dtype=type(jac_e_x0e))
    jac[np.ix_(iE, iE)] = jac_e_x0e
    jac[np.ix_(iE, ix0)] = jac_e_x1o
    jac[np.ix_(ix0, iE)] = jac_x0_x0e
    jac[np.ix_(ix0, ix0)] = jac_x0_x1o

    return jac
Ejemplo n.º 7
0
def eqtn_fx1z_2d_zpos_jac(x1, r, K, w, ix0, iE, a, b, tau1, tau0):  #

    from tvb_epilepsy.base.utils import assert_arrays
    p = x1.shape

    x1, r, K, a, b, tau1, tau0 = assert_arrays([x1, r, K, a, b, tau1, tau0],
                                               (1, x1.size))

    no_x0 = len(ix0)
    no_e = len(iE)

    i_x0 = ones((no_x0, 1), dtype="float32")
    i_e = ones((no_e, 1), dtype="float32")

    tau = divide(tau1, tau0)

    jac_e_x0e = diag(multiply(tau[:, iE], (-4 * r[:, iE])).flatten())
    jac_e_x1o = -dot(dot(i_e, multiply(tau[:, iE], K[:, iE])), w[iE][:, ix0])
    jac_x0_x0e = zeros((no_x0, no_e), dtype="float32")
    jac_x0_x1o = (
        diag(
            multiply(tau[:, ix0],
                     (4 + 3 * multiply(a[:, ix0], power(x1[:, ix0], 2)) -
                      2 * multiply(b[:, ix0], x1[:, ix0]) +
                      multiply(K[:, ix0], sum(w[ix0], axis=1)))).flatten()) -
        multiply(
            dot(i_x0, multiply(tau[:, ix0], K[:, ix0])).T, w[ix0][:, ix0]))

    jac = empty((x1.size, x1.size), dtype=type(jac_e_x0e))
    jac[numpy.ix_(iE, iE)] = jac_e_x0e
    jac[numpy.ix_(iE, ix0)] = jac_e_x1o
    jac[numpy.ix_(ix0, iE)] = jac_x0_x0e
    jac[numpy.ix_(ix0, ix0)] = jac_x0_x1o

    return jac
Ejemplo n.º 8
0
def eqtn_fx1z_diff(x1,
                   K,
                   w,
                   ix,
                   jx,
                   a,
                   b,
                   d,
                   tau1,
                   tau0,
                   model="6d",
                   zmode=np.array("lin")):  # , z_pos=True

    # TODO: for the extreme z_pos = False case where we have terms like 0.1 * z ** 7. See below eqtn_fz()
    # TODO: for the extreme x1_neg = False case where we have to solve for x2 as well

    shape = x1.shape

    x1, K, ix, jx, a, b, d, tau1, tau0 = assert_arrays(
        [x1, K, ix, jx, a, b, d, tau1, tau0], (x1.size, ))

    tau = np.divide(tau1, tau0)

    dcoupl_dx = eqtn_coupling_diff(K, w, ix, jx)

    if zmode == 'lin':
        dfx1_1_dx1 = 4.0 * np.ones(x1[ix].shape)
    elif zmode == 'sig':
        dfx1_1_dx1 = np.divide(
            30 * np.power(np.exp(1), (-10.0 * (x1[ix] + 0.5))),
            np.power(1 + np.power(np.exp(1), (-10.0 * (x1[ix] + 0.5))), 2))
    else:
        raise ValueError('zmode is neither "lin" nor "sig"')

    if model == "2d":
        dfx1_3_dx1 = 3 * np.multiply(np.power(x1[ix], 2.0),
                                     a[ix]) - 2 * np.multiply(x1[ix], b[ix])
    else:
        dfx1_3_dx1 = 3 * np.multiply(np.power(
            x1[ix], 2.0), a[ix]) + 2 * np.multiply(x1[ix], d[ix] - b[ix])

    fx1z_diff = np.empty_like(dcoupl_dx, dtype=dcoupl_dx.dtype)
    for xi in ix:
        for xj in jx:
            if xj == xi:
                fx1z_diff[xi, xj] = np.multiply(
                    dfx1_3_dx1[xi] + dfx1_1_dx1[xi] - dcoupl_dx[xi, xj],
                    tau[xi])
            else:
                fx1z_diff[xi, xj] = np.multiply(-dcoupl_dx[xi, xj], tau[xi])

    return fx1z_diff
def eq_x1_hypo_x0_optimize_jac(x, ix0, iE, x1EQ, zEQ, x0, K, w, yc, Iext1,a=A_DEF, b=B_DEF, d=D_DEF, slope=SLOPE_DEF):

    Iext1, slope, a, b, d, slope = assert_arrays([Iext1, slope, a, b, d, slope])

    # Construct the x1 and z equilibria vectors, comprising of the current x1EQ, zEQ values for i_e regions,
    # and the unknown equilibria x1 and respective z values for the i_x0 regions
    x1EQ[ix0] = numpy.array(x[ix0])
    zEQ[ix0] = numpy.array(calc_eq_z(x1EQ[ix0], yc[ix0], Iext1[ix0], "2d", slope=slope[ix0], a=a[ix0], b=b[ix0],
                                     d=d[ix0]))

    # Construct the x0_values vector, comprising of the current x0_values values for i_x0 regions,
    # and the unknown x0_values values for the i_e regions
    x0_dummy = numpy.array(x0)
    x0 = numpy.empty_like(x1EQ)
    x0[iE] = numpy.array(x[iE])
    x0[ix0] = numpy.array(x0_dummy)
    del x0_dummy

    return calc_fx1z_2d_x1neg_zpos_jac(x1EQ, zEQ, x0, yc, Iext1,  K, w, ix0, iE, a=a, b=b, d=d, tau1=1.0, tau0=1.0)
Ejemplo n.º 10
0
def eqtn_coupling(x1, K, w, ix, jx):
    # Only difference coupling for the moment.
    # TODO: Extend for different coupling forms

    shape = x1.shape

    x1, K = assert_arrays([x1, K], (1, x1.size))

    i_n = np.ones((len(ix), 1), dtype='float32')
    j_n = np.ones((len(jx), 1), dtype='float32')

    # Coupling                 from (jx)                to (ix)
    coupling = np.multiply(
        K[:, ix],
        np.sum(np.multiply(w[ix][:, jx],
                           np.dot(i_n, x1[:, jx]) - np.dot(j_n, x1[:, ix]).T),
               axis=1))

    return np.reshape(coupling, shape)
Ejemplo n.º 11
0
def eqtn_coupling(x1, K, w, ix, jx):

    from tvb_epilepsy.base.utils import assert_arrays

    # Only difference coupling for the moment.
    # TODO: Extend for different coupling forms

    shape = x1.shape

    x1, K = assert_arrays([x1, K], (1, x1.size))

    i_n = ones((len(ix), 1), dtype='float32')
    j_n = ones((len(jx), 1), dtype='float32')

    # Coupling
    #                                                            from (jx)                to (ix)
    coupling = multiply(
        K[:, ix],
        sum(multiply(w[ix][:, jx],
                     dot(i_n, x1[:, jx]) - dot(j_n, x1[:, ix]).T),
            axis=1))

    return reshape(coupling, shape)
def eq_x1_hypo_x0_linTaylor(ix0, iE, x1EQ, zEQ, x0, K, w, yc, Iext1, a=A_DEF, b=B_DEF, d=D_DEF):

    x1EQ, zEQ, yc, Iext1, K, a, b, d = assert_arrays([x1EQ, zEQ, yc, Iext1, K, a, b, d], (1, x1EQ.size))

    x0 = assert_arrays([x0], (1, len(ix0)))

    w = assert_arrays([w], (x1EQ.size, x1EQ.size))

    no_x0 = len(ix0)
    no_e = len(iE)

    n_regions = no_e + no_x0

    # The equilibria of the nodes of fixed epileptogenicity
    x1_eq = x1EQ[:, iE]
    z_eq = zEQ[:, iE]

    #Prepare linear system to solve:

    x1_type = x1EQ.dtype

    #The point of the linear Taylor expansion
    x1LIN = def_x1lin(X1_DEF, X1_EQ_CR_DEF, n_regions).astype(x1_type)

    # For regions of fixed equilibria:
    ii_e = numpy.ones((1, no_e), dtype=x1_type)
    we_to_e = numpy.expand_dims(numpy.sum(w[iE][:, iE] * (numpy.dot(ii_e.T, x1_eq) -
                                                          numpy.dot(x1_eq.T, ii_e)), axis=1), 1).T.astype(x1_type)
    wx0_to_e = x1_eq * numpy.expand_dims(numpy.sum(w[ix0][:, iE], axis=0), 0).astype(x1_type)
    be = 4.0 * x1_eq - z_eq - K[:, iE] * (we_to_e - wx0_to_e)

    # For regions of fixed x0_values:
    ii_x0 = numpy.ones((1, no_x0), dtype=x1_type)
    we_to_x0 = numpy.expand_dims(numpy.sum(w[ix0][:, iE] * numpy.dot(ii_x0.T, x1_eq), axis=1), 1).T.astype(x1_type)
    bx0 = - 4.0 * x0 - yc[:, ix0] - Iext1[:, ix0] - 2.0 * x1LIN[:, ix0] ** 3 - 2.0 * x1LIN[:, ix0] ** 2 \
          - K[:, ix0] * we_to_x0

    # Concatenate B vector:
    b = -numpy.concatenate((be, bx0), axis=1).T.astype(x1_type)

    # From-to Epileptogenicity-fixed regions
    # ae_to_e = -4 * numpy.eye( no_e, dtype=numpy.float32 )
    ae_to_e = -4 * numpy.diag(numpy.ones((no_e,))).astype(x1_type)

    # From x0_values-fixed regions to Epileptogenicity-fixed regions
    ax0_to_e = -numpy.dot(K[:, iE].T, ii_x0) * w[iE][:, ix0]

    # From Epileptogenicity-fixed regions to x0_values-fixed regions
    ae_to_x0 = numpy.zeros((no_x0, no_e), dtype=x1_type)

    # From-to x0_values-fixed regions
    ax0_to_x0 = numpy.diag( (4.0 + 3.0 * x1LIN[:, ix0] ** 2 + 4.0 * x1LIN[:, ix0] +
                K[0, ix0] * numpy.expand_dims(numpy.sum(w[ix0][:, ix0], axis=0), 0)).T[:, 0]) - \
                numpy.dot(K[:, ix0].T, ii_x0) * w[ix0][:, ix0]

    # Concatenate A matrix
    a = numpy.concatenate((numpy.concatenate((ae_to_e, ax0_to_e), axis=1),
                           numpy.concatenate((ae_to_x0, ax0_to_x0), axis=1)), axis=0).astype(x1_type)

    # Solve the system
    x = numpy.dot(numpy.linalg.inv(a), b).T
    if numpy.any([numpy.any(numpy.isnan(x)), numpy.any(numpy.isnan(x))]):
        raise_value_error("nan or inf values in solution x")

    # Unpack solution:
    # The equilibria of the regions with fixed e_values have not changed:
    # The equilibria of the regions with fixed x0_values:
    x1EQ[0, ix0] = x[0, no_e:]

    #Return also the solution of x0s for the regions of fixed e_values (equilibria):
    return x1EQ.flatten(), x[0, :no_e].flatten()
def calc_eq_x2(Iext2, y2eq=None, zeq=None, geq=None, x1eq=None, y1eq=None, Iext1=None, x2=0.0,
               slope=SLOPE_DEF, a=A_DEF, b=B_DEF, d=D_DEF, x1_neg=True, s=S_DEF, x2_neg=True):

    if geq is None:
        geq = calc_eq_g(x1eq)

    if zeq is None:
        zeq = calc_eq_z(x1eq, y1eq, Iext1, "6d", x2, slope, a, b, d, x1_neg)

    zeq, geq, Iext2, s = assert_arrays([zeq, geq, Iext2, s])

    shape = zeq.shape
    n = zeq.size

    zeq, geq, Iext2, s = assert_arrays([zeq, geq, Iext2, s], (n,))

    if SYMBOLIC_CALCULATIONS_FLAG:

        fx2y2, v = symbol_eqtn_fx2y2(n, x2_neg)[1:]
        fx2y2 = fx2y2.tolist()

        x2eq = []
        for iv in range(n):
            fx2y2[iv] = fx2y2[iv].subs([(v["z"][iv], zeq[iv]), (v["g"][iv], geq[iv]), (v["Iext2"][iv], Iext2[iv]),
                                      (v["s"][iv], s[iv]), (v["tau1"][iv], 1.0)])
            fx2y2[iv] = list(solveset(fx2y2[iv], v["x2"][iv], S.Reals))
            x2eq.append(numpy.min(numpy.array(fx2y2[iv], dtype=zeq.dtype)))

    else:

        # fx2 = tau1 * (-y2 + Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05)
        # if x2_neg = True, so that y2eq = 0.0:
        #   fx2 = tau1 * (Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05) =>
        #     0 = x2eq ** 3 - x2eq - (Iext2 + 2 * geq -0.3 * zeq + 1.05)
        # if x2_neg = False , so that y2eq = s*(x2+0.25):
        #   fx2 = tau1 * (-s * (x2 + 0.25) + Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05) =>
        #   fx2 = tau1 * (-0.25 * s  + Iext2 + 2 * g - x2 ** 3 + (1 - s) * x2 - 0.3 * z + 1.05 =>
        #     0 = x2eq ** 3 + (s - 1) * x2eq - (Iext2 + 2 * geq -0.3 * zeq - 0.25 * s + 1.05)

        # According to http://mathworld.wolfram.com/CubicFormula.html
        # and given that there is no square term (x2eq^2; "depressed cubic"), we write the equation in the form:
        # x^3 + 3 * Q * x -2 * R = 0
        Q = (-numpy.ones((n, ))/3.0)
        R = ((Iext2 + 2.0 * geq - 0.3 * zeq + 1.05) / 2)
        if y2eq is None:
            ss = numpy.where(x2_neg, 0.0, s)
            Q += ss / 3
            R -= 0.25 * ss / 2
        else:
            y2eq = (assert_arrays([y2eq], (n, )))
            R += y2eq / 2

        # Then the determinant is :
        # delta = Q^3 + R^2 =>
        delta = Q ** 3 + R ** 2
        # and S = cubic_root(R+sqrt(D), T = cubic_root(R-sqrt(D)
        delta_sq = numpy.sqrt(delta.astype("complex")).astype("complex")
        ST = [R + delta_sq, R - delta_sq]
        for ii in range(2):
            for iv in range(n):
                if numpy.imag(ST[ii][iv]) == 0.0:
                    ST[ii][iv] = numpy.sign(ST[ii][iv]) * numpy.power(numpy.abs(ST[ii][iv]), 1.0/3)
                else:
                    ST[ii][iv] = numpy.power(ST[ii][iv], 1.0 / 3)
        # and B = S+T, A = S-T
        B = ST[0]+ST[1]
        A = ST[0]-ST[1]
        # The roots then are:
        # x1 = -1/3 * a2 + B
        # x21 = -1/3 * a2 - 1/2 * B + 1/2 * sqrt(3) * A * j
        # x22 = -1/3 * a2 - 1/2 * B - 1/2 * sqrt(3) * A * j
        # where j = sqrt(-1)
        # But, in our case a2 = 0.0, so that:
        B2 = - 0.5 *B
        AA = (0.5 * numpy.sqrt(3.0) * A * 1j)
        sol = numpy.concatenate([[B.flatten()], [B2 + AA], [B2 - AA]]).T
        x2eq = []
        for ii in range(delta.size):
            temp = sol[ii, numpy.abs(numpy.imag(sol[ii])) < 10 ** (-6)]
            if temp.size == 0:
                raise_value_error("No real roots for x2eq_" + str(ii))
            else:
                x2eq.append(numpy.min(numpy.real(temp)))

        # zeq = zeq.flatten()
        # geq = geq.flatten()
        # Iext2 = Iext2.flatten()
        # x2eq = []
        # for ii in range(n):
        #
        #     if y2eq is None:
        #
        #         fx2 = lambda x2: calc_fx2(x2, y2=calc_eq_y2(x2, x2_neg=x2_neg), z=zeq[ii], g=geq[ii],
        #                                   Iext2=Iext2[ii], tau1=1.0)
        #
        #         jac = lambda x2: -3 * x2 ** 2 + 1.0 - numpy.where(x2_neg, 0.0, -s)
        #
        #     else:
        #
        #         fx2 = lambda x2: calc_fx2(x2, y2=0.0, z=zeq[ii], g=geq[ii], Iext2=Iext2[ii], tau1=1.0)
        #         jac = lambda x2: -3 * x2 ** 2 + 1.0
        #
        #     sol = root(fx2, -0.5, method='lm', jac=jac, tol=10 ** (-6), callback=None, options=None)
        #
        #     if sol.success:
        #
        #         if numpy.any([numpy.any(numpy.isnan(sol.x)), numpy.any(numpy.isinf(sol.x))]):
        #             raise_value_error("nan or inf values in solution x\n" + sol.message)
        #
        #         x2eq.append(numpy.min(numpy.real(numpy.array(sol.x))))
        #
        #     else:
        #         raise_value_error(sol.message)

    if numpy.array(x2_neg).size == 1:
        x2_neg = numpy.tile(x2_neg, (n, ))

    for iv in range(n):

        if x2_neg[iv] == False and x2eq[iv] < -0.25:
            warning("\nx2eq["+str(iv)+"] = " + str(x2eq[iv]) + " < -0.25, although x2_neg[" + str(iv)+"] = False!" +
                    "\n" + "Rerunning with x2_neg[" + str(iv)+"] = True...")
            temp, _ = calc_eq_x2(Iext2[iv], zeq=zeq[iv], geq=geq[iv], s=s[iv], x2_neg=True)
            if temp < -0.25:
                x2eq[iv] = temp
                x2_neg[iv] = True
            else:
                warning("\nThe value of x2eq returned after rerunning with x2_neg[" + str(iv)+"] = True, " +
                        "is " + str(temp) + ">= -0.25!" +
                        "\n" + "We will use the original x2eq!")

        if x2_neg[iv] == True and x2eq[iv] > -0.25:
            warning("\nx2eq["+str(iv)+"] = " + str(x2eq[iv]) + " > -0.25, although x2_neg[" + str(iv)+"] = True!" +
                    "\n" + "Rerunning with x2_neg[" + str(iv)+"] = False...")
            temp, _ = calc_eq_x2(Iext2[iv], zeq=zeq[iv], geq=geq[iv], s=s[iv], x2_neg=False)
            if temp > -0.25:
                x2eq[iv] = temp
                x2_neg[iv] = True
            else:
                warning("\nThe value of x2eq returned after rerunning with x2_neg[" + str(iv)+"] = False, " +
                        "is " + str(temp) + "=< -0.25!" +
                        "\n" + "We will use the original x2eq!")

    x2eq = numpy.reshape(x2eq, shape)

    return x2eq, x2_neg
def calc_eq_y2(x2eq, s=S_DEF, x2_neg=False):

    x2eq = assert_arrays([x2eq])

    return numpy.where(x2_neg, numpy.zeros(x2eq.shape), s * (x2eq + 0.25))