Point 1: My mistake
First of all remove the Evaluate within my definition of f. This is not correct. It does not change the function values but the contour-plot. The plots now look like (To get the same colors for real and imaginary parts in both plots I added explicit colors cols={RGBColor[0.4, 0.7, 1], RGBColor[1, 0.5, 0]} for ContourStyle and PlotStyle):
Point 2: Strange table-values
I don't understand why your table does not show values like mine. Maybe executing a
Clear["Global'*"]
might help.
BTW: It is never a good idea to use symbols starting with uppercase letters. Your Va and En shoul better read va and en.
Point 3: Global function definition
For not repeating the definition of function f again and again, I define it as global now. (This could be simplified for avoiding the same calculations over and over again). You must execute this one times:
Clear[f];
f[Va_, En_] :=
Module[{Vb = 50000, a = 0.01, b = 0.02, c = 137.036, k, p, q, A, B,
H},
k = Sqrt[En^2 - c^4]/c;
p = Sqrt[(En + c^2 - Va)*(En - c^2 - Va)]/c;
q = Sqrt[(En + c^2 - Vb)*(En - c^2 - Vb)]/c;
A = Sqrt[(En - c^2)/(En + c^2)];
B = Sqrt[(En - c^2 - Vb)/(En + c^2 - Vb)];
H = Sqrt[(En - c^2 - Va)/(En + c^2 - Va)];
Simplify[
(E^(I*q*b)/(16*A^2*B*H)*
(((A + H)^2)*((A + B)^2*E^(2*I*(k*(a - b) - p*a)) - (A - B)^2*
E^(-2*I*(k*(a - b) - p*a))) + ((A - H)^2)*((A - B)^2*
E^(-2*I*(k*(a - b) + p*a)) - (A + B)^2*
E^(2*I*(k*(a - b) + p*a))) +
2*(A^2 - B^2)*(A^2 - H^2)*(E^(2*I*p*a) - E^(-2*I*p*a))))]
];
Our program now looks like:
If[True, Block[{En, Va, tab,
cols = {RGBColor[0.4, 0.7, 1], RGBColor[1, 0.5, 0]}},
(* Define function; f is defined globally *)
If[False, Print[f[Va, En]]];
(* Print a table with function-values *)
tab = Table[Column[Round[ReIm[f[Va, En]], 0.01], Center]
, {Va, 0, 50000, 5000}, {En, 30000, 70000, 4000}];
Print[Grid[Join[
{Prepend[Range[30000, 70000, 4000], "Va\\En:"]},
Join[Transpose[{Range[0, 50000, 5000]}], tab, 2]],
Dividers -> {{2 -> True}, {1 -> True, 2 -> True}}]];
(* Show real and imaginary part of function-values *)
Print[ContourPlot[{Re[f[Va, En]], Im[f[Va, En]]}, {Va, 0,
50000}, {En, 30000, 70000},
PlotRange -> All,
ContourStyle -> cols,
PlotPoints -> {50, 40}, MaxRecursion -> 2,
FrameLabel -> {"Va", "En"}, PlotLegends -> {"Re(f)", "Im(f)"}
]];
(* Show real and imaginary part of function-values in 3D *)
Print[Plot3D[{Re[f[Va, En]], Im[f[Va, En]]}, {Va, 0, 50000}, {En,
30000, 70000},
PlotRange -> {All, All, Automatic},
PlotStyle -> cols,
PlotPoints -> {50, 40}, MaxRecursion -> 2,
AxesLabel -> {"Va", "En"}, PlotLegends -> {"Re(f)", "Im(f)"}
]];
]];
Point 4: Your actual problem
If I understand you correctly, you are looking for the solution of Re[ f[va0, En] ] == h0 for any given value of va0 and h0.
First of all we redraw the contour- and 3D plots of the real part and add some more information on it including the desired va0 and h0 values.
In addition we draw another plot with the sections Re[ f[va0, En] ] of our function for the desired va0 values.
If[True, Block[{En, Va, va0s, cntVa0s, h0s, cntH0s, prVa = {0, 50000},
prEn = {30000, 70000}, prEnL = 6000, col},
(* Desired Va values and function heights *)
va0s = Range[First[prVa], Last[prVa], 10000];
cntVa0s = Length[va0s];
h0s = {-1, -0.5, -0.25, -0.125, -0.075, 0, 0.075, 0.125, 0.25, 0.5,
1}; cntH0s = Length[h0s];
(* Show real part Re(f) of function values *)
Print[ContourPlot[Re[f[Va, En]]
, {Va, First[prVa], Last[prVa]}, {En, First[prEn], Last[prEn]},
PlotRange -> All,
Contours -> h0s, ContourLabels -> True,
ColorFunction -> "TemperatureMap",
PerformanceGoal -> "Quality",
FrameLabel -> (Style[#, Black, Larger] & /@ {"Va", "En"}),
PlotLegends -> Automatic,
PlotLabel -> Style["Re[ f[Va, En] ] contour", Black, Bold],
Epilog -> {Darker[Green], Thin,
Line[{{#, First[prEn]}, {#, Last[prEn]}} & /@ va0s]}
]];
(* Show real part Re(f) of function values in 3D *)
Print[Plot3D[Re[f[Va, En]]
, {Va, First[prVa], Last[prVa]}, {En, First[prEn], Last[prEn]},
PlotRange -> {All, All, Automatic},
ColorFunction -> "TemperatureMap",
PerformanceGoal -> "Quality",
AxesLabel -> (Style[#, Black, Larger] & /@ {"Va", "En", "Re(f)"}),
PlotLegends -> Automatic,
PlotLabel -> Style["Re[ f[Va, En] ]", Black, Bold]
]];
(* Show sections through Re(f) at the points va0 *)
col[va_] :=
Hue[2/3 + (0 - 2/3)/(Last[prVa] - First[prVa])*(va - First[prVa])];
Print[Plot[Evaluate[Table[Re[f[va0, En]], {va0, va0s}]]
, {En, First[prEn], Last[prEn]},
PlotRange -> {prEn - {prEnL, 0}, Automatic},
AxesOrigin -> {First[prEn], 0},
PerformanceGoal -> "Quality",
PlotStyle -> (col[#] & /@ va0s),
Frame -> True,
FrameLabel -> (Style[#, Black, Larger] & /@ {"En",
"Re[f[va0, En]]"}),
PlotLegends -> (Style[Row[{"va0 = ", #}], 10] & /@ va0s),
PlotLabels ->
Placed[va0s, {Scaled[#/10], Above} & /@ Range[cntVa0s]],
PlotLabel ->
Style["Sections Re[ f[va0, En] ], va0 \[Element] va0s", Black,
Bold],
ImageSize -> Scaled[0.85], AspectRatio -> 5/4,
Epilog -> {Darker[Green], Thin,
Line[{{First[prEn] - prEnL, #}, {Last[prEn], #}} & /@ h0s],
Inset[
Style[Row[{"h0 = ", #}], 10, ![enter image description here][2]
Background -> White], {First[prEn] - prEnL/2, #}, {0,
0}] & /@ h0s}
]];
]];
Then we solve the equations Re[ f[va0, En] ] == h0 for some given values va0 an h0. We define a new global function r[Va_ ,En_ ] for the simplified real part Re[ f[va0, En] ].
Solve is not able to solve that, hence we use NSolve. But this does not terminate within reasonable time (Interrupt wit Alt+.).
So we try to find solutions with FindRoot, which takes an approximation per solution. We roughly lookup the approximations in the previous section-plot. They are given as an association
solApproxs = <| {va0,h0} -> {En01, En02, ...}, ... |>. For each {va0,h0}-pair there is a list with zero to n En-approximations. Note: I defined only some solution approximations, not all of them.
In the same way, we collect the solutions within an association
sols = <| {va0,h0} -> {En1, En2, ...}, ... |> for later use. For each {va0,h0}-pair there is a list with zero to n En-solutions.
Finally we draw our contour- and section plot again exactly like before, but with the solutions marked by points.
Clear[r];
r[Va_, En_] := Simplify[Re[f[Va, En]]];
If[True, Block[{test = False, En, Va, va0s, cntVa0s, h0s, cntH0s,
prVa = {0, 50000}, prEn = {30000, 70000}, prEnL = 6000,
solApproxs, approxs, sols, sol, col, va0},
(* Desired Va values and function heights *)
va0s = Range[First[prVa], Last[prVa], 10000];
cntVa0s = Length[va0s];
h0s = {-1, -0.5, -0.25, -0.125, -0.075, 0, 0.075, 0.125, 0.25, 0.5,
1}; cntH0s = Length[h0s];
(* From the plots take some approximations of the solutions for \
{va0,h0} *)
solApproxs = <|{50000, 1} -> {36000, 44000, 59000, 65000}, {50000,
0.5} -> {37000, 43000, 59000, 65000}, {50000, 0} -> {38000,
41000, 61000, 63000},
{20000, 0} -> {34000, 37000, 46000, 53000, 62000, 65000},
{10000, 1} -> {68000}, {10000, 0.5} -> {33000, 36000,
67000}, {10000, 0} -> {33000, 40000, 49000, 59000, 66000}|>;
(* Solve the equations Re[f[va0,En]] \[Equal]
h0 for given values va0 and h0. *)
(* Collect the solutions within sols *)
sols =
Association[
Flatten[Table[{va0, h0} -> {}, {va0, va0s}, {h0, h0s}]]];
Do[(* va0 *)
If[test && ! MemberQ[{50000, 20000, 10000}, va0], Continue[]];
Do[(* h0 *)
If[test && ! MemberQ[{1, 0.5, 0(*,-0.075*)}, h0], Continue[]];
Print[
Style[Row[{"Solving for va0 = ", va0, ", h0 = ", h0}], Blue,
Bold]];
(* sol=Solve[r[va0,En]\[Equal]h0,En]; does not work *)
(*sol=NSolve[r[va0,En]\[Equal]h0&&En\[Element]Reals&&First[
prEn]\[LessEqual]En\[LessEqual]Last[prEn],En,Complexes];
does not terminate *)
approxs = solApproxs[{va0, h0}];
If[MissingQ[approxs],
Print["No approximation known!"]
,
Do[(* approx *)
sol = FindRoot[r[va0, En] == h0, {En, approx}];
If[test, Echo[{approx, sol}, "{approx,sol}: "]];
AppendTo[sols[{va0, h0}], En /. First[sol]]
, {approx, approxs}];
];
(* just for beauty *)
sols[{va0, h0}] = Sort[DeleteDuplicates[sols[{va0, h0}]]];
Print[Row[{"Solutions En = ", sols[{va0, h0}]}]]
, {h0, h0s}]
, {va0, va0s}];
If[test && False,
Print["All solutions En =\n", Column[Normal[sols]]]];
(* Show real part Re(f) of function values with solutions marked *)
Print[ContourPlot[r[Va, En]
, {Va, First[prVa], Last[prVa]}, {En, First[prEn], Last[prEn]},
PlotRange -> All,
Contours -> h0s, ContourLabels -> True,
ColorFunction -> "TemperatureMap",
PerformanceGoal -> "Quality",
FrameLabel -> (Style[#, Black, Larger] & /@ {"Va", "En"}),
PlotLegends -> Automatic,
PlotLabel -> Style["Re[ f[Va, En] ] contour", Black, Bold],
Epilog -> {Darker[Green], Thin,
Line[{{#, First[prEn]}, {#, Last[prEn]}} & /@ va0s],
PointSize[Large],
Point[Flatten[
Table[If[
sols[{va0, h0}] != {}, {va0, #} & /@ sols[{va0, h0}],
Nothing], {va0, va0s}, {h0, h0s}], 2]]}
]];
(* Show sections through Re(f) at the points va0 with solutions \
marked *)
col[va_] :=
Hue[2/3 + (0 - 2/3)/(Last[prVa] - First[prVa])*(va - First[prVa])];
Print[Plot[Evaluate[Table[r[va0, En], {va0, va0s}]]
, {En, First[prEn], Last[prEn]},
PlotRange -> {prEn - {prEnL, 0}, Automatic},
AxesOrigin -> {First[prEn], 0},
PerformanceGoal -> "Quality",
PlotStyle -> (col[#] & /@ va0s),
Frame -> True,
FrameLabel -> (Style[#, Black, Larger] & /@ {"En",
"Re[f[va0, En]]"}),
PlotLegends -> (Style[Row[{"va0 = ", #}], 10] & /@ va0s),
PlotLabels ->
Placed[va0s, {Scaled[#/10], Above} & /@ Range[cntVa0s]],
PlotLabel ->
Style["Sections Re[ f[va0, En] ], va0 \[Element] va0s", Black,
Bold],
ImageSize -> Scaled[0.85], AspectRatio -> 5/4,
Epilog -> {Darker[Green], Thin,
Line[{{First[prEn] - prEnL, #}, {Last[prEn], #}} & /@ h0s],
Inset[
Style[Row[{"h0 = ", #}], 10,
Background -> White], {First[prEn] - prEnL/2, #}, {0,
0}] & /@ h0s,
PointSize[Large],
{va0 = #; col[va0],
Point[Flatten[
Table[If[
sols[{va0, h0}] != {}, {#, h0} & /@ sols[{va0, h0}],
Nothing], {h0, h0s}], 1]]} & /@ va0s }
]];
]];
I think, your problem is solved by this approach. At least numerically. I don't know if there is a closed analytical solution. Probably one would have to simplify the function significantly manually. With Simplify it is still too complicated.