How do I make a loop write to an asymetric pre-allocated array?

1 view (last 30 days)
Hello,
I have the following situation. I have a function that can be expressed as y = f(x)*exp(g(x)*t). I would like to plot this function in surface form for ,say, x= .001:.001:1 and t = 0:.01:5. So far my script works when it looks like this:
x = 1:10;%Excitation energies
M=zeros(10,10);%Pre-allocate 10 by 10 array
for i= x%Repeat for vaues of N
t = 1:10;%Time M(i,:)= (3 * i ^ 2 + 2 * i + 3) * exp(-.02 * t);%decay function
end
surface(N,t,M)
shading flat
but I would like for it to run on with the .001:.001:1 and 0:.01:5. The problem I am having is that if I change the pre-allocation array to accommodate the 1000 values of x and 500 values of t the scrip no longer works and I receive the following error message:
Subscripted assignment dimension mismatch.
I get this message regardless of which pre-allocation dimension I change to 1000 or 500. If you can help me out here I'd appreciate it. If possible, can I get an explanation of where I am going wrong?

Accepted Answer

dpb
dpb on 10 Aug 2013
You didn't do much at all like I did, actually... :)
The first case has identically the same problem as initially--you've got two vectors of differing lengths trying to operate between them on a point-by-point basis.
If you're not going to create the function handle then you have to write the expression to use the results of the meshgrid output directly and certainly can't evaluate it before having defined the grid points.
As for the 'ans=' line; that was output from the command window I posted to illustrate I got identically the same solution as yours by comparing my 'z' results to the 'M' array obtained by running your solution where the two lengths were the same simply to demonstrate the equivalence.
To do it w/o the function handle...
x = 0.001:0.001:1; t = 0.01:0.01:5;
[X,T] = meshgrid(x,t);
M = (3*X.^2+2*X+3).*exp(-0.02*T);
Those lines are all you need (or want).
doc meshgrid % for more details
It's handy to use the function handle; then you don't have to write the expression but once't...you seem to have lost that detail entirely.
f=@(x,t) ([(3*x.^2 + 2*x + 3).*exp(-0.02*t)]);
Execute the above first--it creates a handle to the function as defined by the expression that can be invoked by f(x,t) at will just as any other function. Look up function handles in the doc for details.
Once you have defined it, then you can create the ranges for the two variables, use meshgrid to expand to the planar grid and call the function--
x = 0.001:0.001:1; t = 0.01:0.01:5;
[X,T] = meshgrid(x,t);
M=f(X,T);
The advantage is the succinctness in the evaluation, particularly if need to do it more than once.

More Answers (3)

dpb
dpb on 9 Aug 2013
x=[1:10]; %Excitation energies
M=zeros(length(x)); %Preallocate array
for i=x
t = 1:10
M(i,:)= (3*i^2 + 2*i + 3)*exp(-0.02*t);
end
Indeed, you allocated a square array for the results so if you change one or the other lengths you'll have a mismatch. Using the inner array in conjunction w/ a loop on a single value on the outer is also kinda klunky; this is perfect location for meshgrid and writing your function to be evaluated w/ vector inputs. The "dot" operators are needed there. It's also handy to make a function handle for the function...
% make a function handle -- NB the .*
>> f=@(x,t) ([(3*x.^2 + 2*x + 3).*exp(-0.02*t)]')
f =
@(x,t)([(3*x.^2+2*x+3).*exp(-0.02*t)]')
>> % set up data ranges
>> x=[1:10]; t=[1:10];
>> [X,Y]=meshgrid(x,t);
>> z=f(X,Y);
>> all(all(z==M)) % had done your loop solution earlier...
ans = % confirms got same answer
1
>> x=[0.001:0.001:1]; t=[0:0.01:5]; % your other ranges...
>> [X,Y]=meshgrid(x,t);
>> z=f(X,Y);
>> surface(t,x,z)
NB: last reordering -- to keep orientation or your loop solution also note the ' transpose on the function result. If don't care about that, then can return to natural order.

Chris
Chris on 10 Aug 2013
dpb, thank you for the help. I put your code in and after eliminating the red warnings the scrip/function looks like this: function bright
x = .001:.001:1;
t = .01:.01:1;
M = ((3 * x .^2 +2 * x + 3) .* exp(-0.02 * t));
% set up data rang
x = 1:10; t=1:10;
[X,Y]=meshgrid(x,t);
z = f(X,Y);
all(all(z==M)) % had done your loop solution earlier...
ans = 1;
x = 0.001:.001:1; t = .01:.01:5; % your or ranges.the..
[X,Y] = meshgrid(x,t);
z = f(X,Y);
surface(t,x,z)
but when I run it I get a error:
error using .* matrix dimensions must agree
does this happen because I put in the x= range, t = range at the top? the function wouldn't run without defining x and t before M. Could this cause a problem later on when x = 1:10 and t = 1:10? Also, there is an orange caution with the ans = 1 line because ans can be rewritten, I am not really sure what that means other than it will get a new value. Don't mean to be a pain, just really new to this.
  1 Comment
dpb
dpb on 10 Aug 2013
Chris, please move your followup question to the comments area instead of answers...

Sign in to comment.


Chris
Chris on 12 Aug 2013
dpb,
I tried both the function handle and the plain script and they worked, thanks for your help on this, I really appreciate it.
  1 Comment
dpb
dpb on 12 Aug 2013
Again, PLEASE use the comment section for comments/questions/etc., and reserve the ANSWER section for actual answers to the question posed.
It would be a_good_thing (tm) to move these two answers to comments and then I'll followup and delete the complaints to clean up.
If going to the trouble of using the forum might at least try to make it useful as possible by not cluttering up.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!