Skip to main content

algebraic manipulation - InverseSeries of multiple variables and multiple equations


CONTEXT


Let us consider a bit of the Universe in which we draw spheres



(see a high resolution image here). Astronomers have shown that the density within these spheres could be predicted quite accurately: here is the measured (in red) and predicted (in green) distribution of the density within 503 such spheres at half the age of the Universe: .


Our next purpose is to extend the theory to concentric two or more shells.


In practice, in order to estimate the mildly nonlinear cosmic density of the Universe within concentric shells, I need to find perturbatively the Legendre Transform of a function of two variables in a singular regime (see below).



ϕ(λ1,λ2)=LT(ψ(ρ1,ρ2))supρ1,ρ2[λ1ρ1+λ2ρ2ψ(ρ1,ρ2)]



which in turns involves inverting the system ρψ=λ(1)

for ρ1,ρ2 , and integrating for ϕ(λ1,λ2) the system λϕ=ρ.(2)
This can in principle be done perturbatively. In my context, it needs to be done in the regime where det|2ρψ|=0. I.e. I am interested in Taylor expanding the Legendre transform of ψ near a point (chosen to be zero for simplicity) where one of the eigenvalues of 2ρψ is zero. In physical terms it corresponds to the rare event tail of the density of the Universe in these shells, if you care to know!


ATEMPT


Following this question I know how to do invert (1) for ρ(λ) in 1D (one shell) for the regular


 nn = 3;

