Asked by Gaëtan Poirier
on 16 Aug 2019

I would like to start by saying I am utterly miserable at coding (somewhat of a beginner) and the following might be the worst thing you lay your eyes on today, but please bear with me.

I am trying to write a program that, when a specific material is inputed by the user as well as a wavelength (lambda), the refractive index for that material at that wavelength is provided.

I have a couple equations that represent the functions required to determine the refractive index of said materials dependent on the value given for the wavelength. I would like to have the program prompt the user to provide the material for which they would like the refractive index to be determined, followed by a prompt to provide the specific wavelength that will be used to generate the refractive index for the specified material at the specified wavelength.

So far, I have the following code:

BK7=@(lambda) sqrt((((1.03961212).*(lambda).^2)./((lambda).^2 - (0.0060069867))) + (((0.231792344).*(lambda).^2)./((lambda).^2 - 0.0200179144)) + 1); %BK7 (N-BK7 schoot at 20C)%

FusedSilica=@(lambda) sqrt((((0.6961663).*(lambda).^2)./((lambda).^2 - (0.0684043).^2)) + (((0.4079426).*(lambda).^2)./((lambda).^2 - (0.1162414).^2)) + (((0.8974794).*(lambda).^2)./((lambda).^2 - (9.896161).^2)) + 1); %Fused Silica (Malitson 1965: n 0.21 - 3.71 micrometer at 20C)

SodaLime=@(lambda) 1.5130 - 0.003169.*(lambda).^2 + 0.003962.*(lambda).^-2; %Soda Lime glass (Rubin 1985: Clear; n,k 0.31 - 4.6 micrometer at unspecified temperature)%

Borofloat=@(lambda) sqrt(((1.03961212.*(lambda).^2)./((lambda).^2 - 0.00600069867)) + ((0.231792344.*(lambda).^2)./((lambda).^2 - 0.0200179144)) + ((1.01046945.*(lambda).^2)./((lambda).^2 - 103.560653)) + 1); %Borasilicate Crown (Schott N-BK7 at 20C)%

Air=@(lambda) ((0.05792105)./(238.0195 - (lambda).^-2)) + ((0.00167917)./(57.362 - (lambda).^-2)) + 1; %Air (at 15C)%

NOA61=@(lambda) 1.5375 + ((8290.45)./(lambda).^2) - ((2.11046*10.^8)./(lambda).^4); %Norland Optical Adhesive 61 (at 25C)%

material(1) = input('What material are you looking for? '); %user is asked to provide which material they seek to find the refractive index for

lambda = input('What is the value of lambda? ', 's') %user is asked to provide the wavelength value

%required to determing the refractive index in each equation

%The 's' was needed to

%avoid an error

switch material(1) %the included (1) is also a means to avoid an error

case 'BK7'

solve(BK7) %if BK7 is inputed in the above prompt, we look to solve equation BK7=@(lambda)

disp('The refractive index is:'), disp solve(BK7); %once the equation is solved, the refractive index should be provided to the user

case 'Fused Silica'

solve(FusedSilica)

disp('The refractive index is:'), disp solve(FusedSilica);

case 'Soda Lime'

solve(SodaLime)

disp('The refractive index is:'), disp solve(SodaLime);

case 'Borofloat'

solve(Borofloat)

disp('The refractive index is:'), disp solve(Borofloat);

case 'Air'

solve(Air)

disp('The refractive index is:'), disp solve(Air);

case 'NOA61'

solve(NOA61)

disp('The refractive index is:'), disp solve(NOA61);

otherwise

disp('Type in the correct name or choose another material') %in the case the user does not provide the name for one of the

%materials given on the list of equations above, this statment is issued

end

At the moment I have the issue that the switch function is not dependent on the input of the 'material' but rather the input of the wavelength. For example, any value may be inputted into the material prompt and the program with continue to the wavelength prompt but the input of the wavelength prompt is restricted to the specific cases in the switch function. Therefore, I could input '12' into the material and everything would be fine, but when inputting '12' into the wavelength prompt I receive the statement "Type in the correct name or choose another material," which should be reserved for the material prompt.

Other than the fact that this is probably a convoluted way of generating the desired code, I assume this is an issue of the order of operations that the code runs through. Moreover, I cannot get any inputted wavelength (lambda) term to be included in the outputted refractive index value. At the moment, I cannot run the program to a point where the refractive index is displayed as "The refractive index is: "... I assume because I did not give a way for the value of lambda to be stored as a value (as of now the lambda term in stored as a 'char' so that might be an underlying culprit).

Any help would be greatly appreciated. Thank you in advance!

Answer by Star Strider
on 16 Aug 2019

The 's' indicates that input for ‘lambda’ should return a character vector, so it does.

If the materials are numbered, so the correct response to the material question is a number, the material input will work as you have specified it, although the switch ... case block will have to be re-written to accommodate the numbers rather than the strings. If ‘material’ is supposed to be a string, your code will not work, and will for example throw an error:

Error using input

Undefined function or variable 'BK7'.

Your input assignments may do what you want if you instead write them as:

lambda = input('What is the value of lambda? ')

material = input('What material are you looking for? ', 's')

Gaëtan Poirier
on 16 Aug 2019

Thank you for the insightful response!

This definitely makes sense. I should ask, without making any dramatic changes to the current code, is there anyway to make it so the wavelength is prompted after the material? I understand that it works better the way you suggested, however the material seems like something to ask first (just me being nitpicky I guess).

