Why is fscanf reading a 0 from my input file?
8 views (last 30 days)
Show older comments
I am trying to run the code that is posted below with the input file that is also posted below. The issue that I cannot get passed is when I click run, I continue to get an error that says "Index in position 1 is invalid. Array indices must be positive integers or logical values." Do you have any idea why? I know it occurs during the second time the for loop that is reading the coordinates from the file but I cannot seem to figure out why it is indexing 0 instead of the values from the file.
Here is the code:
function trussEF(file_name, theta);
% OPEN DATA FILE
fid = fopen('parte.txt', 'r');
%READ DATA - READ Constants
E=fscanf(fid, '%d', 1);
display(E)
% READ DATA - READ NODE DATA - read the number of nodes in the truss
Number_nodes=fscanf(fid, '%d', 1);
display(Number_nodes)
% Read the coordinates for each node
for i=1:Number_nodes
Node=fscanf(fid, '%d', 1);
display(Node)
Coordinate(Node, 1)=fscanf(fid, '%g', 1);
Coordinate(Node, 2)=fscanf(fid, '%g', 1);
Height = fscanf(fid, '%s', 1);
%Change height of Node B,D,F with a varrying theta
if (Height == 'B') || (Height == 'D') || (Height == 'F') %Sets the coordinate for nodes with positions that vary with theta
Coordinate(Node,2)=10*tand(theta);
end
end
% READ DATA - READ ELEMENT DATA - Now read the number of elements and the element definition
Number_elements=fscanf(fid, '%d', 1);
display(Number_elements)
K=zeros(2*Number_nodes, 2*Number_nodes); %empty global stiffness matrix
for i=1:Number_elements
Element=fscanf(fid, '%d', 1);
Node_from=fscanf(fid, '%d', 1);
Node_to=fscanf(fid, '%d', 1);
Node_To(i) = Node_to;
Node_From(i) = Node_from;
dx=Coordinate(Node_to,1)-Coordinate(Node_from,1);
dy=Coordinate(Node_to,2)-Coordinate(Node_from,2);
Length=sqrt(dx^2 + dy^2);
length(i) = Length;
%populating the Stiffness Matricies
c=dx/Length; % cosine
cm(i) = c;
s=dy/Length; % sine
sm(i) = s;
Area = fscanf(fid,'%d', 1); % grabbing the cross sectional area for each member
% get local stiffness matrix ke
ke=(E*Area)/Length*[c^2 c*s -c^2 -c*s; %NEED TO ADD IN A AFTER YOU HAVE CODE FOR IT DONT FORGET
c*s s^2 -c*s -s^2;
-c^2 -c*s c^2 c*s;
-c*s -s^2 c*s s^2];
ni = 2*Node_from-1; % map left node of the truss global dof
nj = 2*Node_to-1; % map right node of the truss global dof
% map local dof to GLOBAL STIFFNESS MATRIX, K
K(ni:ni+1,ni:ni+1)=K(ni:ni+1,ni:ni+1)+ke(1:2,1:2);
K(ni:ni+1,nj:nj+1)=K(ni:ni+1,nj:nj+1)+ke(1:2,3:4);
K(nj:nj+1,ni:ni+1)=K(nj:nj+1,ni:ni+1)+ke(3:4,1:2);
K(nj:nj+1,nj:nj+1)=K(nj:nj+1,nj:nj+1)+ke(3:4,3:4);
end
% READ DATA - READ REACTION DATA - Now read in the reactions
Number_reactions = fscanf(fid, '%d', 1);
RAC = []; %Keeps track of rows and columns to reduce later
if (2*Number_nodes ~= (Number_elements + Number_reactions))
error('Invalid number of nodes, elements, and reactions');
end
for i=1:Number_reactions;
Reaction = fscanf(fid, '%d', 1);
Node=fscanf(fid, '%d', 1);
Direction = fscanf(fid, '%s', 1);
if ((Direction == 'y') || (Direction == 'Y'))
K(2*Node, Number_elements+Reaction)=K(2*Node,Number_elements+Reaction)+1; % same code as A, but mapped to K instead of M
RAC = [RAC 2*Node]; %populates the rows and columns needed to reduce
elseif ((Direction == 'x')||(Direction == 'X'))
K(2*Node-1, Number_elements+Reaction)=K(2*Node-1,Number_elements+Reaction)+1; % same code as A, but mapped to K instead of M
RAC = [RAC (2*Node-1)]; %populates the rows and columns needed to reduce
else
error('Invalid direction for reaction')
end
end
% READ DATA - READ EXTERNAL FORCE DATA - Now read in the external forces
External=zeros(2*Number_nodes,1);
Number_forces=fscanf(fid, '%d', 1);
for i=1:Number_forces
Node =fscanf(fid, '%d', 1);
Force=fscanf(fid, '%g', 1);
Direction = fscanf(fid, '%g', 1);
External(2*Node-1)=External(2*Node-1)-Force*cos(Direction*(pi/180));
External(2*Node) =External(2*Node) -Force*sin(Direction*(pi/180));
end
External; %isplay external forces
% COMPUTE FORCES - Solve the system of equations
K_RAC = K;
K_RAC(RAC,:) = [];
K_RAC(:,RAC) = []; %Reduced global stiffness Matrix
F_RAC = External;
F_RAC([RAC],:) = []; %Reduced Force Matrix
Q = K_RAC\F_RAC; %Computed Displacements
displacement = [0 Q(1) Q(3) Q(5) Q(7) Q(9) Q(11) Q(13);
0 Q(2) Q(4) Q(6) Q(8) Q(10) Q(12) 0]'; %Sets up the displacement Matrix, although manually.
scalar = 10000; %Makes the deflection more visible in the plots
DisplacedCoordinate = Coordinate +(displacement*scalar);
for k = 1:Number_elements
hold on
i = Node_From(k);
j = Node_To(k);
x = [Coordinate(i,1) Coordinate(j,1)];
y = [Coordinate(i,2) Coordinate(j,2)];
plot(x,y, 'b')
new_x = [DisplacedCoordinate(i,1) DisplacedCoordinate(j,1)];
new_y = [DisplacedCoordinate(i,2) DisplacedCoordinate(j,2)];
plot(new_x,new_y, 'r')
Stress = (E/(length(k)))*([-cm(k) -sm(k) cm(k) sm(k)]*[displacement((2*i)-1) displacement((2*i)) displacement((2*j)-1) displacement((2*j))]');
fprintf('Stress in element %g = %g\n', k, Stress)
end
%Aspects of the plot ( visal)
xlim([-1 42])
ylim([-4 20])
tline = ('Displaced Coordinates are scaled by 10000 for clarity');
text(0,-2,tline)
legend('Unloaded Truss', 'Deformed Truss', 'Location', 'Best')
end
And here is the input file data (file name is parte):
29500000
14
1 0 0
2 0 .2
3 .2 0
4 .2 .2
5 .4 0
6 .4 .2
7 .6 0
8 .6 .2
9 .8 0
10 .8 .2
11 1 1.5
12 1 .2
13 1.2 1.5
14 1.2 .2
31
1 1 3
2 3 5
3 5 7
4 7 9
5 9 11
6 11 13
7 2 4
8 4 6
9 6 8
10 8 10
11 10 12
12 12 14
13 1 2
14 3 4
15 5 6
16 7 8
17 9 10
18 11 12
19 13 14
20 1 4
21 3 6
22 5 8
23 7 10
24 9 12
25 11 14
26 2 3
27 4 5
28 6 7
29 8 9
30 10 11
31 12 13
3
1 1 X
2 2 X
3 2 Y
2
13 10000 180
14 10000 180
Any help would be greatly appreciated!
0 Comments
Accepted Answer
Walter Roberson
on 23 Apr 2023
Your code has
Height = fscanf(fid, '%s', 1);
%Change height of Node B,D,F with a varrying theta
if (Height == 'B') || (Height == 'D') || (Height == 'F') %Sets the coordinate for nodes with positions that vary with theta
Coordinate(Node,2)=10*tand(theta);
end
The %s format skips all leading whitespace and then reads the next string.
Your code has already read in the
29500000
14
1 0 0
so the leading whitespace for the %s is the newline after the second 0 there, leaving the code positioned at the beginning of the
2 0 .2
So the character vector '2' is read in for Height. 'S' is not any of 'B' or 'D' or 'F' so converting the value by 10*tand() is not done.
The file is now positioned at the end of the '2' on the line. The next loop iteration
Node=fscanf(fid, '%d', 1);
is going to speak the leading whitespace (between the end of the '2' and the '0') and read in Node as numeric 0.
If your input format involves optional characters at the end of line, then you should be reading a line at a time and parsing it. In such a situation consider using textscan() with '%f%f%f%[^\n]' format
Side note: when you use a %s format the value read in could be indefinitely long, not necessarily a scalar character. You should not be using == to compare an indefinite-length character vector to anything: you should be using strcmp() or using string() operations
0 Comments
More Answers (0)
See Also
Categories
Find more on String 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!