calculation of the limit thickness of a tank varying the pressure and the radius and matrix construction on matlab - matlab

I have to write a program on matlab to analyze the effect of the pressure on the minimal thickness for a pressure vessel for a pressure range between 1 and 300 bar and for different L/R ratios
The following code creates a vector called s_lim calculated with the different thicknesses:
`clear all; clc;
L_in = 1; % Internal radius in m
L_R_in = 1; % L/R ratio in m
%material properties
Sy = 2513; % Yield strength in bar
Su = 5521; % Ultimate tensile strength in bar
Density = 0.008027; % kg/m^3
Cost = 18.94; % $/kg % Wall thickness calculation
p_tank = 1:300; % Tank pressure in bar
R_in = 1;
V_in = 1;
R_in = 1;
s_lim = ones(length(p_tank),1);
s_Sy = ones(length(p_tank),1);
s_Su = ones(length(p_tank),1);
SF = 2; % Safety factor s_Sy = p_tank \* R_in / Sy \* 1.5; % Minimum thickness based on yield strength
for i = 1:length(p_tank)
s_Sy(i) = p_tank(i) .\* R_in / Sy \* 1.5; % Minimum thickness based on yield strength in bar
if (s_Su \< s_Sy)
s_Su(i) = p_tank(i).\* R_in / Sy \* SF; % Minimum thickness based on ultimate tensile strength in bar
s_lim(i) = s_Su(i); % Limiting criterion is burst = ultimate strength
disp('burst');
else
s_lim(i) = s_Sy(i); % Limiting criterion is proof = yield strength
disp('proof');
end
end`
The following is the other part that calculates the external radius of the tank for different L/R ratios,
`clear all;clc;
p_tank = 1;
L_in = 1;
L_R_in = 1: 1000;
R_in = ones(1,length(L_R_in));
V_in = ones(1,length(L_R_in));
for i = 1:length(p_tank)
for j = 1: length(L_R_in)
R_in(j) = L_in./L_R_in(j); % Length in m
V_in(j) = 4/3*pi.R_in(j).^3 + (L_in - 2 .* R_in(j)) . pi .\* R_in(j).^2; % m^3 plot(L_in, V_in);
end
end`
I would like to mix the two codes to creating a matrix R_ext(i,j) = R_in +s_lim where on every row I have the different R_ext calculated for every pressure between 1 and 300 bar, while on every column I have the dependance on the L/R ratio (here called L_R_in).
It shouldn't be hard it is just that I'm approaching coding, I hope it is clear
I tried to use a solution like
for i = 1 :length(p_tank) for j = 1 :length(L_R_in) s_Sy (i,j) = p_tank(i,j) .\* R_in(i,j) / Sy \* 1.5; ... ... end end
But it didn'y work

Related

How do I find local threshold for coefficients in image compression using DWT in MATLAB

