How can I use Interp1 here instead of ismembertol?
Ältere Kommentare anzeigen
Hi! Essentially, I am trying to find the distance away from the origin such that the concentration is an exact match to a certain value, and thus requiring interpolation. I am currently using ismembertol as a work around because I've come into some issues with Interp1 (which I'm fairly sure is what I need to be using), but it simply isn't accurate enough for my purposes.
Using interp1 gives an error since the dataset does not consist of unique values, but I cannot just condense it to unique values because I have to use the mesh I've generated to find the distance from the origin (unless I'm wrong here of course).
I am wondering:
- Can I somehow doctor the dataset to retain its order and indicies while removing repeated datapoints?
I.e [1, 5, 7, 8, 8, 16, 35, 35, 35, 60, 120] might become [1, 5, 7, 8, NaN, 16, 35, NaN, NaN, 60, 120]
- Can I use a different method of indexing that would work better in this case?
- Is there another method entirely that would be better suited to this?
It may be important to note that the next step is to vary V and recieve an array of dc values to plot a dc-V curve - so the solution would need to not cause any problems here.
Any help is greatly appriciated, I'm very fair from the code wizard i need ot be for this...
Here's my code so far:
% process Parameters
V = 10 % S/L interface velocity in microns/sec
% Material Parameters
c0 = 0.2; % Alloy composition
k = 0.28; % Partition Coefficient (conc solute in solid/ liquid)
D = 10; % Diffusivity in microns^2/sec
dc_tol = 1.01*c0; % Defines how close to c0 is acceptable
% Mesh Parameters
n = 500; % number of nodes
L = 5; % Length of nodes in microns
dx = L / n; % defining node spacing
x = linspace(0, L, n); % Mesh
% Initialise concentration field
c_field = ones(1, n)*c0; % Creates a field vector of intial concentrration
c_field_update = c_field;
% Initialise dc Field
dc_field = zeros(1, 100);
% Boundary Conditions
c_field(1) = c0 / k;
c_field(n) = c0;
% Solver controls
tol = 1e-3; % Sets the tolerance for stopping the iteration
err = 1; % sets starting value to check against tol
F0 = 0.5*dx*D/V; % Finite Difference Coefficient
% Solver
while err > tol
% Apply Boundary Conditions
c_field_update(1) = c_field(1);
c_field_update(n) = c_field(n);
% Finite Difference Scheme
for i = 2:(n-1)
c_field_update(i) = 0.5*(1+F0)*c_field(i+1)+0.5*(1-F0)*c_field(i-1);
end
% Compute Error
errVector = abs((c_field_update - c_field)./ c_field_update);
err = max(errVector);
% Update Concentration Field
c_field = c_field_update;
end
% Determine Solute Boundary Layer
% The ismembertol function gives number of nodes into the mesh of the first value that meets the dc_tol within a certain toleranmce, idx_tol)
idx_tol = 0.001*dc_tol;
[~, idx] = ismembertol(dc_tol, c_field, idx_tol);
dc = idx*dx % solute boundary layer thickness in microns
dcApprox = 2*D/V;
% Visualisation
figure;
plot (x, c_field, 'r-', 'lineWidth', 2);
xlabel('Position (microns)', "FontSize", 20);
ylabel('Concentration', "FontSize", 20);
title('Concentration Profile', "FontSize", 20);
Akzeptierte Antwort
Weitere Antworten (1)
Fiddling around with indices and ISMEMBERTOL are red-herrings and misdirections from your actual task. Essentially what you are trying to do is root-finding, so use FZERO (or similar). Using FZERO is conceptually neater and much more accurate. I also made a few other improvements (e.g. vectorizing the code inside the WHILE loop).
% Process parameters:
V = 10; % S/L interface velocity (microns/sec)
% Material parameters:
c0 = 0.2; % Alloy composition
k = 0.28; % Partition coefficient (solute in solid/liquid)
D = 10; % Diffusivity (microns^2/sec)
dct = 1.01 * c0; % Threshold concentration value
% Mesh parameters:
n = 500; % Number of nodes
L = 5; % Length of domain (microns)
dx = L / n; % Node spacing
x = linspace(0, L, n); % Spatial mesh
% Initialize concentration field:
cfd = ones(1, n) .* c0;
cfd(1) = c0 / k;
cfd(n) = c0;
% Solver controls:
tol = 1e-3;
err = 1;
f0 = 0.5 * dx * D / V;
% Finite difference solver (partially vectorized):
while err > tol
cfo = cfd;
%
cfd(2:n-1) = 0.5 * (1+f0) .* cfd(3:n) + 0.5 * (1-f0) .* cfd(1:n-2);
%
nzi = (cfd~=0);
rel = zeros(size(cfd));
rel(nzi) = abs((cfd(nzi) - cfo(nzi)) ./ cfd(nzi));
rel(~nzi) = abs(cfd(~nzi) - cfo(~nzi));
err = max(rel);
end
% Determine solute boundary layer:
cfu = @(xi) interp1(x, cfd, xi, 'pchip') - dct;
dc = fzero(cfu, x([1,n]));
dca = 2 * D / V;
% Display results:
fprintf('Computed solute boundary layer thickness: %.4f microns\n', dc);
fprintf('Approximate boundary layer thickness: %.4f microns\n', dca);
% Visualization:
figure;
plot(x, cfd,'r-', dc,dct,'b*', 'LineWidth', 2);
xlabel('Position (microns)', "FontSize", 20);
ylabel('Concentration', "FontSize", 20);
title('Concentration profile', "FontSize", 20);
grid on;
Lets zoom in on that point to see how it matches the plotted data:
plot(x, cfd,'r-', dc,dct,'b*', 'LineWidth', 2);
xlim([0.999,1.001]*dc)
ylim([0.999,1.001]*dct)
1 Kommentar
Compared against your approach using ISMEMBERTOL:
% process Parameters
V = 10; % S/L interface velocity in microns/sec
% Material Parameters
c0 = 0.2; % Alloy composition
k = 0.28; % Partition Coefficient (conc solute in solid/ liquid)
D = 10; % Diffusivity in microns^2/sec
dc_tol = 1.01*c0 % Defines how close to c0 is acceptable
% Mesh Parameters
n = 500; % number of nodes
L = 5; % Length of nodes in microns
dx = L / n; % defining node spacing
x = linspace(0, L, n); % Mesh
% Initialise concentration field
c_field = ones(1, n)*c0; % Creates a field vector of intial concentrration
c_field_update = c_field;
% Initialise dc Field
dc_field = zeros(1, 100);
% Boundary Conditions
c_field(1) = c0 / k;
c_field(n) = c0;
% Solver controls
tol = 1e-3; % Sets the tolerance for stopping the iteration
err = 1; % sets starting value to check against tol
F0 = 0.5*dx*D/V; % Finite Difference Coefficient
% Solver
while err > tol
% Apply Boundary Conditions
c_field_update(1) = c_field(1);
c_field_update(n) = c_field(n);
% Finite Difference Scheme
for i = 2:(n-1)
c_field_update(i) = 0.5*(1+F0)*c_field(i+1)+0.5*(1-F0)*c_field(i-1);
end
% Compute Error
errVector = abs((c_field_update - c_field)./ c_field_update);
err = max(errVector);
% Update Concentration Field
c_field = c_field_update;
end
% Determine Solute Boundary Layer
c_fieldu = unique(c_field, 'stable');
idx = interp1(c_fieldu, (1:numel(c_fieldu)), dc_tol);
dc = idx*dx
plot(x, c_field,'r-', dc,dc_tol,'b*', 'LineWidth', 2);
xlim([0.999,1.001]*dc)
ylim([0.999,1.001]*dc_tol)
Kategorien
Mehr zu Computational Fluid Dynamics (CFD) finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