ρofλr = InverseSeries[Series[ψ'[ρ], {ρ, 0,nn}]] /. ρ -> λ /. ψ'[0] -> 0 /.
Derivative[n_][ψ][0] :> Subscript[ψ, n] // Normal

reg


(note the division by ψ''[0])


and the singular case (for which ψ''[0]=0)


 nn = 3;
ρofλs = InverseSeries[Series[ψ'[ρ], {ρ, 0,nn}]/. ψ''[0]-> 0] /. ρ -> λ /. ψ'[0] -> 0 /.
Derivative[n_][ψ][0] :> Subscript[ψ, n] // Normal


reg


note the square root. It is clear from this expansion that the Legendre transform, ϕ[λ] will have a very different algebraic form in the singular case compared to the regular case.


 ϕ[λ_]=Integrate[ρofλ,λ]

But this is not enough for concentric shells: I need to be able to carry out such Legendre transform when one coordinate is singular.


SOLUTION to first order and for the regular case only


The following works for the regular case only. Let us expand the first system


   nn=1;
eqn = Thread[{λ1, λ2} ==
Series[{Derivative[1, 0][ψ][ ρ1, ρ2],

Derivative[0, 1][ψ][ ρ1, ρ2]}, { ρ1, 0,
nn}, { ρ2, 0, nn}]] // Normal;

and reoder it in power of ϵ


  eqn2 = eqn /. 
Derivative[i_, j_][ψ][0,
0] -> ϵ^(i + j - 1) Derivative[i, j][ψ][0, 0] //
Series[#, {ϵ, 0, 1}] & // Simplify;

Solve for ρ1,ρ2



 sol = Solve[Normal[eqn2], { ρ1,  ρ2}][[1]] /. 
Derivative[n_, p_][ψ][__] :> Subscript[ψ, n, p] //
FullSimplify;

We can then integrate the system (2):


 eqn3 = {D[ϕ[λ1, λ2], λ1] == ρ1,D[ϕ[λ1, λ2], λ2] ==  ρ2} /. sol
ϕ[λ1, λ2]/. DSolve[eqn3,ϕ[λ1, λ2], {λ1, λ2}][[1, 1]] // Apart


But this is not good enough because I am interested in a singular expansion, i.e. near a point where the Jacobian 2ψρiρj has zero determinant! (when the above first order solution becomes singular because ψ02 ψ20 -ψ11^2 =0)



QUESTION



I am interested in doing this in 2D (or 3D...) for the singular case, i.e. when the Jacobian 2ρψ has one null eigenvalue.



The main difficulty is that InverseSeries does not work for series of two variables.


The gist of the problem is the following: assuming x1, x2 y1 and y2 are small, how does one invert pertubatively


 y1= x1+ x1^2 + x2^2 + x1 x2 + x2^3...
y2= x2^2 + x1^2 +x1 x2 + x1^3 +...

in order to write



 x1= y1+...
x2= sqrt(y2)+...

This might sound like a technical question, but the core of the problem is fairly general: how does one InverseSeries of multiple variables and multiple equations? in Mathematica. Any suggestions would be very welcome!



Answer



Algebraically, the way to construct the inverse of a series is straightforward. The basic iterative step is to add the next degree terms and solve for the coefficients.


If we have u=U(x,y), v=V(x,y), then we are looking for x=X(u,v), y=Y(u,v) such that u=U(X(u,v),Y(u,v)) and v=V(X(u,v),Y(u,v)) identically. If the coefficients of the partial series Xn(u,v)=nk=0ki=0ai,kiuivki,Yn(u,v)=nk=0ki=0bi,kiuivki

have been determined, then plug x=Xn(u,v)+n+1i=0ai,n+1iuivn+1i,y=Yn(u,v)+n+1i=0bi,n+1iuivn+1i
into u=U(X(u,v),Y(u,v)),v=V(X(u,v),Y(u,v))
and set the coefficients of the monomials uivj to zero and solve for the unknown a and b.


That's the inductive step, more or less, but how to get started? The original question assumes (justifiably -- by a translation, if necessary) that (0,0) is mapped to (0,0). If the linear terms form an invertible system, then the inductive step can be applied repeatedly up to the desired degree. In the case of the question, the assumptions are that the linear system is nonzero but degenerate (Ux0, Uy=0) and the second order system is parabolic, aligned in an independent direction (Uyy(0,0)0, Uxx=Uxy=0). In this case, the solutions will be power series in u, v.


The function series2DSolveParabolic constructs the series solution up to whatever degree desired. Notes on the code can be found below the example.


terms[poly_, deg_, vars_] := FromCoefficientRules[

Select[CoefficientRules[poly, vars], Total@First@# <= deg &], vars];

series2D[series2DData[f_, {x_, y_}, dataRules_], n_] :=
terms[Normal@Series[f[x, y], {x, 0, n}, {y, 0, n}] /. dataRules,
n, {x, y}];
series2D[series2DSolData[a_, {u_, v_}], n_] := Sum[u^i*v^(-i + k)*a[i, -i + k],
{k, 1, n}, {i, 0, k}];

solveCoeff[terms_, pat_] := Solve[Thread[terms == 0], Cases[terms, pat, Infinity]];


series2DSolveParabolic[{u_ == U0_series2DData, v_ == V0_series2DData}, {x_, y_}, deg_] :=
Module[{a, b, X0, Y0, r},
a[0, 0] = b[0, 0] = 0;
X0 = series2DSolData[a, {u, r}];
Y0 = series2DSolData[b, {u, r}];
Do[
solveCoeff[
DeleteCases[
Flatten[CoefficientList[#, {u, r}] & /@ {
u - terms[series2D[U0, n] /.

{x -> series2D[X0, n], y -> series2D[Y0, n]}, n, {u, r}],
r^2 - terms[series2D[V0, n + 1] /.
{x -> series2D[X0, n + 1], y -> series2D[Y0, n + 1]}, n + 1, {u, r}]}],
_?NumericQ], _a | _b] /. Rule -> Set,
{n, 1, deg}];

{x -> Sum[a[i, j - i] u^i v^((j - i)/2), {j, 0, deg}, {i, 0, j}],
y -> Sum[b[i, j - i] u^i v^((j - i)/2), {j, 0, deg}, {i, 0, j}]}
];


Example (a bit messy):


    series2DSolveParabolic[
{u == series2DData[U, {x, y}, {U[0, 0] -> 0, Derivative[0, 1][U][0, 0] -> 0}],
v == series2DData[V, {x, y},
{V[0, 0] -> 0, Derivative[1, 0][V][0, 0] -> 0,
Derivative[0, 1][V][0, 0] -> 0,
Derivative[1, 1][V][0, 0] -> 0,
Derivative[2, 0][V][0, 0] -> 0}]},
{x, y}, 2]


(* {x -> u/Derivative[1, 0][U][0, 0] -
(v*Derivative[0, 2][U][0, 0])/
(Derivative[0, 2][V][0, 0] * Derivative[1, 0][U][0, 0]) -
(Sqrt[2]*u*Sqrt[v] * Derivative[1, 1][U][0, 0]) /
(Sqrt[Derivative[0, 2][V][0, 0]] * Derivative[1, 0][U][0, 0]^2) -
(u^2 * Derivative[2, 0][U][0, 0]) / (2*Derivative[1, 0][U][0, 0]^3),
y -> (Sqrt[2]*Sqrt[v]) / Sqrt[Derivative[0, 2][V][0, 0]] -
(v * Derivative[0, 3][V][0, 0]) / (3*Derivative[0, 2][V][0, 0]^2) -
(u * Sqrt[v]*Derivative[1, 2][V][0, 0]) /
(Sqrt[2]*Derivative[0, 2][V][0, 0]^(3/2) * Derivative[1, 0][U][0, 0]) -

(u^2*Derivative[2, 1][V][0, 0]) /
(2 * Derivative[0, 2][V][0, 0]*Derivative[1, 0][U][0, 0]^2)} *)

{xu2U(2,0)(0,0)2U(1,0)(0,0)32uvU(1,1)(0,0)U(1,0)(0,0)2V(0,2)(0,0)+uU(1,0)(0,0)vU(0,2)(0,0)U(1,0)(0,0)V(0,2)(0,0),

yu2V(2,1)(0,0)2U(1,0)(0,0)2V(0,2)(0,0)uvV(1,2)(0,0)2U(1,0)(0,0)V(0,2)(0,0)3/2vV(0,3)(0,0)3V(0,2)(0,0)2+2vV(0,2)(0,0)}


Notes on the code:


terms[poly, deg, vars] -- return the terms of the polynomial whose total degree is at most deg


series2DData[f, {x, y}, dataRules] -- represents a series in the variables x and y, with conditions on the derivatives of f given in dataRules


series2DSolData[c, {x, y},] -- represents a series in the variables x and y with coefficients c[i, j].


series2D[ser, n] -- returns the n-th degree Taylor polynomial of the series ser; ser may be either series2DData or series2DSolData


solveCoeff[terms, pat] -- sets the terms equal to zero and solves for the coefficients represented by the pattern pat.



series2DSolveParabolic[{u == uSeries, v == vSeries}, vars, deg] solves the system of equations for power series of vars in terms of the variables {u, v} up to degree deg. Note that the equation are not really treated as equations. The variables u and v have to be symbols and be the left-hand sides. Note also that internally in the Do loop, r represents Sqrt[v], and that the exponent is off by one (goes up to n+1); this has to do with the recursive procedure starting with degree 1 in x and degree 2 in y.




Here's a function that will invert power series if the linear terms are nonsingular.


series2DSolve[{u_ == U0_series2DData, v_ == V0_series2DData}, {x_, y_}, deg_] :=
Module[{a, b, X0, Y0},
a[0, 0] = b[0, 0] = 0;
X0 = series2DSolData[a, {u, v}];
Y0 = series2DSolData[b, {u, v}];
Do[
solveCoeff[

DeleteCases[
Flatten[CoefficientList[#, {u, v}] & /@ {
u -> terms[series2D[U0, n] /. {x -> series2D[X0, n], y -> series2D[Y0, n]},
n, {u, v}],
v -> terms[series2D[V0, n] /. {x -> series2D[X0, n], y -> series2D[Y0, n]},
n, {u, v}]}],
_?NumericQ], _a | _b] /.
Rule -> Set,
{n, 1, deg}];


{x -> Sum[a[i, j - i] u^i v^(j - i), {j, 0, deg}, {i, 0, j}],
y -> Sum[b[i, j - i] u^i v^(j - i), {j, 0, deg}, {i, 0, j}]}
];

Example


f[x_, y_] := Log[1 + x];
g[x_, y_] := Sin[y];
series2DSolve[
{u == series2DData[f, {x, y}, {}],
v == series2DData[g, {x, y}, {}]},

{x, y}, 5]
(* {x -> u + u^2/2 + u^3/6 + u^4/24 + u^5/120, y -> v + v^3/6 + (3 v^5)/40} *)

Normal@Series[ArcSin[v], {v, 0, 6}]
(* v + v^3/6 + (3 v^5)/40 *)



The methods used are from basic algebra. There could be, there ought to be, or perhaps there are built-in functions to do some or all of the above.


Comments

Popular posts from this blog

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

What is and isn't a valid variable specification for Manipulate?

I have an expression whose terms have arguments (representing subscripts), like this: myExpr = A[0] + V[1,T] I would like to put it inside a Manipulate to see its value as I move around the parameters. (The goal is eventually to plot it wrt one of the variables inside.) However, Mathematica complains when I set V[1,T] as a manipulated variable: Manipulate[Evaluate[myExpr], {A[0], 0, 1}, {V[1, T], 0, 1}] (*Manipulate::vsform: Manipulate argument {V[1,T],0,1} does not have the correct form for a variable specification. >> *) As a workaround, if I get rid of the symbol T inside the argument, it works fine: Manipulate[ Evaluate[myExpr /. T -> 15], {A[0], 0, 1}, {V[1, 15], 0, 1}] Why this behavior? Can anyone point me to the documentation that says what counts as a valid variable? And is there a way to get Manpiulate to accept an expression with a symbolic argument as a variable? Investigations I've done so far: I tried using variableQ from this answer , but it says V[1...