dividing on 0 in your denominator.

Dear MATLAB helpers,
I'm trying to run a project for 2 month but it got stuck this warning every time and this influence my results too much.
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.345970e-19.
The warning line:
s=K(fdof,fdof)\(f(fdof)-K(fdof,pdof)*dp);
Also I attached variables value such as K, it may help.
I will be thankful for any suggestion.
All the best

2 Comments

From your warning line it seems you are dividing on 0 in your denominator.

Sign in to comment.

Answers (1)

Adam
Adam on 27 Aug 2014
Your matrix K has a rank of just 7, it needs to be 15 (equal to its size) in order to be considered well conditioned.
There are a number of ways to condition a singular (or close to) matrix and the best probably depends on what you will be using it for so I can't really say what would be best in this case.
What I have done in the past, which is a fairly standard method, is to boost the leading diagonal slightly.
I just tried this on your K matrix and multiplying the leading diagonal by 1.01 resulted in an invertible matrix of full rank (15).
I'm not suggested you should just go ahead and multiply by 1.01 as adding 1% to your leading diagonal may not suit your purpose, but if it does then that could be one solution for you.

5 Comments

Adam
Adam on 27 Aug 2014
Edited: Adam on 27 Aug 2014
for i = 1:15
K(i,i) = K(i,i) * 1.01;
end
would do what I suggested though there would be quicker ways to change the leading diagonal values only than in a for loop. For a quick test on a size 15 matrix though that worked fine.
You can use diag to extract the leading diagonal of a matrix to do the maths on, but then you have to insert those values back in along the leading diagonal.
Adam
Adam on 27 Aug 2014
Edited: Adam on 27 Aug 2014
Sorry, I typed that in from my head rather than the code I used. I have corrected it now to use i for row and column index instead of j for column index.
Try the above code again now with correction.
Adam did just a small mistake on the indexing and you have to adapt the length of the loop for your problem.
for i = 1:length(K)
K(i,i) = K(i,i) * 1.01;
end
If you want a one liner :
K(1:length(K)+1:end) = K(1:length(K)+1:end)*1.01;
Yeah, that one-liner will definitely be more efficient for large k.
How I wish Matlab had operators like *= to make code like that look so much nicer!!
Sorry I didn't run the project as I don't have the time to at the moment.
For the example K matrix you gave in the original question adding 1% to the leading diagonal was enough to make the matrix non-singular, but it may not always be. In some cases you may need to boost it more so try playing around with higher multipliers than 1.01, bearing in mind that you don't want to go too high as you will start to skew the data in your matrix too much.
I use this technique for conditioning a matrix to be used for inversion of a covariance matrix in a Gaussian classifier, but it should work for other cases too with maybe a larger multiplier.

Sign in to comment.

Categories

Find more on Linear Algebra in Help Center and File Exchange

Tags

No tags entered yet.

Asked:

on 27 Aug 2014

Commented:

on 28 Aug 2014

Community Treasure Hunt

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

Start Hunting!