I'm trying to write an image compression script in MATLAB using multilayer 3D DWT(color image). along the way, I want to apply thresholding on coefficient matrices, both global and local thresholds.
I like to use the formula below to calculate my local threshold:
where sigma is variance and N is the number of elements.
Global thresholding works fine; but my problem is that the calculated local threshold is (most often!) greater than the maximum band coefficient, therefore no thresholding is applied.
Everything else works fine and I get a result too, but I suspect the local threshold is miscalculated. Also, the resulting image is larger than the original!
I'd appreciate any help on the correct way to calculate the local threshold, or if there's a pre-set MATLAB function.
here's an example output:
here's my code:
clear;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% COMPRESSION %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% read base image
% dwt 3/5-L on base images
% quantize coeffs (local/global)
% count zero value-ed coeffs
% calculate mse/psnr
% save and show result
% read images
base = imread('circ.jpg');
fam = 'haar'; % wavelet family
lvl = 3; % wavelet depth
% set to 1 to apply global thr
thr_type = 0;
% global threshold value
gthr = 180;
% convert base to grayscale
%base = rgb2gray(base);
% apply dwt on base image
dc = wavedec3(base, lvl, fam);
% extract coeffs
ll_base = dc.dec{1};
lh_base = dc.dec{2};
hl_base = dc.dec{3};
hh_base = dc.dec{4};
ll_var = var(ll_base, 0);
lh_var = var(lh_base, 0);
hl_var = var(hl_base, 0);
hh_var = var(hh_base, 0);
% count number of elements
ll_n = numel(ll_base);
lh_n = numel(lh_base);
hl_n = numel(hl_base);
hh_n = numel(hh_base);
% find local threshold
ll_t = ll_var * (sqrt(2 * log2(ll_n)));
lh_t = lh_var * (sqrt(2 * log2(lh_n)));
hl_t = hl_var * (sqrt(2 * log2(hl_n)));
hh_t = hh_var * (sqrt(2 * log2(hh_n)));
% global
if thr_type == 1
ll_t = gthr; lh_t = gthr; hl_t = gthr; hh_t = gthr;
end
% count zero values in bands
ll_size = size(ll_base);
lh_size = size(lh_base);
hl_size = size(hl_base);
hh_size = size(hh_base);
% count zero values in new band matrices
ll_zeros = sum(ll_base==0,'all');
lh_zeros = sum(lh_base==0,'all');
hl_zeros = sum(hl_base==0,'all');
hh_zeros = sum(hh_base==0,'all');
% initiate new matrices
ll_new = zeros(ll_size);
lh_new = zeros(lh_size);
hl_new = zeros(lh_size);
hh_new = zeros(lh_size);
% apply thresholding on bands
% if new value < thr => 0
% otherwise, keep the previous value
for id=1:ll_size(1)
for idx=1:ll_size(2)
if ll_base(id,idx) < ll_t
ll_new(id,idx) = 0;
else
ll_new(id,idx) = ll_base(id,idx);
end
end
end
for id=1:lh_size(1)
for idx=1:lh_size(2)
if lh_base(id,idx) < lh_t
lh_new(id,idx) = 0;
else
lh_new(id,idx) = lh_base(id,idx);
end
end
end
for id=1:hl_size(1)
for idx=1:hl_size(2)
if hl_base(id,idx) < hl_t
hl_new(id,idx) = 0;
else
hl_new(id,idx) = hl_base(id,idx);
end
end
end
for id=1:hh_size(1)
for idx=1:hh_size(2)
if hh_base(id,idx) < hh_t
hh_new(id,idx) = 0;
else
hh_new(id,idx) = hh_base(id,idx);
end
end
end
% count zeros of the new matrices
ll_new_size = size(ll_new);
lh_new_size = size(lh_new);
hl_new_size = size(hl_new);
hh_new_size = size(hh_new);
% count number of zeros among new values
ll_new_zeros = sum(ll_new==0,'all');
lh_new_zeros = sum(lh_new==0,'all');
hl_new_zeros = sum(hl_new==0,'all');
hh_new_zeros = sum(hh_new==0,'all');
% set new band matrices
dc.dec{1} = ll_new;
dc.dec{2} = lh_new;
dc.dec{3} = hl_new;
dc.dec{4} = hh_new;
% count how many coeff. were thresholded
ll_zeros_diff = ll_new_zeros - ll_zeros;
lh_zeros_diff = lh_zeros - lh_new_zeros;
hl_zeros_diff = hl_zeros - hl_new_zeros;
hh_zeros_diff = hh_zeros - hh_new_zeros;
% show coeff. matrices vs. thresholded version
figure
colormap(gray);
subplot(2,4,1); imagesc(ll_base); title('LL');
subplot(2,4,2); imagesc(lh_base); title('LH');
subplot(2,4,3); imagesc(hl_base); title('HL');
subplot(2,4,4); imagesc(hh_base); title('HH');
subplot(2,4,5); imagesc(ll_new); title({'LL thr';ll_zeros_diff});
subplot(2,4,6); imagesc(lh_new); title({'LH thr';lh_zeros_diff});
subplot(2,4,7); imagesc(hl_new); title({'HL thr';hl_zeros_diff});
subplot(2,4,8); imagesc(hh_new); title({'HH thr';hh_zeros_diff});
% idwt to reconstruct compressed image
cmp = waverec3(dc);
cmp = uint8(cmp);
% calculate mse/psnr
D = abs(cmp - base) .^2;
mse = sum(D(:))/numel(base);
psnr = 10*log10(255*255/mse);
% show images and mse/psnr
figure
subplot(1,2,1);
imshow(base); title("Original"); axis square;
subplot(1,2,2);
imshow(cmp); colormap(gray); axis square;
msg = strcat("MSE: ", num2str(mse), " | PSNR: ", num2str(psnr));
title({"Compressed";msg});
% save image locally
imwrite(cmp, 'compressed.png');
I solved the question.
the sigma in the local threshold formula is not variance, it's the standard deviation. I applied these steps:
used stdfilt() std2() to find standard deviation of my coeff. matrices (thanks to #Rotem for pointing this out)
used numel() to count the number of elements in coeff. matrices
this is a summary of the process. it's the same for other bands (LH, HL, HH))
[c, s] = wavedec2(image, wname, level); %apply dwt
ll = appcoeff2(c, s, wname); %find LL
ll_std = std2(ll); %find standard deviation
ll_n = numel(ll); %find number of coeffs in LL
ll_t = ll_std * (sqrt(2 * log2(ll_n))); %local the formula
ll_new = ll .* double(ll > ll_t); %thresholding
replace the LL values in c in a for loop
reconstruct by applying IDWT using waverec2
this is a sample output:

Representing an exponential function with Fourier series

I am trying to represent a double exponential function with Fourier series in Matlab, but without the dc component. The basic function has the form K*(exp(-t.*alpha) - exp(-t.*beta)) and the expected format should be like this double exponential with the time domain function. I used the Heaviside function to make the rectangular window and invert the waveform.
clear, clc
Tr = 1.5E-6; Tf = 50E-6;
al=1/Tf; be=1/Tr; % alpha and beta
f0 = 1/(8*Tf);
T = 1/f0; % fundamental period
K = 1; % Amplitude
t=0:Tr/4:T; % Time
w0 = 2*pi/T; % Fundamental freq (in rad/s)
uV = 1E-6; % 1 uV = 1E-6 V
%% Double exponential - TD continuous
DEXP_TD_parameters = K* (exp(-t.*al) - exp(-t.*be));
DEXP_TD = K* (exp(-t.*al) - exp(-t.*be)).* (heaviside(t)-heaviside(t-T/2)) ...
- K* (exp(-(t-T/2).*al) - exp(-(t-T/2).*be)).*(heaviside(t-T/2)-heaviside(t-T));
Then, I calculated the ck of the series and plotted the time domain function again.
%% DEXP - Fourier coefficient c_k
h = 150; % Number of harmonics
for m = 1:h
if mod(m,2) == 0, ck(m) = NaN;
else
ck(m) = (K/pi) * ( (1+exp(-al*pi/w0)) / (1j*m+al/w0) ...
-(1+exp(-be*pi/w0)) / (1j*m+be/w0) );
ck_n(h-m+1) = (K/pi) * ( (1+exp(-al*pi/w0)) / (1j*(-m)+al/w0) ...
-(1+exp(-be*pi/w0)) / (1j*(-m)+be/w0) );
end
end
ck_n(ck_n == 0) = NaN;
%% FD/TD Reconstruction
DEXP_TD_rec = zeros(1,(length(t)));
summ = zeros(1,h);
if mod(h,2) == 0
hk=h-1;
else hk=h;
end
for m = 1:length(t)
for k = 1:2:h(end)
% DEXP_sum(k) = (ck(k)) * (exp(1j*w0*k*t(m)) + exp(-1j*w0*k*t(m)));
DEXP_sum(k) = 2*abs(ck(k)) * (cos(k*w0.*t(m) + angle(ck(k))));
end
DEXP_TD_rec(m) = sum(DEXP_sum);
end
%% Plots
figure(1) % TD
plot(t/uV, DEXP_TD,'r', t/uV, abs(DEXP_TD_rec),'--b')
grid
The time domain Fourier series waveform (in blue) does not match the red curve, and I wonder why. The shape is okay, but the second half of the curve should be negative. Any tips on how to solve it?

Simulating random walkers which can not collide into each other in Matlab

I have written a code to simulate the motion of circular particles in a 2d box. Whenever they move out of the box, I put them inside the box and near the wall. I want to add the diameter (2R) of particles in the code, which means when the distance between the center of two circles become less than 2R, they separate along the line connecting their centers so that the distance between the centers of the circles becomes equal to 2R.
Could anyone suggest a code to perevent the overlapping of particles?
This is my code in which overlap is not considered:
clear all
close all
l = 224; nn = 800; %number of particles
time = 1000; dd = 1;
x= l*rand(1,nn);
y= l*rand(1,nn);
for t = 1:time;
x= x + rand(1,nn)-0.5* ones(1,nn);
y=y+rand(1,nn)-0.5* ones (1,nn);
index = (x < 0); x(index) = abs(normrnd(0,1,1,nnz(index)));
index = (y < 0); y(index) = abs(normrnd(0,1,1,nnz(index)));
index = (x > l); x(index) = l-abs(normrnd(0,1,1,nnz(index)));
index = (y > l); y(index) = l-abs(normrnd(0,1,1,nnz(index)));
end
Here is some commented code which does what you want. Notably:
psize is some defined particle size for interaction.
point-to-point distances found using pdist2.
points that are too close are moved away from each other by some amount (dp times their current distances, if dp=1/2 then their x and y distances double) until there are no clashes.
See comments for details.
clear; close all;
l = 224; nn = 800; % number of particles
time = 100;
x = l*rand(1,nn); y = l*rand(1,nn);
psize = 2; % Particle size for interaction
dp = 0.1;
figure; hold on; axis([0 l 0 l]);
for t = 1:time;
% Random movement
movement = 2*rand(2,nn)-1;
x = x + movement(1,:);
y = y + movement(2,:);
index = (x < 0); x(index) = abs(normrnd(0,1,1,nnz(index)));
index = (y < 0); y(index) = abs(normrnd(0,1,1,nnz(index)));
index = (x > l); x(index) = l-abs(normrnd(0,1,1,nnz(index)));
index = (y > l); y(index) = l-abs(normrnd(0,1,1,nnz(index)));
% Particle interaction. Loop until there are no clashes. For
% robustness, some max iteration counter should be added!
numclash = 1;
while numclash > 0
dists = pdist2([x;y]', [x;y]'); % Distances between all particles
dists(dists < psize) = NaN; % Those too close are assigned NaN
tooclose = isnan(tril(dists,-1)); % All NaNs identified by logical
[clash1,clash2] = find(tooclose); % Get particles which are clashing
numclash = numel(clash1); % Get number of clashes
% All points where there was a clash, move away from each other
x(clash1) = x(clash1) + (x(clash1)-x(clash2))*dp;
x(clash2) = x(clash2) - (x(clash1)-x(clash2))*dp;
y(clash1) = y(clash1) + (y(clash1)-y(clash2))*dp;
y(clash2) = y(clash2) - (y(clash1)-y(clash2))*dp;
end
% Plot to visualise results. Colour fade from dark to bright green over time
scatter(x,y,'.','markeredgecolor',[0.1,t/time,0.4]);
drawnow;
end
hold off
Result:
Edit:
For a clearer diagram, you could initialise some colour matrix C = rand(nn,3); and plot using
scatter(x,y,[],C*(t/time),'.'); % the (t/time) factor makes it fade from dark to light
This would give each particle a different colour, which also fade from dark to light, rather than just fading from dark to light as before. The result would be something like this:

Is there an efficient way to calculate overlap between several boundaries in matlab?

I have two lists of regions (regionsA, regionsB) defined with boundaries (coordinates over an image of size 1024x1024) (.mat file available here). I want to calculate the overlap of each possible pair of regions between those two lists. And I expected it to be slow, but not that slow.
Currently I am using below code and it takes 20 - 40 seconds for 50x60 objects for me:
intersect_matrix = zeros(length(regionsA), length(regionsB)); % for storing true/false
intersect_matrix_iou = zeros(size(intersect_matrix_iou)); % for storing IoU (intersect over union)
for i = 1:length(regionsA)
for j = 1:length(regionsB)
% get coordinates
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
% move coordinates to origin (start at zero)
% this is not necessary but reduces the size of the mask created by poly2mask(), hence reduces consumed memory is
minX = min([x1(:); x2(:)]);
minY = min([y1(:); y2(:)]);
x1 = x1 - minX;
x2 = x2 - minX;
y1 = y1 - minY;
y2 = y2 - minY;
% create object masks in n x m window
m = max([x1(:); x2(:)]);
n = max([y1(:); y2(:)]);
objMask1 = poly2mask(y1,x1,m,n);
objMask2 = poly2mask(y2,x2,m,n);
save('regionsAB','regionsA', 'regionsB');
intersection = objMask1 & objMask2;
union = objMask1 | objMask2;
% store info
intersect_matrix(i,j) = (bwarea(intersection) ~= 0); % store true/false
if (bwarea(intersection) ~= 0)
intersect_matrix_iou(i,j) = bwarea(intersection) / bwarea(union);
else
intersect_matrix_iou(i,j) = 0; % avoid division by zero
end
end; clear j;
end; clear i;
Before, I approached the problem with polygon operations first. That was still slow (12 sec) but much better. However I had to change that to above code, since for some cases I got NaN values, as polybool / polyarea / ... have problems with unconnected areas. Using pixel masks is robust to those problems. This replaced the content of the for-loops:
% polygonal overlap
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
[x_i,y_i] = polybool('intersection',x1,y1,x2,y2);
[x_u,y_u] = polybool('union',x1,y1,x2,y2);
% store info
%intersect_matrix_geo{i, j} = [x_i,y_i];
intersect_matrix(i,j) = ~isempty([x_i,y_i]);
if ~isempty([x_i,y_i])
intersect_matrix_iou(i,j) = polyarea(x_i, y_i) / polyarea(x_u, y_u);
else
intersect_matrix_iou(i,j) = 0;
end
Question: Are there more efficient / faster ways to implement this ? (and still be robust to disconnected intersect regions and such things...)
most of the polygons don't intersect at all so most of the computations are redundant. I used rectint to test the intersections of the enclosing rectangles of the polygons so I'll have a prior on which polygons might intersect. It gave me much less computations and thus much faster code:
load regionsAB.mat
% get enclosing rectangle for each polygon
poly2rect = #(x) [min(x(:,1)),min(x(:,2)),...
1+max(x(:,1))-min(x(:,1)),1+max(x(:,2))-min(x(:,2))];
rectsA = cell2mat(cellfun(poly2rect,regionsA,'UniformOutput',0)');
rectsB = cell2mat(cellfun(poly2rect,regionsB,'UniformOutput',0)');
% compute rectangle intersections
ar = rectint(rectsA,rectsB);
[ii,jj] = find(ar > 0);
idx = numel(ii);
% test only for intersecting rectangles
intersect_matrix_iou = zeros(numel(rectsA),numel(rectsB)); % for storing IoU (intersect over union)
tic
for idx = 1:numel(ii)
i = ii(idx);
j = jj(idx);
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
% move coordinates to origin (start at zero)
% this is not necessary but reduces the size of the mask created by poly2mask(), hence reduces consumed memory is
minX = min([x1(:); x2(:)]);
minY = min([y1(:); y2(:)]);
% because set x1,y1 outside inner loop
x1 = x1 - minX;
y1 = y1 - minY;
x2 = x2 - minX;
y2 = y2 - minY;
% create object masks in n x m window
m = max([x1(:); x2(:)]);
n = max([y1(:); y2(:)]);
objMask1 = poly2mask(y1,x1,m,n);
objMask2 = poly2mask(y2,x2,m,n);
intersection = objMask1 & objMask2;
union = objMask1 | objMask2;
% store info
intersect_matrix_iou(i,j) = bwarea(intersection) / bwarea(union);
end
intersect_matrix = intersect_matrix_iou > 0;
toc

Trying implement the plot function but its not displaying the graph

In this MATLAB code, I intend to display a graph, but it shows me an empty graph.
% Proposed Model For Two-Phase Flow Analytical Design Equation for gas
% pipelines
clc
d = 26.75; % diameter in inches
pie = 3.142; %normal pie
A = (pie *d^2)/4; % Compute for the area
qm = 150; %volume flow rate of mixture
pm = 8; %Density of the mixture
Wm = qm* pm; % mass flow rate of mixture i.e oil and gas
Ho = 0.01; %Liquid Hold up
z = 0.85; % compressibility factor
R = 10.73; % Gas constant
f = 0.0254; %friction factor
p0 = 150; % Density of oil
T = 580; % Temperature in R degrees
P0 =1700; % 1700psi
L = 63.068; % Length
P1 = 602.7; % 602.7 psia
%Assume
Mg = 9.8;
formule1 = d*A^2*Mg*(1-Ho);
formule2 = f*Wm^2*z*R*T;
formule = formule1/formule2;
exprs1 = (p0*Ho*z*R*T)/Mg*(1-Ho);
express2 = P2^2-P1^2
drop_p =P1-P2
express3 = 2*p0*Ho*z*R*T*drop_p
better_express = express2 + express3
func1 = d/f
solve( (formule*better_express)- func1*log(P2+ exprs1/P1 + exprs1)^2 + L == 0, P2)
figure
plot(drop_p,L,'r:+')
Please, can anyone help me out? Thanks.
In your code: drop_p = P1-P2 and L = 63.068, so unless P2 is a vector you will get just a single red + in your graph. Like this (for P2 = 1):
Right now, the solve line returns an error, because it should be with '' on the variable to solve to:
solve( (formule*better_express)- func1*log(P2+ exprs1/P1 + exprs1)^2 + L == 0, 'P2')
but this doesn't effect the resulted graph anyway, because the solve output is not assigned to any variable.