Идеи для уменьшения сложности трехмерной функции плотности для создания графика тройной поверхности в Matlab
У меня есть трехмерная функция плотности q(x,y,z), которую я пытаюсь построить в Matlab 8.3.0.532 (R2014a).
Область моей функции начинается в a и заканчивается в b равным интервалом ds. Я хочу построить плотность на графике тройной поверхности, где каждое измерение на графике представляет собой долю x, y, z в данной точке. Например, если у меня есть единица плотности в области при q(1,1,1) и другая единица плотности в области при q(17,17,17), в обоих случаях равные пропорции x, Поэтому у y, z и I на графике троичной поверхности будет две единицы плотности в координатах (1/3,1/3,1/3). У меня есть код, который работает с использованием Ternsurf. Проблема заключается в том, что количество точек пропорционального роста растет экспоненциально быстро с размером домена. На данный момент я могу построить только область размером 10 (в каждом измерении) с единичным интервалом (ds = 1). Однако мне нужен гораздо больший домен, чем этот (размер 100 в каждом измерении) и гораздо меньший, чем расстояние между единицами (в идеале всего 0,1) - это приведет к 100^3 * (1/0,1)^3 точкам на сетке, с которым Matlab просто не может справиться. У кого-нибудь есть идеи о том, как как-то связать функцию плотности с 3D-пропорциями, чтобы уменьшить количество точек?
Мой рабочий код с примером:
a = 0; % start of domain
b = 10; % end of domain
ds = 1; % spacing
[x, y, z] = ndgrid((a:ds:b)); % generate 3D independent variables
n = size(x);
q = zeros(n); % generate 3D dependent variable with some norm distributed density
for i = 1:n(1)
for j = 1:n(2)
for k = 1:n(2)
q(i,j,k) = exp(-(((x(i,j,k) - 10)^2 + (y(i,j,k) - 10)^2 + (z(i,j,k) - 10)^2) / 20));
end
end
end
Total = x + y + z; % calculate the total of x,y,z at every point in the domain
x = x ./ Total; % find the proportion of x at every point in the domain
y = y ./ Total; % find the proportion of y at every point in the domain
z = z ./ Total; % find the proportion of z at every point in the domain
x(isnan(x)) = 0; % set coordinate (0,0,0) to 0
y(isnan(y)) = 0; % set coordinate (0,0,0) to 0
z(isnan(z)) = 0; % set coordinate (0,0,0) to 0
xP = reshape(x,[1, numel(x)]); % create a vector of the proportions of x
yP = reshape(y,[1, numel(y)]); % create a vector of the proportions of y
zP = reshape(z,[1, numel(z)]); % create a vector of the proportions of z
q = reshape(q,[1, numel(q)]); % create a vector of the dependent variable q
ternsurf(xP, yP, q); % plot the ternary surface of q against proportions
shading(gca, 'interp');
colorbar
view(2)
2 ответа
Способ дискретизации, вероятно, зависит от использования вашего сюжета, возможно, имеет смысл прояснить ваш вопрос с этой точки зрения. В целом, вы, вероятно, боретесь с ошибкой "Недостаточно памяти", здесь описаны несколько важных приемов http://www.mathworks.nl/help/matlab/matlab_prog/resolving-out-of-memory-errors.html?s_tid=doc_12b?refresh=true. Конечно, они работают только до определенного размера массивов.
Более универсальным решением является слишком частичное сохранение массивов на жестком диске, оно замедляет обработку, но будет работать. Например, вы можете определить несколько функций q с масштабируемыми ngrids (например, ngridOrder0=[0:10:100], ngridOrder10=[1:1:9], ngridOrder11=[11:1:19] и т. Д...), и напишите функцию доступа, которая будет загружать / сохранять соответствующую сетку и функцию q в зависимости от части графика, которую вы просматриваете.
Я полагаю, ты имел в виду n(3)
в вашей внутренней петле. Вот несколько советов:
1) Ослабьте петли:
q = exp(- ((x - 10).^2 + (y - 10).^2 + (z - 10).^2) / 20);
2) Освободить формы:
xP = x(:); yP = y(:); zP = z(:);
3) Проверить Total
один раз вместо трех проверок x,y,z
:
Total = x + y + z; % calculate the total of x,y,z at every point in the domain
Total( abs(Total) < eps ) = 1;
x = x ./ Total; % find the proportion of x at every point in the domain
y = y ./ Total; % find the proportion of y at every point in the domain
z = z ./ Total; % find the proportion of z at every point in the domain
PS: я только что узнал твое имя.. это Джонатан;)