def define_xi_related_eqns(self) -> None: r""" Define equations related to the erosion model. Define equations related to surface erosion speed :math:`\xi` and its vertical behavior. The derivations below are for an erosion model with :math:`\left|\tan\beta\right|^\eta`, :math:`\eta=3/2`. Attributes: xiv_varphi_pxpz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\xi^{\downarrow} = - \dfrac{p_{x}^{\eta} \left(p_{x}^{2} + p_{z}^{2}\right)^{\tfrac{1}{2} - \tfrac{\eta}{2}} \varphi{\left(\mathbf{r} \right)}}{p_{z}}` px_xiv_varphi_eqn (:class:`~sympy.core.relational.Equality`): :math:`\left(\xi^{\downarrow}\right)^{2}` :math:`\left(p_{x}^{2} p_{x}^{2 \eta} \left(p_{x}^{2} \ + \frac{1}{\left(\xi^{\downarrow}\right)^{2}}\right)^{- \eta} \varphi^{2}{\left(\mathbf{r} \right)} - 1 \ + \dfrac{p_{x}^{2 \eta} \left(p_{x}^{2} \ + \frac{1}{\left(\xi^{\downarrow}\right)^{2}}\right)^{- \eta} \varphi^{2}{\left(\mathbf{r} \right)}} {\left(\xi^{\downarrow}\right)^{2}}\right)` :math:`\times\,\,\,\left(p_{x}^{2} p_{x}^{2 \eta} \left(p_{x}^{2} \ + \frac{1}{\left(\xi^{\downarrow}\right)^{2}}\right)^{- \eta} \varphi^{2}{\left(\mathbf{r} \right)} + 1 \ + \dfrac{p_{x}^{2 \eta} \left(p_{x}^{2} \ + \frac{1}{\left(\xi^{\downarrow}\right)^{2}}\right)^{- \eta} \varphi^{2}{\left(\mathbf{r} \right)}} {\left(\xi^{\downarrow}\right)^{2}}\right) = 0` eta_dbldenom (:class:`~sympy.core.numbers.Integer`) : a convenience variable, recording double the denominator of :math:`\eta`, which must itself be a rational number """ logging.info("gme.core.xi.define_xi_related_eqns") eta_dbldenom = 2 * denom(self.eta_) self.xiv_varphi_pxpz_eqn = simplify( Eq( xiv, (self.xi_varphi_beta_eqn.rhs / cos(beta)).subs( e2d(self.tanbeta_pxpz_eqn)).subs( e2d(self.cosbeta_pxpz_eqn)).subs( e2d(self.sinbeta_pxpz_eqn)).subs({Abs(px): px}), )) xiv_eqn = self.xiv_varphi_pxpz_eqn px_xiv_varphi_eqn = simplify( Eq( (xiv_eqn.subs({Abs(px): px})).rhs**eta_dbldenom - xiv_eqn.lhs**eta_dbldenom, 0, ).subs(e2d(self.pz_xiv_eqn))) # HACK!! # Get rid of xiv**2 multiplier... # should be a cleaner way of doing this self.px_xiv_varphi_eqn = factor(Eq(px_xiv_varphi_eqn.lhs / xiv**2, 0)) self.eta__dbldenom = eta_dbldenom
def define_Hamiltons_eqns(self) -> None: r""" Define Hamilton's equations. Attributes: hamiltons_eqns (`Matrix`_): :math:`\left[\begin{matrix}\ \dot{r}^x = \varphi_0^{2} p_{x}^{2 \eta - 1} x_{1}^{- 4 \mu} \left(p_{x}^{2} + p_{z}^{2}\right)^{- \eta} \left(\eta p_{z}^{2} + p_{x}^{2}\right) \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)^{2}\\ \dot{r}^z = - \varphi_0^{2} p_{x}^{2 \eta} p_{z} x_{1}^{- 4 \mu} \left(\eta - 1\right) \left(p_{x}^{2} + p_{z}^{2}\right)^{- \eta} \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)^{2}\\ \dot{p}_x = 2 \mu \varphi_0^{2} p_{x}^{2 \eta} x_{1}^{- 4 \mu} \left(p_{x}^{2} + p_{z}^{2}\right)^{1 - \eta} \left(x_{1} - {r}^x\right)^{2 \mu - 1} \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)\\ \dot{p}_z = 0 \end{matrix}\right]` """ logging.info("gme.core.hamiltons.define_Hamiltons_eqns") self.hamiltons_eqns = Matrix(( self.rdotx_pxpz_eqn.rhs.subs(e2d(self.varphi_rx_eqn)), self.rdotz_pxpz_eqn.rhs.subs(e2d(self.varphi_rx_eqn)), self.pdotx_pxpz_eqn.rhs.subs(e2d(self.varphi_rx_eqn)), self.pdotz_pxpz_eqn.rhs.subs(e2d(self.varphi_rx_eqn)) # .subs({pdotz:pdotz_tfn}) ))
def define_p_eqns(self) -> None: r""" Define normal slowness :math:`p` and derive related equations. Attributes: p_covec_eqn (:class:`~sympy.core.relational.Equality`): :math:`\mathbf{\widetilde{p}} := [p_x, p_z]` px_p_beta_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_x = p \sin\beta` pz_p_beta_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_z = p \cos\beta` p_norm_pxpz_eqn (:class:`~sympy.core.relational.Equality`): :math:`p = \sqrt{p_x^2+p_z^2}` tanbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan\beta = -\dfrac{p_x}{p_z}` sinbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\sin\beta = \dfrac{p_x}{\sqrt{p_x^2+p_z^2}}` cosbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\cos\beta = \dfrac{-p_z}{\sqrt{p_x^2+p_z^2}}` pz_px_tanbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_z = -\dfrac{p_x}{\tan\beta}` px_pz_tanbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_x = -{p_z}{\tan\beta}` p_pz_cosbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`p = -\dfrac{p_z}{\cos\beta}` """ logging.info("gme.core.rp.define_p_eqns") self.p_covec_eqn = Eq(pcovec, Matrix([px, pz]).T) self.px_p_beta_eqn = Eq(px, p * sin(beta)) self.pz_p_beta_eqn = Eq(pz, -p * cos(beta)) self.p_norm_pxpz_eqn = Eq( trigsimp( sqrt(self.px_p_beta_eqn.rhs**2 + self.pz_p_beta_eqn.rhs**2)), (sqrt(self.px_p_beta_eqn.lhs**2 + self.pz_p_beta_eqn.lhs**2)), ) self.tanbeta_pxpz_eqn = Eq( simplify(-self.px_p_beta_eqn.rhs / self.pz_p_beta_eqn.rhs), -self.px_p_beta_eqn.lhs / self.pz_p_beta_eqn.lhs, ) self.sinbeta_pxpz_eqn = Eq( sin(beta), solve(self.px_p_beta_eqn, sin(beta))[0].subs(e2d(self.p_norm_pxpz_eqn)), ) self.cosbeta_pxpz_eqn = Eq( cos(beta), solve(self.pz_p_beta_eqn, cos(beta))[0].subs(e2d(self.p_norm_pxpz_eqn)), ) self.pz_px_tanbeta_eqn = Eq(pz, solve(self.tanbeta_pxpz_eqn, pz)[0]) self.px_pz_tanbeta_eqn = Eq(px, solve(self.tanbeta_pxpz_eqn, px)[0]) self.p_pz_cosbeta_eqn = Eq(p, solve(self.pz_p_beta_eqn, p)[0])
def define_z_eqns(self) -> None: r""" Form a polynomial-type ODE in $\hat{z}(\hat{x})$. Attributes: dzdx_Ci_polylike_eqn """ logging.info("gme.core.profile.define_z_eqns") tmp_eqn = Eq( (xiv / varphi_r(rvec)), solve( simplify( self.pz_varphi_beta_eqn.subs(e2d(self.pz_xiv_eqn)).subs( {Abs(sin(beta)): sin(beta)})), xiv, )[0] / varphi_r(rvec), ) self.xiv_eqn = tmp_eqn.subs({ sin(beta): sqrt(1 - cos(beta)**2) }).subs({cos(beta): sqrt(1 / (1 + tan(beta)**2))}) self.xvi_abs_eqn = factor( Eq(self.xiv_eqn.lhs**4, (self.xiv_eqn.rhs)**4)) self.dzdx_polylike_eqn = self.xvi_abs_eqn.subs({tan(beta): dzdx}) self.dzdx_Ci_polylike_prelim_eqn = (expand_power_base( self.dzdx_polylike_eqn.subs(e2d(self.varphi_rx_eqn)).subs( e2d(self.varphi0_Lc_xiv0_Ci_eqn)).subs({ xiv: xiv_0 }).subs({ varepsilon: varepsilonhat * Lc }).subs({ rx: xhat * Lc }).subs({ (Lc * varepsilonhat - Lc * xhat + Lc): (Lc * (varepsilonhat - xhat + 1)) }))).subs({Abs(dzdx): dzdx}) self.dzdx_Ci_polylike_eqn = Eq( self.dzdx_Ci_polylike_prelim_eqn.rhs * ((dzdx**2 + 1)**(2 * eta)) - self.dzdx_Ci_polylike_prelim_eqn.lhs * ((dzdx**2 + 1)**(2 * eta)), 0, ).subs({pzhat_0: 1 / xivhat_0})
def postprocessing(self, spline_order: int = 2, extrapolation_mode: int = 0) -> None: """ Process the results of ODE integrations. Supplements the standard set of array generations. Args: spline_order: optional order of spline interpolation to be used when resampling along the profile at regular x intervals extrapolation_mode: optionally extrapolate (1) or don't extrapolate (1) at the end of the interpolation span """ logging.info("gme.core.time_invariant.postprocessing") super().postprocessing(spline_order=spline_order, extrapolation_mode=extrapolation_mode) xiv0_ = float((xiv_0 / xih_0).subs(e2d(self.gmeq.xiv0_xih0_Ci_eqn))) self.beta_vt_array = np.arctan( (self.rdotz_array + xiv0_) / self.rdotx_array) self.beta_vt_interp = InterpolatedUnivariateSpline( self.rx_array, self.beta_vt_array, k=spline_order, ext=extrapolation_mode, ) self.beta_vt_error_interp = (lambda x_: 100 * (self.beta_vt_interp( x_) - self.beta_p_interp(x_)) / self.beta_p_interp(x_)) (self.x_array, self.h_array) = [np.empty_like(self.t_array) for idx in [0, 1]] self.rays: List = [] for i in range(0, len(self.t_array), 1): if i < len(self.t_array): self.rays += [ np.array([ self.rx_array[:i + 1], self.rz_array[:i + 1] + self.t_array[i] * xiv0_, ]) ] self.x_array[i] = self.rx_array[i] self.h_array[i] = self.rz_array[i] + self.t_array[i] * xiv0_ self.h_interp: Callable = InterpolatedUnivariateSpline( self.x_array, self.h_array, k=spline_order, ext=extrapolation_mode) dhdx_interp: Callable = InterpolatedUnivariateSpline( self.x_array, self.h_array, k=spline_order, ext=extrapolation_mode).derivative() self.beta_ts_interp = lambda x_: np.arctan(dhdx_interp(x_)) self.dhdx_array: np.ndarray = dhdx_interp(self.x_array) self.beta_ts_array: np.ndarray = self.beta_ts_interp(self.x_array) self.beta_ts_error_interp: Callable = ( lambda x_: 100 * (self.beta_ts_interp(x_) - self.beta_p_interp(x_) ) / self.beta_p_interp(x_))
def initial_conditions( self, t_lag: float = 0, xiv_0_: float = 0, ) -> Tuple[float, float, float, float]: """Initialize.""" rz0_: float = 0 rx0_: float = 0 # HACK: poly_px_xiv0_eqn not actually defined... (px0_, pz0_) = pxpz0_from_xiv0(self.parameters, self.gmeq.pz_xiv_eqn, self.gmeq.poly_px_xiv0_eqn) print(type(pz0_)) return (rz0_, rx0_, px0_, pz0_.subs(e2d(self.gmeq.xiv0_xih0_Ci_eqn)))
def __init__( self, gmeq: Equations, grid_res: int = 301, dpi: int = 100, font_size: int = 11, ) -> None: r"""Initialize: constructor method.""" # Default construction super().__init__(dpi, font_size) self.H_Ci_eqn: Eq = gmeq.H_Ci_eqn self.degCi_H0p5_eqn: Eq = gmeq.degCi_H0p5_eqn Lc_varphi0_xih0_Ci_eqn: Eq = Eq( Lc, solve(gmeq.xih0_Lc_varphi0_Ci_eqn.subs({}), Lc)[0]) self.gstarhat_eqn = Eq( gstarhat, (simplify( gmeq.gstar_varphi_pxpz_eqn.rhs.subs(e2d( gmeq.varphi_rx_eqn)).subs(e2d(gmeq.px_pxhat_eqn)).subs( e2d(gmeq.pz_pzhat_eqn)).subs(e2d( gmeq.rx_rxhat_eqn)).subs( e2d(gmeq.varepsilon_varepsilonhat_eqn)).subs( e2d(Lc_varphi0_xih0_Ci_eqn)))) / xih_0**2, ) # Mesh grids for px-pz and rx-px space slicing plots self.grid_array: np.ndarray = np.linspace(0, 1, grid_res) self.grid_array[self.grid_array == 0.0] = 1e-6 self.pxpzhat_grids: List[np.ndarray] = np.meshgrid(self.grid_array, -self.grid_array, sparse=False, indexing="ij") self.rxpxhat_grids: List[np.ndarray] = np.meshgrid(self.grid_array, self.grid_array, sparse=False, indexing="ij")
def define_px_poly_eqn( self, eta_choice: Rational = None, do_ndim: bool = False ) -> None: r""" Define :math:`p_x` polynomial. TODO: remove ref to xiv_0 Define polynomial form of function combining normal-slowness covector components :math:`(p_x,p_z)` (where the latter is given in terms of the vertical erosion rate :math:`\xi^{\downarrow} = -\dfrac{1}{p_z}`) and the erosion model flow component :math:`\varphi(\mathbf{r})` Args: eta_choice (:class:`~sympy.core.numbers.Rational`): value of :math:`\eta` to use instead value given at instantiation; otherwise the latter value is used Attributes: poly_px_xiv_varphi_eqn (:class:`~sympy.polys.polytools.Poly`): :math:`\operatorname{Poly}{\left( \left(\xi^{\downarrow}\right)^{4} \varphi^{4}{\left(\mathbf{r} \right)} p_{x}^{6} - \left(\xi^{\downarrow}\right)^{4} p_{x}^{2} - \left(\xi^{\downarrow}\right)^{2}, p_{x}, domain=\mathbb{Z}\left[\varphi{\left(\mathbf{r} \right)}, \xi^{\downarrow}\right] \right)}` poly_px_xiv_eqn (:class:`~sympy.core.relational.Equality`): :math:`\varphi_0^{4} \left(\xi^{\downarrow{0}}\right)^{4} p_{x}^{6} \left(\varepsilon + \left(\frac{x_{1} - {r}^x}{x_{1}}\right)^{2 \mu}\right)^{4} - \left(\xi^{\downarrow{0}}\right)^{4} p_{x}^{2} - \left(\xi^{\downarrow{0}}\right)^{2} = 0` """ logging.info(f"gme.core.pxpoly.define_px_poly_eqn (ndim={do_ndim})") if do_ndim: # Non-dimensionalized version varphi0_solns = solve( self.sinCi_xih0_eqn.subs({eta: eta_choice}), varphi_0 ) varphi0_eqn = Eq(varphi_0, varphi0_solns[0]) if eta_choice is not None and eta_choice <= 1: tmp_eqn = separatevars( simplify( self.px_xiv_varphi_eqn.subs({eta: eta_choice}) .subs({varphi_r(rvec): self.varphi_rxhat_eqn.rhs}) .subs(e2d(self.px_pxhat_eqn)) .subs(e2d(varphi0_eqn)) ) ) self.poly_pxhat_xiv_eqn = simplify( Eq( ( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs) ) / xiv ** 2, 0, ) ) self.poly_pxhat_xiv0_eqn = self.poly_pxhat_xiv_eqn.subs( {xiv: xiv_0} ).subs(e2d(self.xiv0_xih0_Ci_eqn)) else: tmp_eqn = separatevars( simplify( self.px_xiv_varphi_eqn.subs({eta: eta_choice}) .subs({varphi_r(rvec): self.varphi_rxhat_eqn.rhs}) .subs(e2d(self.px_pxhat_eqn)) .subs(e2d(varphi0_eqn)) ) ) self.poly_pxhat_xiv_eqn = simplify( Eq( ( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs) ) / xiv ** 2, 0, ) ) self.poly_pxhat_xiv0_eqn = simplify( Eq( self.poly_pxhat_xiv_eqn.lhs.subs({xiv: xiv_0}).subs( e2d(self.xiv0_xih0_Ci_eqn) ) / xih_0 ** 2, 0, ) ) else: # Dimensioned version tmp_eqn = simplify(self.px_xiv_varphi_eqn.subs({eta: eta_choice})) if eta_choice is not None and eta_choice <= 1: self.poly_px_xiv_varphi_eqn = poly(tmp_eqn.lhs, px) else: self.poly_px_xiv_varphi_eqn = poly( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs), px ) self.poly_px_xiv_eqn = Eq( self.poly_px_xiv_varphi_eqn.subs(e2d(self.varphi_rx_eqn)), 0 )
def prep_geodesic_eqns(self, parameters: Dict = None): r""" Define geodesic equations. Args: parameters: dictionary of model parameter values to be used for equation substitutions Attributes: gstar_ij_tanbeta_mat (`Matrix`_): :math:`\dots` g_ij_tanbeta_mat (`Matrix`_): :math:`\dots` tanbeta_poly_eqn (:class:`~sympy.core.relational.Equality`): :math:`\dots` where :math:`a := \tan\alpha` tanbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dots` where :math:`a := \tan\alpha` gstar_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` gstar_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` g_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g[1,1] = \dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g[1,1] =\dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat_lambdified (function) : lambdified version of `g_ij_mat` gstar_ij_mat_lambdified (function) : lambdified version of `gstar_ij_mat` """ logging.info("gme.core.geodesic.prep_geodesic_eqns") self.gstar_ij_tanbeta_mat = None self.g_ij_tanbeta_mat = None self.tanbeta_poly_eqn = None self.tanbeta_eqn = None self.gstar_ij_tanalpha_mat = None self.gstar_ij_mat = None self.g_ij_tanalpha_mat = None self.g_ij_mat = None self.g_ij_mat_lambdified = None self.gstar_ij_mat_lambdified = None mu_eta_sub = {mu: self.mu_, eta: self.eta_} # if parameters is None: return H_ = self.H_eqn.rhs.subs(mu_eta_sub) # Assume indexing here ranges in [1,2] def p_i_lambda(i): return [px, pz][i - 1] # r_i_lambda = lambda i: [rx, rz][i-1] # rdot_i_lambda = lambda i: [rdotx, rdotz][i-1] def gstar_ij_lambda(i, j): return simplify( Rational(2, 2) * diff(diff(H_, p_i_lambda(i)), p_i_lambda(j))) gstar_ij_mat = Matrix([ [gstar_ij_lambda(1, 1), gstar_ij_lambda(2, 1)], [gstar_ij_lambda(1, 2), gstar_ij_lambda(2, 2)], ]) gstar_ij_pxpz_mat = gstar_ij_mat.subs({varphi_r(rvec): varphi}) g_ij_pxpz_mat = gstar_ij_mat.inv().subs({varphi_r(rvec): varphi}) cosbeta_eqn = Eq(cos(beta), 1 / sqrt(1 + tan(beta)**2)) sinbeta_eqn = Eq(sin(beta), sqrt(1 - 1 / (1 + tan(beta)**2))) sintwobeta_eqn = Eq(sin(2 * beta), cos(beta)**2 - sin(beta)**2) self.gstar_ij_tanbeta_mat = expand_trig( simplify(gstar_ij_pxpz_mat.subs(e2d( self.px_pz_tanbeta_eqn)))).subs(e2d(cosbeta_eqn)) self.g_ij_tanbeta_mat = expand_trig( simplify(g_ij_pxpz_mat.subs(e2d(self.px_pz_tanbeta_eqn)))).subs( e2d(cosbeta_eqn)) tanalpha_beta_eqn = self.tanalpha_beta_eqn.subs(mu_eta_sub) tanbeta_poly_eqn = Eq( numer(tanalpha_beta_eqn.rhs) - tanalpha_beta_eqn.lhs * denom(tanalpha_beta_eqn.rhs), 0, ).subs({tan(alpha): ta}) tanbeta_eqn = Eq(tan(beta), solve(tanbeta_poly_eqn, tan(beta))[0]) self.tanbeta_poly_eqn = tanbeta_poly_eqn self.tanbeta_eqn = tanbeta_eqn # Replace all refs to beta with refs to alpha self.gstar_ij_tanalpha_mat = (self.gstar_ij_tanbeta_mat.subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.gstar_ij_mat = (self.gstar_ij_tanalpha_mat.subs({ ta: tan(alpha) }).subs(e2d(self.tanalpha_rdot_eqn)).subs( e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_tanalpha_mat = (expand_trig(self.g_ij_tanbeta_mat).subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.g_ij_mat = (self.g_ij_tanalpha_mat.subs({ ta: rdotz / rdotx }).subs(e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.g_ij_mat, "numpy") self.gstar_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.gstar_ij_mat, "numpy")
def nondimensionalize(self) -> None: r""" Non-dimensionalization. Non-dimensionalize variables, Hamiltonian, and Hamilton's equations; define dimensionless channel incision number :math:`\mathsf{Ci}`. """ logging.info("gme.core.ndim.nondimensionalize") varsub: Dict = {} self.rx_rxhat_eqn = Eq(rx, Lc * rxhat) self.rz_rzhat_eqn = Eq(rz, Lc * rzhat) self.varepsilon_varepsilonhat_eqn = Eq(varepsilon, Lc * varepsilonhat) self.varepsilonhat_varepsilon_eqn = Eq( varepsilonhat, solve(self.varepsilon_varepsilonhat_eqn, varepsilonhat)[0], ) self.varphi_rxhat_eqn = Eq( varphi_rxhat_fn(rxhat), factor( self.varphi_rx_eqn.rhs.subs(e2d(self.rx_rxhat_eqn)).subs( e2d(self.varepsilon_varepsilonhat_eqn)).subs(varsub)), ) self.xi_rxhat_eqn = simplify( self.xi_varphi_beta_eqn.subs({ varphi_r(rvec): varphi_rxhat_fn(rxhat) }).subs(e2d(self.varphi_rxhat_eqn))) self.xih0_beta0_eqn = simplify( Eq( xih_0, (self.xi_rxhat_eqn.rhs / sin(beta_0)).subs( e2d(self.varphi_rx_eqn)).subs({ Abs(sin(beta)): sin(beta_0) }).subs({ rxhat: 0 }).subs(varsub), )) self.xiv0_beta0_eqn = simplify( Eq( xiv_0, (self.xi_rxhat_eqn.rhs / cos(beta_0)).subs( e2d(self.varphi_rx_eqn)).subs({ Abs(sin(beta)): sin(beta_0) }).subs({ rxhat: 0 }).subs(varsub), )) self.xih0_xiv0_beta0_eqn = Eq( (xih_0), xiv_0 * simplify( (xih_0 / xiv_0).subs(e2d(self.xiv0_beta0_eqn)).subs( e2d(self.xih0_beta0_eqn))), ) self.xih_xiv_tanbeta_eqn = Eq(xih, xiv / tan(beta)) self.xiv_xih_tanbeta_eqn = Eq(xiv, solve(self.xih_xiv_tanbeta_eqn, xiv)[0]) # Eq(xiv, xih*tan(beta)) self.th0_xih0_eqn = Eq(th_0, (Lc / xih_0)) self.tv0_xiv0_eqn = Eq(tv_0, (Lc / xiv_0)) self.th0_beta0_eqn = factor( simplify(self.th0_xih0_eqn.subs(e2d(self.xih0_beta0_eqn)))) self.tv0_beta0_eqn = simplify( self.tv0_xiv0_eqn.subs(e2d(self.xiv0_beta0_eqn))) self.t_that_eqn = Eq(t, th_0 * that) self.px_pxhat_eqn = Eq(px, pxhat / xih_0) self.pz_pzhat_eqn = Eq(pz, pzhat / xih_0) self.pzhat_xiv_eqn = Eq( pzhat, solve(self.pz_xiv_eqn.subs(e2d(self.pz_pzhat_eqn)), pzhat)[0]) self.H_varphi_rxhat_eqn = factor( simplify( self.H_varphi_rx_eqn.subs(varsub).subs( e2d(self.varepsilon_varepsilonhat_eqn)).subs( e2d(self.rx_rxhat_eqn)).subs(e2d( self.px_pxhat_eqn)).subs(e2d(self.pz_pzhat_eqn)))) self.H_split = (2 * pxhat**(-2 * eta) * (pxhat**2 + pzhat**2)**(eta - 1) * (1 - rxhat + varepsilonhat)**(-4 * mu)) self.H_Ci_eqn = Eq( H, simplify(((sin(Ci))**(2 * (1 - eta)) / self.H_split).subs( e2d(self.H_varphi_rxhat_eqn))), ) self.degCi_H0p5_eqn = Eq( Ci, deg(solve(self.H_Ci_eqn.subs({H: Rational(1, 2)}), Ci)[0])) self.sinCi_xih0_eqn = Eq( sin(Ci), (sqrt( simplify((H * self.H_split).subs(e2d( self.H_varphi_rxhat_eqn)))))**(1 / (1 - eta)), ) self.Ci_xih0_eqn = Eq(Ci, asin(self.sinCi_xih0_eqn.rhs)) self.sinCi_beta0_eqn = Eq( sin(Ci), factor( simplify(self.sinCi_xih0_eqn.rhs.subs(e2d( self.xih0_beta0_eqn)))).subs({ sin(beta_0) * sin(beta_0)**(-eta): (sin(beta_0)**(1 - eta)) }).subs({ (sin(beta_0)**(1 - eta))**(-1 / (eta - 1)): sin(beta_0) }), ) self.Ci_beta0_eqn = Eq(Ci, asin(self.sinCi_beta0_eqn.rhs)) self.beta0_Ci_eqn = Eq(beta_0, solve(self.Ci_beta0_eqn, beta_0)[1]) self.rdotxhat_eqn = Eq(rdotxhat_thatfn(that), simplify(diff(self.H_Ci_eqn.rhs, pxhat))) self.rdotzhat_eqn = Eq(rdotzhat_thatfn(that), simplify(diff(self.H_Ci_eqn.rhs, pzhat))) self.pdotxhat_eqn = Eq(pdotxhat_thatfn(that), simplify(-diff(self.H_Ci_eqn.rhs, rxhat))) self.pdotzhat_eqn = Eq(pdotzhat_thatfn(that), simplify(-diff(self.H_Ci_eqn.rhs, rzhat))) self.xih0_Ci_eqn = factor( self.xih0_beta0_eqn.subs(e2d(self.beta0_Ci_eqn))) # .subs({varepsilonhat:0}) self.xih0_Lc_varphi0_Ci_eqn = self.xih0_Ci_eqn self.xiv0_xih0_Ci_eqn = self.xiv_xih_tanbeta_eqn.subs({ xiv: xiv_0, xih: xih_0, beta: beta_0 }).subs(e2d(self.beta0_Ci_eqn)) # .subs({varepsilonhat:0}) self.xiv0_Lc_varphi0_Ci_eqn = simplify( self.xiv0_xih0_Ci_eqn.subs(e2d(self.xih0_Lc_varphi0_Ci_eqn))) self.varphi0_Lc_xiv0_Ci_eqn = Eq( varphi_0, solve(self.xiv0_Lc_varphi0_Ci_eqn, varphi_0)[0]).subs({Abs(cos(Ci)): cos(Ci)}) self.ratio_xiv0_xih0_eqn = Eq(xiv_0 / xih_0, (xiv_0 / xih_0).subs( e2d(self.xiv0_xih0_Ci_eqn)))
def define_tanbeta_eqns(self) -> None: r""" Define equations for surface tilt angle :math:`\beta`. Attributes: tanbeta_alpha_eqns (list) : :math:`\left[ \tan{\left(\beta \right)} \ = \dfrac{\eta - \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}, \tan{\left(\beta \right)} = \dfrac{\eta + \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}\right]` tanbeta_alpha_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{\eta - \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}` tanalpha_ext_eqns (list) : :math:`\left[ \tan{\left(\alpha_c \right)} = - \frac{\sqrt{\eta - 2 + \frac{1}{\eta}}}{2}, \tan{\left(\alpha_c \right)} = \frac{\sqrt{\eta - 2 + \frac{1}{\eta}}}{2}\right]` tanalpha_ext_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\alpha_c \right)} = \dfrac{\eta - 1}{2 \sqrt{\eta}}` tanbeta_crit_eqns (list) : :math:`\left[ \tan{\left(\beta_c \right)} = - \dfrac{\eta - 1}{\sqrt{\eta - 2 + \frac{1}{\eta}}}, \tan{\left(\beta_c \right)} = \dfrac{\eta - 1}{\sqrt{\eta - 2 + \frac{1}{\eta}}}\right]` tanbeta_crit_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta_c \right)} = \sqrt{\eta}` tanbeta_rdotxz_pz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{v^{z} - \frac{1}{p_{z}}}{v^{x}}` tanbeta_rdotxz_xiv_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{\xi^{\downarrow} + v^{z}}{v^{x}}` """ logging.info("gme.core.angles.define_tanbeta_eqns") # eta_sub = {eta: self.eta_} if self.eta_ == 1 and self.beta_type == "sin": logging.info(r"Cannot compute all $\beta$ equations " + r"for $\sin\beta$ model and $\eta=1$") return solns = solve(self.tanalpha_beta_eqn.subs({tan(alpha): ta}), tan(beta)) self.tanbeta_alpha_eqns = [ Eq(tan(beta), soln.subs({ta: tan(alpha)})) for soln in solns ] # Bit of a hack - extracts the square root term in tan(beta) # as a fn of tan(alpha), which then gives the critical alpha root_terms = [[ arg_ for arg__ in arg_.args if isinstance(arg__, sy.core.power.Pow) or isinstance(arg_, sy.core.power.Pow) ] for arg_ in numer(self.tanbeta_alpha_eqns[0].rhs).args if isinstance(arg_, (sy.core.mul.Mul, sy.core.power.Pow)) ] self.tanalpha_ext_eqns = [ Eq(tan(alpha_ext), soln) for soln in solve(Eq(root_terms[0][0], 0), tan(alpha)) ] tac_lt1 = simplify( (factor(simplify(self.tanalpha_ext_eqns[0].rhs * sqrt(eta))) / sqrt(eta)).subs({Abs(eta - 1): 1 - eta})) tac_gt1 = simplify( (factor(simplify(self.tanalpha_ext_eqns[1].rhs * sqrt(eta))) / sqrt(eta)).subs({Abs(eta - 1): eta - 1})) self.tanalpha_ext_eqn = Eq( tan(alpha_ext), Piecewise((tac_lt1, eta < 1), (tac_gt1, True))) self.tanbeta_crit_eqns = [ factor( tanbeta_alpha_eqn_.subs({ beta: beta_crit, alpha: alpha_ext }).subs(e2d(tanalpha_ext_eqn_))) for tanalpha_ext_eqn_, tanbeta_alpha_eqn_ in zip( self.tanalpha_ext_eqns, self.tanbeta_alpha_eqns) ] # This is a hack, because SymPy simplify can't handle it self.tanbeta_crit_eqn = Eq( tan(beta_crit), sqrt(simplify((self.tanbeta_crit_eqns[0].rhs)**2))) self.tanbeta_rdotxz_pz_eqn = Eq(tan(beta), (rdotz - 1 / pz) / rdotx) self.tanbeta_rdotxz_xiv_eqn = self.tanbeta_rdotxz_pz_eqn.subs( {pz: self.pz_xiv_eqn.rhs}) self.tanalpha_ext = float( N(self.tanalpha_ext_eqn.rhs.subs({eta: self.eta_}))) self.tanbeta_crit = float( N(self.tanbeta_crit_eqn.rhs.subs({eta: self.eta_})))
def define_varphi_related_eqns(self) -> None: r""" Define further equations related to normal slowness :math:`p`. Attributes: p_varphi_beta_eqn (`Equality`_): :math:`p = \dfrac{1}{\varphi(\mathbf{r})|\sin\beta|^\eta}` p_varphi_pxpz_eqn (`Equality`_): :math:`\sqrt{p_{x}^{2} + p_{z}^{2}} = \dfrac{\left( {\sqrt{p_{x}^{2} + p_{z}^{2}}} \right)^{\eta}} {\varphi{\left(\mathbf{r} \right)}{p_{x}}^\eta}` p_rx_pxpz_eqn (`Equality`_): :math:`\sqrt{p_{x}^{2} + p_{z}^{2}} = \dfrac{p_{x}^{- \eta} x_{1}^{2 \mu} \left(p_{x}^{2} + p_{z}^{2}\right)^{\frac{\eta}{2}}} {\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)}` p_rx_tanbeta_eqn (`Equality`_): :math:`\sqrt{p_{x}^{2} + \dfrac{p_{x}^{2}}{\tan^{2} {\left(\beta \right)}}} = \dfrac{p_{x}^{- \eta} x_{1}^{2 \mu} \left(p_{x}^{2} + \dfrac{p_{x}^{2}}{\tan^{2}{\left(\beta \right)}}\right)^{\frac{\eta}{2}}} {\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)}` px_beta_eqn (`Equality`_): :math:`p_{x} = \dfrac{p_{x}^{- \eta} x_{1}^{2 \mu} \left(p_{x}^{2} + \dfrac{p_{x}^{2}} {\tan^{2}{\left(\beta \right)}}\right)^{\frac{\eta}{2}} \sin{\left(\beta \right)}}{\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)}` pz_beta_eqn (`Equality`_): :math:`p_{z} = - \dfrac{p_{x}^{- \eta} x_{1}^{2 \mu} \left(p_{x}^{2} + \dfrac{p_{x}^{2}}{\tan^{2} {\left(\beta \right)}}\right)^{\frac{\eta}{2}} \cos{\left(\beta \right)}} {\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(x_{1} - {r}^x\right)^{2 \mu}\right)}` xiv_pxpz_eqn (`Equality`_): :math:`\xi^{\downarrow} = \dfrac{p_z}{p_x^{2} + p_z^{2}}` px_varphi_beta_eqn (`Equality`_): :math:`p_{x} = \dfrac{\sin{\left(\beta \right)} \left|{\sin{\left(\beta \right)}}\right|^{- \eta}} {\varphi{\left(\mathbf{r} \right)}}` pz_varphi_beta_eqn (`Equality`_): :math:`p_{z} = - \dfrac{\cos{\left(\beta \right)} \left|{\sin{\left(\beta \right)}}\right|^{- \eta}} {\varphi{\left(\mathbf{r} \right)}}` px_varphi_rx_beta_eqn (`Equality`_): :math:`p_{x} = \dfrac{\sin{\left(\beta \right)} \left|{\sin{\left(\beta \right)}}\right|^{- \eta}} {\varphi_0 \left(\varepsilon + \left(\dfrac{x_{1} - {r}^x}{x_{1}}\right)^{2 \mu}\right)}` pz_varphi_rx_beta_eqn (`Equality`_): :math:`p_{z} = - \dfrac{\cos{\left(\beta \right)} \left|{\sin{\left(\beta \right)}}\right|^{- \eta}} {\varphi_0 \left(\varepsilon + \left(\dfrac{x_{1} - {r}^x}{x_{1}}\right)^{2 \mu}\right)}` """ logging.info("gme.core.varphi.define_varphi_related_eqns") self.p_varphi_beta_eqn = self.p_xi_eqn.subs( e2d(self.xi_varphi_beta_eqn)) # Note force px >= 0 self.p_varphi_pxpz_eqn = (self.p_varphi_beta_eqn.subs( e2d(self.tanbeta_pxpz_eqn)).subs(e2d(self.sinbeta_pxpz_eqn)).subs( e2d(self.p_norm_pxpz_eqn)).subs({Abs(px): px})) # Don't do this simplification step because it messes up # later calc of rdotz_on_rdotx_eqn etc # if self.eta_==1 and self.beta_type=='sin': # self.p_varphi_pxpz_eqn \ # = simplify(Eq(self.p_varphi_pxpz_eqn.lhs/sqrt(px**2+pz**2), # self.p_varphi_pxpz_eqn.rhs/sqrt(px**2+pz**2))) self.p_rx_pxpz_eqn = simplify( self.p_varphi_pxpz_eqn.subs( {varphi_r(rvec): self.varphi_rx_eqn.rhs})) self.p_rx_tanbeta_eqn = self.p_rx_pxpz_eqn.subs( {pz: self.pz_px_tanbeta_eqn.rhs}) self.px_beta_eqn = Eq(px, self.p_rx_tanbeta_eqn.rhs * sin(beta)) self.pz_beta_eqn = Eq(pz, -self.p_rx_tanbeta_eqn.rhs * cos(beta)) self.xiv_pxpz_eqn = simplify( Eq(xiv, -cos(beta) / p).subs({ cos(beta): 1 / sqrt(1 + tan(beta)**2) }).subs({ self.tanbeta_pxpz_eqn.lhs: self.tanbeta_pxpz_eqn.rhs }).subs({self.p_norm_pxpz_eqn.lhs: self.p_norm_pxpz_eqn.rhs})) tmp = self.xi_varphi_beta_eqn.subs(e2d(self.xi_p_eqn)).subs( e2d(self.p_pz_cosbeta_eqn)) self.pz_varphi_beta_eqn = Eq(pz, solve(tmp, pz)[0]) tmp = self.pz_varphi_beta_eqn.subs(e2d(self.pz_px_tanbeta_eqn)) self.px_varphi_beta_eqn = Eq(px, solve(tmp, px)[0]) self.pz_varphi_rx_beta_eqn = self.pz_varphi_beta_eqn.subs( e2d(self.varphi_rx_eqn)) self.px_varphi_rx_beta_eqn = self.px_varphi_beta_eqn.subs( e2d(self.varphi_rx_eqn))
def set_ibc_eqns(self) -> None: r""" Define initial condition equations. Attributes: rz_initial_eqn (:class:`~sympy.core.relational.Equality`): :math:`{r}^z = \dfrac{h_{0} \tanh{\left(\frac{ \kappa_\mathrm{h} {r}^x}{x_{1}} \right)}}{\tanh{\left( \frac{\kappa_\mathrm{h}}{x_{1}} \right)}}` tanbeta_initial_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{\kappa_\mathrm{h} h_{0} \left(1 - \tanh^{2}{\left(\frac{\kappa_ \mathrm{h} x}{x_{1}} \right)}\right)}{x_{1} \tanh{\left(\frac{\kappa_\mathrm{h}}{x_{1}} \right)}}` p_initial_eqn (:class:`~sympy.core.relational.Equality`): :math:`p = \dfrac{x_{1}^{2 \mu} \left|{\sin{\left(\beta \right)}}\right|^{- \eta}}{\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(- x + x_{1}\right)^{2 \mu}\right)}` px_initial_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_{x} = \dfrac{\kappa_\mathrm{h} h_{0} x_{1}^{2 \mu} \left(\dfrac{1}{\kappa_\mathrm{h} h_{0} \left|{\tanh^{2}{ \left(\frac{\kappa_\mathrm{h} x}{x_{1}} \right)} - 1}\right|} \right)^{\eta} \left(\kappa_\mathrm{h}^{2} h_{0}^{2} \left(\tanh^{2}{\left(\frac{\kappa_\mathrm{h} x}{x_{1}} \right)} - 1\right)^{2} + x_{1}^{2} \tanh^{2}{\left( \frac{\kappa_\mathrm{h}}{x_{1}} \right)}\right)^{\frac{\eta}{2} - \frac{1}{2}} \left|{\tanh^{2}{\left(\frac{\kappa_ \mathrm{h} x}{x_{1}} \right)} - 1}\right|}{\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(- x + x_{1}\right)^{2 \mu}\right)}` pz_initial_eqn (:class:`~sympy.core.relational.Equality`): :math:`p_{z} = - \dfrac{x_{1}^{2 \mu + 1} \left(\dfrac{1}{\kappa_\mathrm{h} h_{0} \left|{\tanh^{2}{ \left(\frac{\kappa_\mathrm{h} x}{x_{1}} \right)} - 1} \right|}\right)^{\eta} \left(\kappa_\mathrm{h}^{2} h_{0}^{2} \left(\tanh^{2}{\left(\frac{\kappa_\mathrm{h} x}{x_{1}} \right)} - 1\right)^{2} + x_{1}^{2} \tanh^{2}{\left(\frac{ \kappa_\mathrm{h}}{x_{1}} \right)}\right)^{\frac{\eta}{2} - \frac{1}{2}} \tanh{\left(\frac{\kappa_\mathrm{h}}{x_{1}} \right)}}{\varphi_0 \left(\varepsilon x_{1}^{2 \mu} + \left(- x + x_{1}\right)^{2 \mu}\right)}` """ logging.info("gme.core.ibc.set_ibc_eqns") cosbeta_eqn = Eq(cos(beta), 1 / sqrt(1 + tan(beta)**2)) sinbeta_eqn = Eq(sin(beta), sqrt(1 - 1 / (1 + tan(beta)**2))) # sintwobeta_eqn = Eq(sin(2*beta), cos(beta)**2-sin(beta)**2) ibc_type = self.ibc_type self.rz_initial_eqn = self.boundary_eqns[ibc_type]["h"].subs({ h: rz, x: rx }) self.tanbeta_initial_eqn = Eq( tan(beta), self.boundary_eqns[ibc_type]["gradh"].rhs) self.p_initial_eqn = simplify( self.p_varphi_beta_eqn.subs(e2d(self.varphi_rx_eqn)) # .subs({varphi_r(rvec):self.varphi_rx_eqn.rhs}) .subs({ self.tanbeta_initial_eqn.lhs: self.tanbeta_initial_eqn.rhs }).subs({rx: x})) self.px_initial_eqn = Eq( px, simplify((+self.p_initial_eqn.rhs * sin(beta)).subs( e2d(sinbeta_eqn)).subs(e2d(cosbeta_eqn)).subs({ tan(beta): self.tanbeta_initial_eqn.rhs, rx: x })), ) self.pz_initial_eqn = Eq( pz, simplify((-self.p_initial_eqn.rhs * cos(beta)).subs( e2d(sinbeta_eqn)).subs(e2d(cosbeta_eqn)).subs({ tan(beta): self.tanbeta_initial_eqn.rhs, rx: x })), )
def __init__( self, gmeq: Union[Equations, EquationsIdtx], pr: Parameters, sub_: Dict, varphi_: float = 1, ) -> None: """Initialize: constructor method.""" super().__init__() self.H_parametric_eqn = (Eq((2 * gmeq.H_eqn.rhs)**2, 1).subs({ varphi_r(rvec): varphi_, xiv: xiv_0 }).subs(sub_)) if pr.model.eta == Rational(3, 2): pz_min_eqn = Eq( pz_min, (solve( Eq( ((solve( Eq(4 * gmeq.H_eqn.rhs**2, 1).subs({varphi_r(rvec): varphi}), px**2, )[2]).args[0].args[0].args[0])**2, 0, ), pz**4, )[0])**Rational(1, 4), ) px_min_eqn = Eq( px_min, solve( simplify( gmeq.H_eqn.subs({ varphi_r(rvec): varphi }).subs({pz: pz_min_eqn.rhs})).subs({H: Rational(1, 2)}), px, )[0], ) tanbeta_max_eqn = Eq( tan(beta_max), ((px_min / pz_min).subs(e2d(px_min_eqn))).subs( e2d(pz_min_eqn)), ) self.tanbeta_max = float(N(tanbeta_max_eqn.rhs)) else: pz_min_eqn = Eq(pz_min, 0) px_min_eqn = Eq( px_min, sqrt( solve( Eq( (solve( Eq(4 * gmeq.H_eqn.rhs**2, 1).subs({varphi_r(rvec): varphi}), pz**2, )[:])[0], 0, ), px**2, )[1]), ) tanbeta_max_eqn = Eq(tan(beta_max), oo) self.tanbeta_max = 0.0 pz_min_ = round(float(N(pz_min_eqn.rhs.subs({varphi: varphi_}))), 8) px_H_solns = [ simplify(sqrt(soln)) for soln in solve(self.H_parametric_eqn, px**2) ] px_H_soln_ = [ soln for soln in px_H_solns if Abs(im(N(soln.subs({pz: 1})))) < 1e-10 ][0] self.px_H_lambda = lambdify([pz], simplify(px_H_soln_)) pz_max_ = 10**4 if pr.model.eta == Rational(3, 2) else 10**2 pz_array = -(10**np.linspace( np.log10(pz_min_ if pz_min_ > 0 else 1e-6), np.log10(pz_max_), 1000, )) px_array = self.px_H_lambda(pz_array) p_array = np.vstack([px_array, pz_array]).T tanbeta_crit = float(N(gmeq.tanbeta_crit_eqn.rhs)) self.p_infc_array = p_array[np.abs(p_array[:, 0] / p_array[:, 1]) < tanbeta_crit] self.p_supc_array = p_array[np.abs(p_array[:, 0] / p_array[:, 1]) >= tanbeta_crit] v_from_gstar_lambda_tmp = lambdify( (px, pz), N( gmeq.gstar_varphi_pxpz_eqn.subs({ varphi_r(rvec): varphi_ }).rhs * Matrix([px, pz])), ) self.v_from_gstar_lambda = lambda px_, pz_: (v_from_gstar_lambda_tmp( px_, pz_)).flatten() def v_lambda(pa): return np.array([(self.v_from_gstar_lambda(px_, pz_)) for px_, pz_ in pa]) self.v_infc_array = v_lambda(self.p_infc_array) self.v_supc_array = v_lambda(self.p_supc_array)