0% found this document useful (0 votes)
89 views8 pages

Creating Sparse Finite-Element Matrices in MATLAB Loren On The Art of MATLAB

The document discusses efficient ways to create sparse finite element matrices in MATLAB. It describes how using A(i,j)= for a sparse matrix A can be very slow, and recommends using the sparse function instead. It also explains how MATLAB stores sparse matrices internally and why directly modifying elements is inefficient.

Uploaded by

kkkraja
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
89 views8 pages

Creating Sparse Finite-Element Matrices in MATLAB Loren On The Art of MATLAB

The document discusses efficient ways to create sparse finite element matrices in MATLAB. It describes how using A(i,j)= for a sparse matrix A can be very slow, and recommends using the sparse function instead. It also explains how MATLAB stores sparse matrices internally and why directly modifying elements is inefficient.

Uploaded by

kkkraja
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

PostedbyLorenShure,March1,2007
I'mpleasedtointroduceTimDavisasthisweek'sguestblogger.TimisaprofessorattheUniversityofFlorida,andistheauthororcoauthorofmany
ofoursparsematrixfunctions(lu,chol,muchofsparsebackslash,orderingmethodssuchasamdandcolamd,andotherfunctionssuchasetree
andsymbfact).Heisalsotheauthorofarecentbook,DirectMethodsforSparseLinearSystems,publishedbySIAM,wheremoredetailsofMATLAB
sparsematricesarediscussed(http://www.cise.ufl.edu/~davis).

Contents

MATLABisSlow?OnlyIfYouUseItIncorrectly

HowNottoCreateaFiniteElementMatrix

What'sWrongwithIt?

HowMATLABStoresSparseMatrices

ABetterWaytoCreateaFiniteElementMatrix

Moral:DoNotAbuseA(i,j)=...forSparseAUsesparseInstead

TryaFasterSparseFunction

WhenFastisNotFastEnough...

MATLABisSlow?OnlyIfYouUseItIncorrectly
Fromtimetotime,Ihearcommentssuchas"MATLABisslowforlargefiniteelementproblems."WhenIlookatthedetails,theproblemistypically
duetoanoveruseofA(i,j)= ...whencreatingthesparsematrix(assemblingthefiniteelements).Thiscanbeseenintypicaluser'scode,
MATLABcodeinbooksonthetopic,andeveninMATLABitself.Theproblemiswidespread.MATLABcanbeveryfastforfiniteelementproblems,
butnotifit'susedincorrectly.

HowNottoCreateaFiniteElementMatrix
Agoodexampleofwhatnottodocanbefoundinthewathen.mfunction,inMATLAB.A=gallery('wathen',200,200)takesahugeamountof
timeaveryminormodificationcutstheruntimedrastically.I'mnotintendingtosingleoutthisonefunctionforcritiquethisisaverycommonissue
thatIseeoverandoveragain.ThisfunctionisbuiltintoMATLAB,whichmakesitanaccessibleexample.ItwasfirstwrittenwhenMATLABdidnot
supportsparsematrices,andwasmodifiedonlyslightlytoexploitsparsity.Itwasnevermeantforgeneratinglargesparsefiniteelementmatrices.
Youcanseetheentirefunctionwiththecommand:

typeprivate/wathen.m
Belowisanexcerptoftherelevantpartsofwathen.m.Thefunctionwathen1.mcreatesafiniteelementmatrixofannxbynymesh.Eachiloop
createsasingle8by8finiteelementmatrix,andaddsitintoA.

typewathen1
tic
A=wathen1(200,200)
toc

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

1/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

functionA=wathen1(nx,ny)
rand('state',0)
e1=[66286326202666820632]
e2=[38268168202838620816]
e=[e1e2e2'e1]/45
n=3*nx*ny+2*nx+2*ny+1
A=sparse(n,n)
RHO=100*rand(nx,ny)
nn=zeros(8,1)
forj=1:ny
fori=1:nx
nn(1)=3*j*nx+2*i+2*j+1
nn(2)=nn(1)1
nn(3)=nn(2)1
nn(4)=(3*j1)*nx+2*j+i1
nn(5)=3*(j1)*nx+2*i+2*j3
nn(6)=nn(5)+1
nn(7)=nn(6)+1
nn(8)=nn(4)+1
em=e*RHO(i,j)
forkrow=1:8
forkcol=1:8
A(nn(krow),nn(kcol))=A(nn(krow),nn(kcol))+em(krow,kcol)
end
end
end
end
Elapsedtimeis305.832709seconds.

What'sWrongwithIt?
Theabovecodeisfineforgeneratingamodestsizedmatrix,buttheA(i,j) = ...statementisquiteslowwhenAislargeandsparse,particularly
wheniandjarealsoscalars.Theinnertwoforloopscanbevectorizedsothatiandjarevectorsoflength8.EachA(i,j) = ...statementis
assemblinganentirefiniteelementmatrixintoA.However,thisleadstoveryminimalimprovementinruntime.

typewathen1b
tic
A1b=wathen1b(200,200)
toc

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

2/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

functionA=wathen1b(nx,ny)
rand('state',0)
e1=[66286326202666820632]
e2=[38268168202838620816]
e=[e1e2e2'e1]/45
n=3*nx*ny+2*nx+2*ny+1
A=sparse(n,n)
RHO=100*rand(nx,ny)
nn=zeros(8,1)
forj=1:ny
fori=1:nx
nn(1)=3*j*nx+2*i+2*j+1
nn(2)=nn(1)1
nn(3)=nn(2)1
nn(4)=(3*j1)*nx+2*j+i1
nn(5)=3*(j1)*nx+2*i+2*j3
nn(6)=nn(5)+1
nn(7)=nn(6)+1
nn(8)=nn(4)+1
em=e*RHO(i,j)
A(nn,nn)=A(nn,nn)+em
end
end
Elapsedtimeis282.945593seconds.

disp(norm(AA1b,1))

HowMATLABStoresSparseMatrices
Tounderstandwhytheaboveexamplesaresoslow,youneedtounderstandhowMATLABstoresitssparsematrices.AnnbynMATLABsparse
matrixisstoredasthreearraysI'llcallthemp,i,andx.ThesethreearraysarenotdirectlyaccessiblefromM,buttheycanbeaccessedbya
mexFunction.Thenonzeroentriesincolumnjarestoredini(p(j):p(j+1)-1)andx(p(j):p(j+1)-1),wherexholdsthenumericalvaluesand
iholdsthecorrespondingrowindices.Belowisaverysmallexample.First,Icreateafullmatrixandconvertitintoasparseone.Thisisonlysothat
youcaneasilyseethematrixCandhowit'sstoredinsparseform.Youshouldnevercreateasparsematrixthisway,exceptfortinyexamples.

C=[
4.50.03.20.0
3.12.90.00.9
0.01.73.00.0
3.50.40.01.0]
C=sparse(C)

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

3/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

C=
(1,1)4.5000
(2,1)3.1000
(4,1)3.5000
(2,2)2.9000
(3,2)1.7000
(4,2)0.4000
(1,3)3.2000
(3,3)3.0000
(2,4)0.9000
(4,4)1.0000
NoticethatthenonzeroentriesinCarestoredincolumnorder,withsortedrowindices.Theinternalp,i,andxarrayscanbereconstructedas
follows.Thefind(C)statementreturnsalistof"triplets,"wherethekthtripletisi(k),j(k),andx(k).ThisspecifiesthatC(i(k),j(k))isequalto
x(k).Next,find(diff(...))constructsthecolumnpointerarrayp(thisonlyworksiftherearenoallzerocolumnsinthematrix).

[ijx]=find(C)
n=size(C,2)
p=find(diff([0jn+1]))
forcol=1:n
fprintf('column%d:\nkrowindexvalue\n',col)
disp([(p(col):p(col+1)1)'i(p(col):p(col+1)1)x(p(col):p(col+1)1)])
end

column1:
krowindexvalue
1.00001.00004.5000
2.00002.00003.1000
3.00004.00003.5000
column2:
krowindexvalue
4.00002.00002.9000
5.00003.00001.7000
6.00004.00000.4000
column3:
krowindexvalue
7.00001.00003.2000
8.00003.00003.0000
column4:
krowindexvalue
9.00002.00000.9000
10.00004.00001.0000
NowconsiderwhathappenswhenoneentryisaddedtoC:

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

4/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

C(3,1)=42
[ijx]=find(C)
n=size(C,2)
p=find(diff([0jn+1]))
forcol=1:n
fprintf('column%d:\nkrowindexvalue\n',col)
disp([(p(col):p(col+1)1)'i(p(col):p(col+1)1)x(p(col):p(col+1)1)])
end

column1:
krowindexvalue
1.00001.00004.5000
2.00002.00003.1000
3.00003.000042.0000
4.00004.00003.5000
column2:
krowindexvalue
5.00002.00002.9000
6.00003.00001.7000
7.00004.00000.4000
column3:
krowindexvalue
8.00001.00003.2000
9.00003.00003.0000
column4:
krowindexvalue
10.00002.00000.9000
11.00004.00001.0000
andyoucanseethatnearlyeveryentryinChasbeenmoveddownbyoneintheiandxarrays.Ingeneral,thesinglestatementC(3,1)=42takes
timeproportionaltothenumberofentriesinmatrix.Thus,loopingnnz(A)timesoverthestatementA(i,j)=A(i,j)+...takestimeproportionalto
nnz(A)^2.

ABetterWaytoCreateaFiniteElementMatrix
Theversionbelowisonlyslightlydifferent.Itcouldbeimproved,butIleftitnearlythesametoillustratehowsimpleitistowritefastMATLABcodeto
solvethisproblem,viaaminortweak.Theideaistocreatealistoftriplets,andletMATLABconvertthemintoasparsematrixallatonce.Ifthereare
duplicates(whichafiniteelementmatrixalwayshas)theduplicatesaresummed,whichisexactlywhatyouwantwhenassemblingafiniteelement
matrix.InMATLAB7.3(R2006b),sparseusesquicksort,whichtakesnnz(A)*log(nnz(A))time.Thisisslowerthanitcouldbe(alineartime
bucketsortcanbeused,takingessentiallynnz(A)time).However,it'sstillmuchfasterthannnz(A)^2.Forthismatrix,nnz(A)isabout1.9million.

typewathen2.m
tic
A2=wathen2(200,200)
toc

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

5/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

functionA=wathen2(nx,ny)
rand('state',0)
e1=[66286326202666820632]
e2=[38268168202838620816]
e=[e1e2e2'e1]/45
n=3*nx*ny+2*nx+2*ny+1
ntriplets=nx*ny*64
I=zeros(ntriplets,1)
J=zeros(ntriplets,1)
X=zeros(ntriplets,1)
ntriplets=0
RHO=100*rand(nx,ny)
nn=zeros(8,1)
forj=1:ny
fori=1:nx
nn(1)=3*j*nx+2*i+2*j+1
nn(2)=nn(1)1
nn(3)=nn(2)1
nn(4)=(3*j1)*nx+2*j+i1
nn(5)=3*(j1)*nx+2*i+2*j3
nn(6)=nn(5)+1
nn(7)=nn(6)+1
nn(8)=nn(4)+1
em=e*RHO(i,j)
forkrow=1:8
forkcol=1:8
ntriplets=ntriplets+1
I(ntriplets)=nn(krow)
J(ntriplets)=nn(kcol)
X(ntriplets)=em(krow,kcol)
end
end
end
end
A=sparse(I,J,X,n,n)
Elapsedtimeis1.594073seconds.

disp(norm(AA2,1))

1.4211e014
Ifyoudonotknowhowmanyentriesyourmatrixwillhave,youmaynotbeabletopreallocatetheI,J,andXarrays,asdoneinwathen2.m.Inthat
case,startthematareasonablesize(anythinglargerthanzerowilldo)andaddthiscodetotheinnermostloop,justafterntripletsis
incremented:

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

6/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

len=length(X)
if(ntriplets>len)
I(2*len)=0
J(2*len)=0
X(2*len)=0
end
andwhendone,usesparse(I(1:ntriplets),J(1:ntriplets),X(1:ntriplets),n,n).

Moral:DoNotAbuseA(i,j)=...forSparseAUsesparseInstead
Avoidstatementssuchas

C(4,2)=C(4,2)+42
inaloop.Createalistoftriplets(i,j,x)andusesparseinstead.Thisadviceholdsforanysparsematrix,notjustfiniteelementones.

TryaFasterSparseFunction
CHOLMODincludesasparse2mexFunctionwhichisareplacementforsparse.Itusesalineartimebucketsort.TheMATLAB7.3(R2006b)
sparseaccountsforabout3/4thsthetotalruntimeofwathen2.m.Forthismatrixsparse2inCHOLMODisabout10timesfasterthantheMATLAB
sparse.CHOLMODcanbefoundintheSuiteSparsepackage,inMATLABCentral.
IfyouwouldliketoseeashortandconciseCmexFunctionimplementationofthemethodusedbysparse2,takealookatCSparse,whichwas
writtenforaconcisetextbookstylepresentation.Thecs_sparsemexFunctionusescs_compress.c,toconvertthetripletstoacompressedcolumn
formofA',cs_dupl.ctosumupduplicateentries,andthencs_transpose.ctotransposetheresult(whichalsosortsthecolumns).

WhenFastisNotFastEnough...
EvenwiththisdramaticimprovementinconstructingthematrixA,MATLABcouldstilluseadditionalfeaturesforfasterconstructionofsparsefinite
elementmatrices.Constructingthematrixshouldbemuchfasterthanx=A\b,sincecholisdoingabout700timesmoreworkassparseforthis
matrix(1.3billionflops,vs1.9millionnonzerosinA).Theruntimesarenotthatdifferent,however:

tic
A=wathen2(200,200)
toc
b=rand(size(A,1),1)
tic
x=A\b
toc

Elapsedtimeis1.720397seconds.
Elapsedtimeis3.125791seconds.

GettheMATLABcode
PublishedwithMATLAB7.4

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

7/8

7/1/2016

CreatingSparseFiniteElementMatricesinMATLABLorenontheArtofMATLAB

http://blogs.mathworks.com/loren/2007/03/01/creatingsparsefiniteelementmatricesinmatlab/

8/8

You might also like