Оптимизация интерполяции в Mathematica

В рамках моей работы мне часто приходится визуализировать сложные трехмерные плотности. Один набор программ, с которым я работаю, выводит радиальную составляющую плотности в виде набора из 781 точки на логарифмической сетке, ri = (Rmax/Rstep)^((i-1)/(pts-1), умноженной на сферическую гармонику. Для систем с низкой симметрией число сферических гармоник может быть достаточно большим для обеспечения точности, например. одна система требует 49 гармоник, соответствующих lmax = 6. Таким образом, чтобы использовать эти данные в Mathematica, у меня будет сумма до 49 интерполированных функций, каждая из которых умножается на другую сферическую гармонику. При использовании v.6 и построении интерполированных радиальных функций с использованием Interpolation и установки r = Sqrt(x^2 + y^2 + z^2) я останавливал ContourPlot3D спустя более часа, когда ничего не отображалось. Это включало уменьшение как InterpolationOrder, так и MaxRecursion до 1.

Появилось несколько альтернатив:

  1. Оцените функцию плотности на фиксированной сетке и используйте вместо нее ListContourPlot.
  2. Или линейно сплайнируйте радиальную функцию и используйте Piecewise, чтобы сшить их вместе. (Это представилось само собой, так как я мог использовать упрощение, чтобы уменьшить сложность результирующей функции.)

В итоге я использовал обе, так как InterpolatingFunction дает заметную задержку в оценке, а при оценке до 49 интерполируемых функций любая задержка может стать заметной. Кроме того, ContourPlot3D был быстрее со сплайном, но это не дало мне желаемого ускорения.

Я честно признаюсь, что я не пробовал Interpolation на v.7, и я не пробовал это на моем обновленном оборудовании (G4 против Intel Core i5). Тем не менее, я ищу альтернативы моей текущей схеме; желательно тот, где я могу использовать ContourPlot3D напрямую. Я мог бы попробовать другую форму сплайна, например B-spline, и, возможно, объединить что с UnitBox вместо использования Piecewise.

Редактировать: Просто чтобы уточнить, моя текущая реализация включает в себя создание сплайна первого порядка для каждой радиальной части, умножение каждого из них на соответствующую сферическую гармонику, суммирование и Simplifyобработка уравнений для каждого радиального интервала, а затем использование Piecewise связать их в одну функцию. Итак, моя реализация является полуаналитической в ​​том смысле, что сферические гармоники точны, а числовой является только радиальная часть. Это одна из причин, по которой я хотел бы использовать ContourPlot3D, чтобы воспользоваться полуаналитическим характером данных. Следует отметить, что радиальная сетка достаточно мелкая, чтобы создать хорошее представление радиальной части и ее можно плавно интерполировать. Хотя это дало мне значительное ускорение, когда я писал код, он все еще был медленным для оборудования, которое я использовал в то время.

Итак, вместо использования ContourPlot3D я бы сначала сгенерировал функцию, как указано выше, а затем оценил бы ее на декартовой сетке 803. Именно данные этого шага я использовал в ListContourPlot3D. Так как это не адаптивная сетка, местами это было слишком конечно, и мне не хватало фич.


person rcollyer    schedule 25.10.2010    source источник
comment
Просто чтобы убедиться, что я правильно вас понял: у вас есть 781 точка данных для каждой радиальной функции, всего 781 * 49 скаляров?   -  person Janus    schedule 26.10.2010
comment
Используете ли вы DataRange и данные только для ListContourPlot - в противном случае это выглядит как внутренний уровень интерполяции, см. stackoverflow.com/questions/2497517/   -  person Janus    schedule 26.10.2010
comment
@ Янус, да, ты правильно прочитал. Имеется до 781*49 скаляров. Как я указывал выше, угловая часть данных является аналитической, а числовой — только радиальная. Кроме того, я столкнулся с ошибкой низкого разрешения для данных в форме {x,y,z,f} при использовании ListContourPlot3D раньше, но здесь я сгенерировал 3D-массив и указал формат DataRange. Кроме того, хотя и медленный, внутренний слой интерполяции в ListContourPlot3D все же быстрее, чем ContourPlot3D.   -  person rcollyer    schedule 26.10.2010


Ответы (2)


Если вас действительно замедляет интерполяция радиальных функций, вы можете подумать о ручном кодировании этой части на основе ваших знаний о точках выборки. Как показано ниже, это дает значительное ускорение:

Я настроил вещи с вашей нотацией. lookuprvals — это список из 100 000 r значений для поиска по времени.

Во-первых, взгляните на интерполяцию акций как на базовую отметку.

With[{interp=Interpolation[N@Transpose@{rvals,yvals}]},
  Timing[interp[lookuprvals]][[1]]]
Out[259]= 2.28466

Переход на интерполяцию 0-го порядка уже на порядок быстрее (первый порядок почти такая же скорость):

With[{interp=Interpolation[N@Transpose@{rvals,yvals},InterpolationOrder->0]},
  Timing[interp[lookuprvals]][[1]]]
Out[271]= 0.146486

Мы можем получить еще 1,5 порядка, вычислив индексы напрямую:

Module[{avg=MovingAverage[yvals,2],idxfact=N[(pts-1) /Log[Rmax/Rstep]]},
  Timing[res=Part[avg,Ceiling[idxfact Log[lookuprvals]]]][[1]]]
Out[272]= 0.006067

В качестве среднего уровня выполните логарифмическую интерполяцию вручную. Это медленнее, чем приведенное выше решение, но все же намного быстрее, чем стандартная интерполяция:

Module[{diffs=Differences[yvals],
  idxfact=N[(pts-1) /Log[Rmax/Rstep]]},
  Timing[Block[{idxraw,idxfloor,idxrel},
    idxraw=1+idxfact Log[lookuprvals];
    idxfloor=Floor[idxraw];
    idxrel=idxraw-idxfloor;
    res=Part[yvals,idxfloor]+Part[diffs,idxfloor]idxrel  
  ]][[1]]]
Out[276]= 0.026557

Если у вас есть память для этого, я бы кэшировал сферические гармоники и радиус (или даже индекс радиуса) на полной сетке. Затем сгладьте кеши сетки, чтобы вы могли сделать

 Sum[ interpolate[yvals[lm],gridrvals] gridylmvals[lm], {lm,lmvals} ]

и воссоздайте свою сетку, как обсуждалось здесь.

person Janus    schedule 26.10.2010
comment
жаль, что я так долго смотрел на это. В вашем третьем примере вы вычисляете скользящее среднее значение, но ничего с ним не делаете. Кроме того, вычисление индексов и использование Part разумно, и, по сути, то, что я думал сделать. Я уже Compile функции, но, возможно, это можно сделать достаточно хорошо с таблицей диспетчеризации. Я не уверен, насколько хорошо 0-й порядок будет работать для того, что я хочу сделать, но если он эффективен, это обеспечит большое ускорение. Есть о чем подумать, и, поскольку на данный момент это побочный проект, пройдет какое-то время, прежде чем я смогу его реализовать. Спасибо за мысли. - person rcollyer; 29.10.2010
comment
Изменил пример 3 на то, что я имел в виду: вернуть среднее значение конечных точек на каждом интервале. Глядя на это снова, мне пришло в голову, что, возможно, на самом деле стоит передискретизировать ваши радиальные данные (с помощью сплайна или чего-то еще), просто чтобы вы могли выполнять быструю интерполяцию 0-го порядка, когда вы делаете выборку на сетке? - person Janus; 30.10.2010

Если вы можете обойтись без Mathematica, я бы посоветовал вам взглянуть на Paraview (FOSS, финансируемый правительством США, все платформы ), который, как я обнаружил, превосходит все, что касается визуализации огромных объемов данных. Ядром программного обеспечения является «Инструментарий визуализации» VTK, и при необходимости вы можете найти/написать другие внешние интерфейсы. .

VTK/Paraview может обрабатывать данные практически любого типа: скалярные и векторные в структурированных сетках или случайных точках, многоугольники, данные временных рядов и т. д. Из Mathematica я часто просто выгружаю данные сетки в VTK устаревший формат, который в простейшем случае выглядит так

# vtk DataFile Version 2.0
Generated by mma via vtkGridDump

ASCII

DATASET STRUCTURED_POINTS
DIMENSIONS 49 25 15
SPACING 0.125 0.125 0.0625
ORIGIN 8.5 5. 0.7124999999999999

POINT_DATA 18375
SCALARS  RF_pondpot_1V1MHz1amu  double 1
LOOKUP_TABLE default

0.04709501616121583
0.04135197485227461
... <18373 more numbers> ...

ХТХ!

person Janus    schedule 26.10.2010
comment
+1, я сталкивался с ними в прошлом, но в то время кривой обучения было достаточно, чтобы я их избегал. Это определенно промышленные решения, и мне, возможно, придется прибегнуть к ним в конечном итоге. Но я надеялся на решение, основанное на Mathematica, так как это то, что я знаю лучше всего, а время для реализации составит в худшем случае несколько часов. - person rcollyer; 26.10.2010