comparing columns between differently sized matrices
Show older comments
Hi, I am writing a finite element analysis code in MATLAB using tetrahedral elements. In the formulation of the problem, I have a 3xM surface connectivity matrix containing global node numbers and I have a 4xN volume connectivity matrix where M is the number of surfaces and N is the number of elements (M≠N). Each column in the surface connectivity matrix represents the surface number and each column in the volume connectivity matrix represents the element number. I need to compare each column of the 3xM surface connectivity matrix to each column of the 4xN volume connectivity matrix to determine which element number corresponds to each surface. Example matrices are given below.
surface connectivity matrix (3xM)
1 4 4 1
3 1 7 4
2 2 2 7
Volume connectivity matrix (4xN)
1 1 1 1 3 4
4 8 7 7 2 7
7 3 8 9 8 2
2 2 2 8 10 10
As can be seen in this example surface #1 corresponds to element #2, surface #2 corresponds to element #1, surface #3 corresponds to elements #1 and #6 (this surface is shared between two elements) etc. To complicate matters, the global node ordering for the surfaces is different than the ordering for the element numbers, but the ordering doesn’t matter. I can perform the comparison using a for loop (looping M times) and searching the entire 4xN matrix during each loop iteration, but since M and N are >10^5, the computation time is unreasonable. Is there a way to perform this comparison operation in a vectorized way to avoid loops?
Answers (2)
Fangjun Jiang
on 29 Sep 2011
SCM=[1 4 4 1
3 1 2 4
2 2 7 7];
VCM=[1 1 1 1 3 4
4 8 7 7 2 7
7 3 8 9 8 2
2 2 2 8 10 10];
M=size(SCM,2);
N=size(VCM,2);
CORRESP=false(M,N);
for k=1:M
for j=1:N
CORRESP(k,j)=all(ismember(SCM(:,k),VCM(:,j)));
end
end
CORRESP =
0 1 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 1
1 0 0 0 0 0
It shows surface #1 corresponds to element #2, surface #2 corresponds to element #1, surface #3 corresponds to elements #1 and #6, surface #4 corresponds to elements #1.
2 Comments
Joel
on 29 Sep 2011
Fangjun Jiang
on 29 Sep 2011
Can you show your code so we understand how the loop is done?
Joel
on 29 Sep 2011
6 Comments
Fangjun Jiang
on 29 Sep 2011
Not using a for-loop doesn't necessarily mean fast. There are many factor can impact the efficiency. In your code, double() and sum() seem to be unnecessary. You can use all() for that. I hope you pre-allocate elem.
Again, show your actual code so others can point out any place that can be improved. There are many examples on this forum that the best approach is application dependent.
Joel
on 29 Sep 2011
Fangjun Jiang
on 29 Sep 2011
So your algorithm is to compare the whole VCM matrix(4xN) with each column of SCM matrix(3xM) at a time, the result b is also a 4xN matrix. You then check if any of the b column sums to 3.
When N is large (10^5), I think this might not be efficient. I think you agree that my double-loop algorithm works too. Why don't you time both to see the difference. I'll probably do it too when I have spare time.
Jan
on 29 Sep 2011
SUM operates on LOGICAL arrays, so there is no need to cast to DOUBLE in "b=double(ismember( ..."
Joel
on 29 Sep 2011
Fangjun Jiang
on 30 Sep 2011
Now I thought it more, I think your approach is probably most efficient. I can't think of any other ways. Don't be obsessed with "no-loop". The loop in new versions of MATLAB is very efficient. There are functions like cellfun(), arrayfun(), bxsfun() etc that can be used to eliminate the loop but I don't think there will be a good use for your case.
If you are still interested in improving the efficiency of your code, many other experts can probably point out other areas to improve if you post your code.
Categories
Find more on Matrix Indexing 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!