MATLAB Answers

Efficient way of finding numbers from one matrix in another, not using for loops

3 views (last 30 days)
JLV
JLV on 1 Jan 2020
Commented: JLV on 1 Jan 2020
I have always been shown how to do this using for loops whilst at University, but with a large number of rows, the current for loop takes 10 minutes and there are a lot more implementation steps going forward which will use a similar technique, which would take hours
I have the following code, the first part with the help of the MATLAB community. All files are attached.
clear
clc
ElementFibreTensor = dlmread('ElementResultsUnedited.txt','',3,0); %Fibre Orientation @ Nodes. Read text file, first few lines not needed
fmt1 = '"TET4{%f%*f%*f%*f%*f%*s%*f%*f%f%f%f%f}"'; % note the ignored fields! Star after % is ignore
opt1 = {'HeaderLines',4,'CollectOutput',true}; %First four lines of text not required
[fid1,msg1] = fopen('NodeNosatElementsUnedited.txt','rt'); %Opens file
assert(fid1>=3,msg1) %Checks if file can open, if not message will pop up.
NodesatElements = textscan(fid1,fmt1,opt1{:}); %Reads File line by line
fclose(fid1); %Closes file
NodesatElements = NodesatElements{1}; %Display Data
[numRows1,numCols1] = size(ElementFibreTensor); %Size of array
for i = 1:numRows1
TempVar1 = ElementFibreTensor(i,1); %Collate ElementIDs at Elements ONLY assoicated with Fibre Orientation Tensor
FindLoc1 = find(NodesatElements(:,1) == TempVar1); %Collate Node Numbers at Elements ONLY assoicated with Fibre Orientation Tensor
ElementNodes(i,:) = NodesatElements(FindLoc1,:);
%[ElementID, Nodes 1-4 associated with ElementID]
end
I am particularly looking to simplify how I use the for loop. What I am currently doing is asking MATLAB to look at the first columnt of ElementMesh ID's (from one file) and trying to find the nodes numbers associated with the particular Element ID. There are over a quarter of a million Element ID's, but I don't know how I would do this without a for loop, I haven't so far come across any functions to do this. As a similar method will be used in the future to find co-ordinates, I thought it would be useful to solve now and understand a new way of performing the action.

  0 Comments

Sign in to comment.

Accepted Answer

Stephen Cobeldick
Stephen Cobeldick on 1 Jan 2020
Edited: Stephen Cobeldick on 1 Jan 2020
Your code's slowness is partly due to the fact that you are expanding the output array ElementNodes on each loop iteration: this forces MATLAB to move the entire array in memory on each loop iteration, which is very inefficient. You can avoid this by preallocating the output array before the loop, e.g.:
ElementNodes = nan(numRows1,size(NodesatElements,2));
for i = 1:numRows1
...
ElementNodes(i,:) = ...
end
However probably the fastest solution is to use ismember's two outputs:
[idx,idy] = ismember(ElementFibreTensor(:,1),NodesatElements(:,1));
ElementNodes2 = NodesatElements(idy(idx),:);
Compare the run times:
Elapsed time is 656.365 seconds. % Your code...
Elapsed time is 252.188 seconds. % ... with preallocated output array.
Elapsed time is 0.0380042 seconds. % Using ISMEMBER.
You can use isequal to compare the outputs of the different methods.

  3 Comments

JLV
JLV on 1 Jan 2020
I will preallocate my code now.
ElementNodes2 = NodesatElements(idy(idx),:)
Having read the help, I know what idx and idy are but I don't see how the above line gives me the final result (which is correct) as it only finds the lowest index.
Stephen Cobeldick
Stephen Cobeldick on 1 Jan 2020
"...as it only finds the lowest index."
Your own code assumes exactly one matching value on each loop iteration (the indexing into ElementNodes makes this clear, as your code will throw an error if there are zero/multiple matches), so your comment is rather moot: if there is always exactly one match for one value (like in your code) then the "lowest" and the "highest" indices (and indeed all the indices in between...) are one and the same: the index of that one match. So why would it matter?
The ismember code is not exactly equivalent because it can return zero/multiple matches, but as this is not the case in your code, nor in your data. If you have data where that can occur, you need to decide if that is appropriate or not (and then what steps might be needed to handle it).
JLV
JLV on 1 Jan 2020
Thank you, I was getting confused with the example in the help and the line above.

Sign in to comment.

More Answers (0)

Products


Release

R2019b