Можно ли создать полярный CountourPlot/ListCountourPlot/DensityPlot в Mathematica?

Я хочу нарисовать что-то вроде режимов шепчущей галереи - двумерный цилиндрически симметричный график в полярных координатах. Что-то вроде этого:

whispering gallery modes

Я нашел следующий фрагмент кода в путеводителе по символике Тротта. Пробовал работать с очень маленьким набором данных; он съел 4 ГБ памяти и запустил мое ядро:

(* add points to get smooth curves *)
addPoints[lp_][points_, \[Delta]\[CurlyEpsilon]_] := 
Module[{n, l}, Join @@ (Function[pair,
       If[(* additional points needed? *)
          (l = Sqrt[#. #]&[Subtract @@ pair]) < \[Delta]\[CurlyEpsilon], pair, 
          n = Floor[l/\[Delta]\[CurlyEpsilon]] + 1; 
          Table[# + i/n (#2 - #1), {i, 0, n - 1}]& @@ pair]] /@ 
          Partition[If[lp === Polygon, 
                       Append[#, First[#]], #]&[points], 2, 1])]

(* Make the plot circular *)
With[{\[Delta]\[CurlyEpsilon] = 0.1, R = 10}, 
 Show[{gr /. (lp : (Polygon | Line))[l_] :> 
     lp[{#2 Cos[#1], #2 Sin[#1]} & @@@(* add points *)
       addPoints[lp][l, \[Delta]\[CurlyEpsilon]]], 
   Graphics[{Thickness[0.01], GrayLevel[0], Circle[{0, 0}, R]}]}, 
  DisplayFunction -> $DisplayFunction, Frame -> False]]

Здесь gr представляет собой прямоугольный 2D ListContourPlot, созданный с использованием чего-то вроде этого (например):

data = With[{eth = 2, er = 2, wc = 1, m = 4}, 
   Table[Re[
     BesselJ[(Sqrt[eth] m)/Sqrt[er], Sqrt[eth] r wc] Exp[
       I m phi]], {r, 0, 10, .2}, {phi, 0, 2 Pi, 0.1}]];
gr = ListContourPlot[data, Contours -> 50, ContourLines -> False, 
  DataRange -> {{0, 2 Pi}, {0, 10}}, DisplayFunction -> Identity, 
  ContourStyle -> {Thickness[0.002]}, PlotRange -> All, 
  ColorFunctionScaling -> False]

Есть ли простой способ делать такие цилиндрические графики?.. Мне трудно поверить, что мне придется обратиться к Matlab для моих криволинейных координат:)

Ответ 1

Предыдущие фрагменты удалены, так как это, безусловно, лучший ответ, который я придумал:

With[{eth = 2, er = 2, wc = 1, m = 4}, 
 ContourPlot[
  Re[BesselJ[(Sqrt[eth] m)/Sqrt[er], Sqrt[eth] r wc] Exp[I phi m]]/. 
                                         {r ->Norm[{x, y}], phi ->ArcTan[x, y]}, 
  {x, -10, 10}, {y, -10, 10}, 
  Contours -> 50, ContourLines -> False, 
  RegionFunction -> (#1^2 + #2^2 < 100 &), 
  ColorFunction -> "SunsetColors"
 ]
]

enter image description here

Edit

Замена ContourPlot на Plot3D и удаление неподдерживаемых параметров:

enter image description here

Ответ 2

Это относительно простая проблема. Ключ в том, что если вы можете параметризовать его, вы можете построить его. В соответствии с документацией ListContourPlot и ListDensityPlot принимать данные в двух формах: массив значений высоты или список координат плюс значение функции ({{x, y, f} ..}). Вторая форма легче справиться, так что даже если ваши данные находятся в первой форме, мы преобразуем ее во вторую форму.

Просто, чтобы преобразовать данные формы {{r, t, f} ..} в данные формы {{x, y, f} ..}, вы делаете N[{#[[1]] Cos[ #[[2]] ], #[[1]] Sin[ #[[2]] ], #[[3]]}]& /@ data, когда применяется к данным, взятым из BesselJ[1, r/2] Cos[3 t], вы получаете

code for and plot of numerical data

Как насчет того, когда у вас есть только массив данных, например этот парень? В этом случае у вас есть 2D-массив, в котором каждая точка в массиве имеет известное местоположение, и для его построения вам нужно превратить его во вторую форму. Я неравнодушен к MapIndexed, но есть и другие способы сделать это. Скажем, ваши данные хранятся в массиве, где строки соответствуют радиальной координате, а столбцы - это координата angular. Затем, чтобы преобразовать его, я использовал бы

R = 0.01;    (*radial increment*)
T = 0.05 Pi; (*angular increment*)
xformed = MapIndexed[ 
   With[{r = #2[[1]]*R, t = #2[[1]]*t, f = #1},
   {r Cos[t], r Sin[t], f}]&, data, {2}]//Flatten[#,1]&

который дает тот же результат.


Если у вас есть аналитическое решение, вам нужно преобразовать его в декартовы координаты, как указано выше, но вместо этого вы используете правила замены. Например,

ContourPlot[ Evaluate[
    BesselJ[1, r/2]*Cos[3 t ] /. {r -> Sqrt[x^2 + y^2], t -> ArcTan[x, y]}], 
   {x, -5, 5}, {y, -5, 5}, PlotPoints -> 50, 
   ColorFunction -> ColorData["DarkRainbow"], Contours -> 25]

дает

analytic plot of Bessel in cylindrical coordinates

Следует отметить две вещи: 1) Evaluate необходим, чтобы гарантировать, что замена выполнена правильно, и 2) ArcTan[x, y] учитывает квадрант, в котором находится точка {x,y}.