Moreover, I did the changes and it works better but my output is "solve(...)" instead of a value. Should I look to assign the "solve(...)" to a specific value or character and when I want to output the answer given by the equation I call that specified value or character?

I just rewrote the final display to have the "solve(...)" in parentheses.

switch material(1) %the included (1) is also a means to avoid an error

case 'BK7'

solve(BK7) %if BK7 is inputed in the above prompt, we look to solve equation BK7=@(lambda)

disp('The refractive index is:'), disp (solve(BK7)); %once the equation is solved, the refractive index should be provided to the user

The above seems to give a both a positive and a negative root (which I assume is a good sign) although they are far from simplified.

Star Strider
on 16 Aug 2019

My pleasure.

With respect to the order, just reverse the input assignments:

material = input('What material are you looking for? ', 's')

lambda = input('What is the value of lambda? ')

I saw the solve calls, however your code is not obvious in that respect (for example, there is no syms call) so I assume you conld have intended fsolve. In any event, if you want to use symbolic variables, vpasolve might be a better choice, perhaps combined with double. Those will return numeric results (ideally) that you can use in other parts of your code. You can then choose the positive root (since that is what I believe you would want) with straightforward logic, for example:

rt = solve(BK7);

disp('The refractive index is:')

disp(rt(rt > 0))

although it would likely be more efficient to do something like:

fprintf('The refractive index for %s at lambda = %.2f is: %.2f\n', material, lambda, rt(rt>0))

instead of the disp calls.

I did not test any of this, so I am listing it as UNTESTED CODE. It should work, although minor modifications may be necessary.

Sign in to comment.

Answer by dpb
on 16 Aug 2019

Do something more like:

materials={'BK7','Fused Silica','Soda Lime','Borofloat','Air','NOA61'};

[material,ok] = listdlg('PromptString','Select a material:',...

'SelectionMode','single',...

'ListString',materials)

if ~ok, return, end % bail out if user didn't select a material...

lambdastr=input('What is the value of lambda? ', 's') %user is asked to provide the wavelength value

try

lambda=str2double(lambdastr);

catch

error("Must enter valid number, sorry...")

end

...

You can be a little more user friendly with the numeric input by wrapping in a while...end loop until get a valid response and/or use a text dialog box for prettier interface...there are examples if search Answers.

With the listbox dialog, the selection is the numeric order of the options in the list so you change you switch block case values to the appropriate integer instead of strings.

Sign in to comment.

Answer by Stephen Cobeldick
on 16 Aug 2019

Edited by Stephen Cobeldick
on 16 Aug 2019

Your code is mixed up with the (meta-)data (i.e. the variable names named as material types), which is a very bad practice and should be avoided. You can easily use a non-scalar structure to hold your data, which makes the rest of your task trivial (i.e. better data design makes code simpler and more efficient):

S(1).typ = 'BK7';

S(1).txt = 'BK7 (N-BK7 schoot at 20C)';

S(1).fun = @(lambda) sqrt((((1.03961212).*(lambda).^2)./((lambda).^2 - (0.0060069867))) + (((0.231792344).*(lambda).^2)./((lambda).^2 - 0.0200179144)) + 1);

S(2).typ = 'FusedSilica';

S(2).txt = 'Fused Silica (Malitson 1965: n 0.21 - 3.71 micrometer at 20C)';

S(2).fun = @(lambda) sqrt((((0.6961663).*(lambda).^2)./((lambda).^2 - (0.0684043).^2)) + (((0.4079426).*(lambda).^2)./((lambda).^2 - (0.1162414).^2)) + (((0.8974794).*(lambda).^2)./((lambda).^2 - (9.896161).^2)) + 1);

S(3).typ = 'SodaLime';

S(3).txt = 'Soda Lime glass (Rubin 1985: Clear; n,k 0.31 - 4.6 micrometer at unspecified temperature)';

S(3).fun = @(lambda) 1.5130 - 0.003169.*(lambda).^2 + 0.003962.*(lambda).^-2;

S(4).typ = 'Borofloat';

S(4).txt = 'Borasilicate Crown (Schott N-BK7 at 20C)'

S(4).fun = @(lambda) sqrt(((1.03961212.*(lambda).^2)./((lambda).^2 - 0.00600069867)) + ((0.231792344.*(lambda).^2)./((lambda).^2 - 0.0200179144)) + ((1.01046945.*(lambda).^2)./((lambda).^2 - 103.560653)) + 1);

S(5).typ = 'Air';

S(5).txt = 'Air (at 15C)';

S(5).fun = @(lambda) ((0.05792105)./(238.0195 - (lambda).^-2)) + ((0.00167917)./(57.362 - (lambda).^-2)) + 1;

S(6).typ = 'NOA61';

S(6).txt = 'Norland Optical Adhesive 61 (at 25C)';

S(6).fun = @(lambda) 1.5375 + ((8290.45)./(lambda).^2) - ((2.11046*10.^8)./(lambda).^4);

[X,B] = listdlg('ListString',{S.typ}, 'SelectionMode','single')

L = str2double(inputdlg('Lambda'))

V = S(X).fun(L);

fprintf('The refractive index of %s is %g\n',S(X).typ,V);

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Stephen Cobeldick (view profile)

## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/476424-i-have-multiple-equations-that-depend-on-a-specific-value-and-would-like-matlab-to-ask-the-user-whic#comment_735880

Sign in to comment.