If statements vs conditions
1 view (last 30 days)
Show older comments
Hi all,
I'm trying to set conditions to define some later operations.
I'm essentially simulating Esim4 which can be a value from 0 to 10, and fgsim which is a binary variable indicating whether something is installed (1) or missing (0). I'm then trying to calculate Asim_door. If fg installed (i.e., fgsim=1) and Esim4 is below n_fg, then Asim_door=0. If fg is installed and Esim4 is above n_fg, then Asim_door=Asim_door/A_fg. Otherwise if fg is not installed then Asim_door is not changed.
I get an error "Unable to perform assignment because the left and right sides have a different number of elements." when I attempt this with conditions as indicated by the %%%%.
What's the difference between doing it this way and an if statement?
% CVol3 sim
for iCombCVol3=1:size(IndMatCVol3) %Parent PS1 has 3 states for child node Vi
% EFH loc 4 sim
EFH4_a=[]; EFH4_a=ExtSurgeBinEdges_Lo(IndMatCVol3(iCombCVol3,4));
EFH4_c=[]; EFH4_c=ExtSurgeBinEdges_Hi(IndMatCVol3(iCombCVol3,4));
pdEFH4=[]; pdEFH4=makedist('Uniform',EFH4_a,EFH4_c);
Esim4=[]; Esim4=random(pdEFH4,[Nsim,1]); %simulate external flood heights within bin (Uniform)
Esim4=Esim4.*(Esim4>=0); % make sure the difference is never below zero
% Cumulative flow volume 1 sim
CVol2_a=[]; CVol2_a=VBinEdges_Lo(IndMatCVol3(iCombCVol3,3));
CVol2_c=[]; CVol2_c=VBinEdges_Hi(IndMatCVol3(iCombCVol3,3));
pdCVol2=[]; pdCVol2=makedist('Uniform',CVol2_a,CVol2_c);
CVol2sim=[]; CVol2sim=random(pdCVol2,[Nsim,1]); %simulate external flood heights within bin (Uniform)
CVol2sim=CVol2sim.*(CVol2sim>=0); % make sure the difference is never below zero
CVol2sim(CVol2sim>=Vroom(:,1))=Vroom(:,1); % make sure the difference is never below zero
%fgsim installed or missing
p_fg = [0.97 0.03]; % prob of fg installed, missing
% fg state sim of installed or not
pd_fg = makedist('Binomial',1, p_fg(IndMatCVol3(iCombCVol3,2)));
fgsim = random(pd_fg,[Nsim,1]);
% Door state sim through area
Asim_door = Esim4*door_W;
Asim_door(Asim_door<0)=0; % make sure the area is postive
Asim_door(Asim_door>A_door)=A_door; %make sure area is never bigger than the possible area of door
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Asim_door(fgsim>=1 & Esim4<=n_fg)=0; %fg installed, Esim below n_fg then no A_door flow area available
Asim_door(fgsim>=1 & Esim4>=n_fg)=(Asim_door./A_fg); %fg installed, Esim above n_fg then A_door/A_fg flow area available
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Volumetric flow rate 2 sim calculation
Qsim_door=[]; Qsim_door=Cd.*Asim_door.*sqrt(2*g*(Esim4)); %ft^3/s
Qsim_door=Qsim_door.*(Qsim_door>=0); %Ensures positivity
Qsim_door(Esim4<=n_ps)=1E-20; %No flow when Esim is less than or equal to installation height
% Flow volume sim calculation
Vsim_door=[]; Vsim_door=Qsim_door.*Dsim; %ft^3
Vsim_door=Vsim_door.*(Vsim_door>=0); %ensure positivity
Vsim_door(Vsim_door>=Vroom(:,1))=Vroom(:,1); %Ensure Vsim is less than Vroom (3 Vroom configs)
Vsim_door(Esim4<=n_ps)=1E-20; %No flow volume when Esim is less than or equal to installation height
% Cumulative flow 1 sim calculation
CVol3sim= CVol2sim+Vsim_door;
CVol3sim=CVol3sim.*(CVol3sim>=0); %ensure positivity
CVol3sim(CVol3sim>=Vroom(:,1))=Vroom(:,1);
CVol3sim(CVol2sim<=0 & Vsim_door<=0)=0; % No cumulative flow 3 if CVol2 and Vsim_door have no flow
% Histogram
Hist_CVol3=[]; [Hist_CVol3,~] = histcounts(CVol3sim,VBinEdges);
Hist_CVol3=Hist_CVol3';
PMF_CVol3(:,iCombCVol3)=Hist_CVol3./sum(Hist_CVol3); % Bins it by the parents
end
0 Comments
Accepted Answer
Voss
on 6 Sep 2023
In this line, you have the entire array Asim_door (divided by A_fg) on the right side, trying to assign it to a subset on the left side. That's the problem.
Asim_door(fgsim>=1 & Esim4>=n_fg)=(Asim_door./A_fg); %fg installed, Esim above n_fg then A_door/A_fg flow area available
You have to use the same indices on both sides.
So if A_fg is a scalar:
idx = fgsim>=1 & Esim4>=n_fg;
Asim_door(idx) = Asim_door(idx)./A_fg; %fg installed, Esim above n_fg then A_door/A_fg flow area available
Or if A_fg is an array the same size as Asim_door:
idx = fgsim>=1 & Esim4>=n_fg;
Asim_door(idx) = Asim_door(idx)./A_fg(idx); %fg installed, Esim above n_fg then A_door/A_fg flow area available
What's the difference between doing it this way and an if statement?
Doing it this way (using logical indexing) is more concise and likely to be faster than using an if statement. With an if, you'd need to loop over the elements, e.g., if A_fg, n_fg and fgsim are arrays the same size as Asim_door:
for ii = 1:numel(Esim4)
if fgsim(ii) >= 1 && Esim4(ii) >= n_fg(ii)
Asim_door(ii) = Asim_door(ii)./A_fg(ii);
end
end
and if any of them are scalars, remove the (ii) indexing for those (and you could likely simplify the logic, e.g., if fg_sim is a scalar, you do not need to perform the loop at all if fg_sim < 1).
Note that the logical indexing expression
idx = fgsim>=1 & Esim4>=n_fg;
works the same regardless of whether n_fg and/or fgsim are scalars because of how & works:
true & [false false true]
[true true true] & [false false true]
More Answers (1)
Steven Lord
on 6 Sep 2023
Esim4=Esim4.*(Esim4>=0); % make sure the difference is never below zero
I likely would just call the max function on Esim4 instead.
Esim4 = max(Esim4, 0);
Some of your other conditional steps could probably be replaced by calls to min and/or max instead of logical indexing (potentially combined with element-wise multiplication.)
0 Comments
See Also
Categories
Find more on Manage Products in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!