whats wrong in this function?
37 views (last 30 days)
Show older comments
Hi:)
When I call the attached function with for instance best_salt_1='ZnBr2' and best_salt_2='MgCl2' and temperatur_1 = 40, I get this error saying:
Output argument "massetetthet_MgCl2" (and maybe others) not assigned during call to "beregn_massetetthet_mettetsaltlosning".
I dont understand I have set all the variables after each if block to something...and I know a similar function has worked for me earlier.
4 Comments
dpb
ongeveer 2 uur ago
I meant something like the following, not images and without all the superfluous blank lines and all so that one can't readily see what the code structure really is.
function [massetetthet_ZnBr2,massetetthet_MgCl2,massetethet_CaCl2, massetetthet_KCl, ...
massetetthet_MgBr2,massetetthet_NaCl, massetetthet_AlCl3,massetetthet_CH3CO2K, ...
massetetthet_HCOOK, massetetthet_HCOONa, massetetthet_CaBr2]= ...
beregn_massetetthet_mettetsaltlosning(best_salt_1, best_salt_2, temperatur_1)
if ~isempty(temperatur_1)
if strcmpi(best_salt_1,'ZnBr2')||strcmpi(best_salt_2,'ZnBr2')
masse_salt= ( 3E-05)*temperatur_1^4 - 0.0053*temperatur_1^3 + 0.3028*temperatur_1 - 0.5269*temperatur_1 + 386.79
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast ZnBr2
volum_salt= (masse_salt/4.2);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_ZnBr2= (masse_total./ Volum_losning);
elseif strcmpi(best_salt_1, 'MgCl2')||strmpci(best_salt_2,'MgCl2')
masse_salt= 0.0016*temperatur_1^2 + 0.0394*temperatur_1 + 53.066
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast ZnBr2
volum_salt= (masse_salt/2.316);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_MgCl2=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1, 'CaCl2')||strmcpi(best_salt_2, 'CaCl2')
masse_salt= (-2E-07)*temperatur_1^5 + (5E-05)*temperatur_1^4 - (0.0053)*temperatur_1^3 + 0.2307*temperatur_1^2 - 1.9318*temperatur_1 + 60.824
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast MgBr2
volum_salt= (masse_salt/2.15);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_CaCl2=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1, 'KCl')|| strcmpi(best_salt_2,'KCl')
masse_salt=0.2832*temperatur_1 + 28.468
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast KCl
volum_salt= (masse_salt/1.98);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_KCl=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1, 'MgBr2')|| strcmpi(best_salt_2,'MgBr2')
masse_salt=0.001*temperatur_1^2 + 0.1751*temperatur_1 + 97.542
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast KCl
volum_salt= (masse_salt/3.72);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_MgBr2=(masse_total./Volum_losning);
elseif strcmpi(best_salt_1,'NaCl')||strmcpi(best_salt_2,'NaCl')
masse_salt=0.0003*temperatur_1^2 + 0.0082*temperatur_1 + 35.629
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast MgBr2
volum_salt= (masse_salt/2.17);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_NaCl=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1,'AlCl3')||strcmpi(best_salt_2,'AlCl3')
masse_salt= (3E-06)*temperatur_1^3 - 0.001*temperatur_1^2 + 0.1175*temperatur_1 + 43.86
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast AlCl3
volum_salt= (masse_salt/2.48);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_AlCl3=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1,'CH3CO2K')||strcmpi(best_salt_2,'CH3CO2K')
masse_salt=(-2E-08)*temperatur_1^6 + (6E-06)*temperatur_1^5 - (0.0006)*temperatur_1^4+ 0.0234*temperatur_1^3 - 0.3943*temperatur_1^2 + 3.9427*temperatur_1 + 215.8
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast k-acetat
volum_salt= (masse_salt/1.57);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_CH3CO2K=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1,'HCOOK')||strmcpi(best_salt_2,'HCOOK')
masse_salt= (1E-05)*temperatur_1^4 - 0.0027*temperatur_1^3 + 0.1913*temperatur_1^2 - 2.5374*temperatur_1 + 326.45
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast k-acetat
volum_salt= (masse_salt/1.91);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_HCOOK=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1,'HCOONa')||strmcpi(best_salt_2,'HCOONa')
masse_salt= (2E-09)*temperatur_1^6 - (8E-07)*temperatur_1^5 + 0.0001*temperatur_1^4 - 0.0061*temperatur_1^3 + 0.1429*temperatur_1^2 + 0.8372*temperatur_1 + 44.057
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast k-acetat
volum_salt= (masse_salt/1.920);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_HCOONa=(masse_total./ Volum_losning);
elseif strcmpi(best_salt_1, 'CaBr2')||strmcpi(best_salt_2,'CaBr2')
masse_salt= (2E-05)*temperatur_1^4 - 0.0045*temperatur_1^3 + 0.3397*temperatur_1^2 - 6.3523*temperatur_1 + 166.33
masse_total=(100.0+masse_salt);
volum_vann=(100.0/0.998);
% volum av saltet er lik massen til saltet delt på massetetthetent
% til fast k-acetat
volum_salt= (masse_salt/3.41);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+ volum_salt)*0.80;
massetetthet_CaBr2=(masse_total./ Volum_losning);
else
massetetthet_ZnBr2=[];
massetetthet_MgCl2=[];
massetethet_CaCl2=[];
massetetthet_KCl=[];
massetetthet_MgBr2=[];
massetetthet_NaCl=[];
massetetthet_AlCl3=[];
massetetthet_CH3CO2K=[];
massetetthet_HCOOK=[];
massetetthet_HCOONa=[];
massetetthet_CaBr2 =[];
end
else
massetetthet_ZnBr2=[];
massetetthet_MgCl2=[];
massetethet_CaCl2=[];
massetetthet_KCl=[];
massetetthet_MgBr2=[];
massetetthet_NaCl=[];
massetetthet_AlCl3=[];
massetetthet_CH3CO2K=[];
massetetthet_HCOOK=[];
massetetthet_HCOONa=[];
massetetthet_CaBr2=[];
end
end
Answers (2)
Steven Lord
ongeveer 2 uur ago
Let's look at the signature of your function (with some line breaks added to avoid scrolling.)
function [massetetthet_ZnBr2,massetetthet_MgCl2, massetethet_CaCl2,...
massetetthet_KCl,massetetthet_MgBr2, massetetthet_NaCl,...
massetetthet_AlCl3, massetetthet_CH3CO2K, massetetthet_HCOOK, ...
massetetthet_HCOONa, massetetthet_CaBr2] = ...
beregn_massetetthet_mettetsaltlosning(best_salt_1, best_salt_2, temperatur_1)
I suspect what you believe will happen is that only the massetetthet_* variables corresponding to the inputs you pass in for best_salt_1 and best_salt_2 will be returned from this function. That is not correct. Your function declares that it returns eleven variables in a particular order, so you have to call it with all eleven outputs even if you just wanted (as an example) massetetthet_HCOONa and massetetthet_CaBr2.
In addition, if / elseif / else statements don't "fall through". As soon as one of the if or elseif conditions are satisfied, MATLAB runs the body of that section of the statement then skips to the next line after the trailing end. It doesn't "check the next elseif check" or anything like that. So at best, unless neither best_salt_1 nor best_salt_2 are any of the salts you're looking for (only your else block defines all eleven variables) your code won't work.
Rather than defining eleven output variables, I would define two: massetetthet_salt1 and massetetthet_salt2. I would also write the code that does the if / elseif / else statement as a local function so I could call that local function twice, once with best_salt_1 as input and once with best_salt_2 as input. That would avoid duplicating the code.
2 Comments
dpb
ongeveer een uur ago
Edited: dpb
25 minuten ago
The point @Steven Lord is making is that MATLAB runs ONLY ONE of the "if" or "elseif" clauses when called. Your logic cases are, for example
if strcmpi(best_salt_1,'ZnBr2')||strcmpi(best_salt_2,'ZnBr2')
and in that clause you define only the output for that one salt, leaving all the others including the input other salt whether it's first one or second undefined.
The question is what do you want the results to be; if need the two to both be calculated (as one would really presume on looking in more depth), you would need to call the function twice, once for each of the two.
Or, your if...elseif...elseif...end block should be a set of independent "if...end" cases so each of the two would be satisfied. Steven's suggestion of only two outputs instead of all eleven is also a much cleaner solution; more along the lines I was suggesting with a somewhat different strategy to also keep the given salt name.
dpb
ongeveer 2 uur ago
Edited: dpb
13 minuten ago
OK, try this...
function [massetetthet]=beregn_massetetthet_mettetsaltlosning(best_salt_1, best_salt_2, temperatur_1)
% take care of possible missing input temp
assert(~isempty(temperatur_1), "No temperature input. Aborting.")
% now do work...return as structure with salt names as fields
massetetthet.(best_salt_1)=doSaltDensity(best_salt_1,temperatur_1);
massetetthet.(best_salt_2)=doSaltDensity(best_salt_2,temperatur_1);
function massetetthet=doSaltDensity(salt,T)
SALTS={'ZnBr2','MgCl2','CaCl2','KCl','MgBr2','NaCl','AlCl3','CH3CO2K','HCOOK','HCOONa','CaBr2'};
COEFFS=[0, 0, 3E-05, -0.0053, 0.3028, -0.5269, 386.79;
0, 0, 0, 0, 0.0016, 0.0394, 53.066
];
DENS25=[4.22; 2.316; 2.15; 1.98; 3.72; 2.17; 2.48; 1.57; 1.91; 1.920; 3.41];
volum_vann=(100.0/0.998);
ixSalt=find(matches(SALTS,salt,'ignorecase',1)); % lookup which salt it is working on...
assert(~isempty(ixSalt),'Salt %s not found. Aborting.',salt) % make sure found one
masse_salt=polyval(COEFFS(ixSalt,:),T); % compute initial mass from correlation
masse_total=(100.0+masse_salt);
% volum av saltet er lik massen til saltet delt på massetetthetent til fast
volum_salt=masse_salt/DENS25(ixSalt);
% Volum av løsningen med ca 10% krympning
Volum_losning=(volum_vann+volum_salt)*0.80;
massetetthet=masse_total./Volum_losning;
end
end
beregn_massetetthet_mettetsaltlosning('MgCl2','ZnBr2',40)
You'll have to go through and finish filling out the COEFFS array; I only did the first two for testing. Also verify there aren't any unique things for any case I neglected to account for; I did make the assumption everything other than the numeric constants is the same without reading every line to ensure there wasn't something in one of the cases.
This way, you can add any number of additional salts that have similar behavior simply by augmenting the data arrays.
As the above illustrates, the key to writing generic code is to separate the data from the code; write code to solve the physical problem for any set of data, then pass the data. Here it's complicated only slightly by the need to have the data values also dependent upon a given input, but as illustrated, that's generally solvable by use of lookup tables as shown.
1 Comment
dpb
ongeveer een uur ago
Edited: dpb
17 minuten ago
ADDENDUM
COEFFS=[0, 0, 3E-05, -0.0053, 0.3028, -0.5269, 386.79];
A word of caution would be to ensure you're using all the precision that is available for these polynomial constants -- a high order polynomial can be very sensitive to the higher power terms, even if they're small numerically. Here for example
T=40;
P4=3e-5*T^4
D=polyval(COEFFS,T)
P4/D*100
It's 13% of the evaluated value.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!