matlab有限元计算程序

function [T,fail,meth]=DefineBases(T,ntries)

% [T,fail]=DefineBases(T,ntries)
%
% This function implements a heuristic algorithm to
% define the list of bases for the triangles in
% the mesh T. If it is successful, it adds the
% field Bases to T; T.Bases(i) is the index of
% the base of triangle i in T.Edges.
%
% The input ntries determines how many times
% the heuristic algorithm is attempted; the default
% is ntries=4. (There is a random element to
% the algorithm, so it can be attempted repeatedly.
% The probability of success increases with ntries,
% but obviously so does the execution time.)
%
% The output flag fail is 0 if the algorithm succeeds
% (so that T.Bases is added to T) and nonzero if
% the algorithm fails (in which case T is unchanged).
%
% T.Bases is used by the newest node refinement algorithm.
% See LocalRefine1 for details.

% The following algorithm is based on a linear programming
% formulation of the problem. If the linear program
% has an integer-valued solution, then DefineBases succeeds.
% However, this is not guaranteed. The code tries four
% non-random cost functions and then ntries-4 random
% cost functions, if necessary.

if nargin<2
ntries=4;
end

Nt=size(T.Elements,1);
Ne=size(T.Edges,1);

% First, get the triangle-edge incidence matrix

A=TriEdgeIncidence(T);

% Define the right-hand side for the LP constraints:

b=ones(Nt,1);

% Get the lengths of the edges in T:

c=zeros(Ne,1);
for i=1:Ne
c(i,1)=norm(T.Nodes(T.Edges(i,1),:)-T.Nodes(T.Edges(i,2),:));
end

% Weight boundary edges by half:

i=find(T.EdgeEls(:,2)<=0);
c(i)=0.5*c(i);

% Define ntries different cost functions.
%
% 1: Maximize the total length of the chosen bases.
% 2: Maximize the number of bases chosen.
% 3: Minimize the total length of the chosen bases.
% 4: Minimize the number of bases chosen.
% 5,6,...,ntries: random

C=[c,ones(Ne,1),-c,-ones(Ne,1)];
for i=5:ntries
C=[C,rand(Ne,1)];
end

% Invoke the simplex method up to ntries times, looking
% for an integer-valued solution:

fail=1;
for i=1:ntries
x=rsimplex(C(:,i),A,b,zeros(Ne,1),ones(Ne,1));
if norm(x-round(x))<100*eps*norm(x)
fail=0;
meth=i;
break
end
end

if fail
meth=0;
return
else

% An integer-valued solution was found.
% x now indicates the edges chosen as bases. Loop through
% the triangles and record the base of each:

T.Bases=zeros(Nt,1);
for i=1:Nt
e=abs(T.Elements(i,:));
T.Bases(i)=e(find(x(e)==1));
end

end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function A=TriEdgeIncidence(T)

% A=TriEdgeIncidence(T)
%
% This function computes the triangle-edge incidence
% matrix of the mesh T. The result is an Nt by Ne
% sparse 0-1 matrix.

Nt=size(T.Elements,1);
Ne=size(T.Edges,1);
A=sparse(Nt,Ne);

for i=1:Nt
A(i,abs(T.Elements(i,

:)))=1;
end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function x=rsimplex(c,A,b,l,u)

% x=rsimplex(c,A,b,l,u)
%
% This function applies the revised simplex method to the LP
%
% max c'x
% s.t. Ax=b
% l<=x<=u

% Get the problem size

[m,n]=size(A);

% Get a value for scaling:

sval=max([max(max(abs(A))),max(abs(b))])*1e5*eps;

% Set up the Phase 1 LP

% Create the augmented cost vector and constraint matrix

c1=zeros(m+n,1);
A1=[A,speye(m)];

% Assign the basic variables

bfs.B=n+1:n+m;

% Assign the nonbasic variables

bfs.N1=[];
bfs.N2=[];
bfs.N3=[];
bfs.x=zeros(n+m,1);
for j=1:n
if l(j)>-inf
bfs.x(j)=l(j);
bfs.N1=[bfs.N1,j];
elseif u(j)bfs.x(j)=u(j);
bfs.N2=[bfs.N1,j];
else
bfs.N3=[bfs.N3,j];
end
end

% Solve for the basic variables

bfs.x(n+1:n+m)=b-A*bfs.x(1:n);

% Create the extended constraints and
% define the extended cost vector

l1=[l;zeros(m,1)];
u1=[u;zeros(m,1)];
for i=1:m
if bfs.x(n+i)>=0
l1(n+i)=0;
u1(n+i)=inf;
c1(n+i)=-1;
else
l1(n+i)=-inf;
u1(n+i)=0;
c1(n+i)=1;
end
end

% Now invoke rsimplex_bfs to solve the Phase 1 LP

bfs=rsimplex_bfs(c1,A1,b,l1,u1,bfs);

% If the optimal value in Phase 1 is not zero, then the
% program is infeasible.

if any(abs(bfs.x(n+1:n+m))>sval)

error('The LP is infeasible')

% Otherwise, invoke Phase 2

else

% Change the bounds for the artificial variables

l1(n+1:n+m)=zeros(m,1);
u1(n+1:n+m)=zeros(m,1);

% Change the extended cost vector

c1=[c;zeros(m,1)];

% Apply the simplex method again

[bfs,tflag]=rsimplex_bfs(c1,A1,b,l1,u1,bfs);

x=bfs.x(1:n);
z=c'*x;
if tflag==1
error('The LP is unbounded')
end

end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [bfs,tflag]=rsimplex_bfs(c,A,b,l,u,bfs);

% [bfs,termcode]=rsimplex_bfs(c,A,b,l,u,bfs);
%
% This function applies the revised simplex method to the LP
%
% max c'x
% s.t. Ax=b
% l<=x<=u
%
% An initial basic feasible solution bfs must be provided.
% The basic feasible solution is described by a structure
% containing the following fields
%
% bfs.x - the BFS itself (an n-vector)
% bfs.B - the index set for the basis
% bfs.N1 - the index set for the nonbasic variables at
% their lower bounds
% bfs.N2 - the index set for the nonbasic variables at
% their upper bounds
% bfs.N3 - the index set for the unrestricted nonbasic
% variables
% (The index sets are all row vectors.)
%
% The return code termcode indicates how the simplex method
% terminated:
%
% termcode==0 - Optimal solution found
% termcode==1 - LP is unbounded

% Get the problem size

[m,n]=si

ze(A);

% Get a value for scaling:

sval=max([max(max(abs(A))),max(abs(b))])*1e5*eps;

% Main iteration

done=0;
while ~done

% Get the basis A_B matrix and factor it

AB=A(:,bfs.B);
[L,U]=lu(AB);

% Gather the indices of the nonbasic variables

N=[bfs.N1,bfs.N2,bfs.N3];
n1=length(bfs.N1);
n2=length(bfs.N2);
n3=length(bfs.N3);

% Step 1: Compute the dual vector y and the vector of
% prices

y=L'\(U'\c(bfs.B));
cbar=c(N)-A(:,N)'*y;

% Now choose the entering variable

% First identify all of the candidates:

i1=find(cbar(1:n1)>sval);
i2=find(cbar(n1+1:n1+n2)<-sval);
i3=find(abs(cbar(n1+n2+1:n1+n2+n3))>sval);

% If there are no candidates, the current BFS is optimal

if isempty(i1)&isempty(i2)&isempty(i3)

done=1;
break;

end

% If there are candidates, choose the entering variable by
% the smallest-subscript rule.

pc=min([bfs.N1(i1),bfs.N2(i2),bfs.N3(i3)]);
if isempty(bfs.N1)
i1=[];
else
i1=find(bfs.N1==pc);
end
if ~isempty(i1)
Nflag=1;
pc=bfs.N1(i1);
else
if isempty(bfs.N2)
i2=[];
else
i2=find(bfs.N2==pc);
end
if ~isempty(i2);
Nflag=2;
pc=bfs.N2(i2);
else
if isempty(bfs.N3)
i3=[];
else
i3=find(bfs.N3==pc);
end
if ~isempty(i3)
if cbar(n1+n2+i3)>0
Nflag=3;
else
Nflag=4;
end
pc=bfs.N3(i3);
else
error('Inconsistency in choice of entering variable')
end
end
end

% Step 2: Find the changes in the basic variables and choose the
% leaving variable

d=U\(L\A(:,pc));

% Identify the candidates for leaving variables

% First look among the basic variables

pr=[];
len=0;
for i=1:m

if (d(i)>sval & (Nflag==1|Nflag==3)) | ...
(d(i)<-sval & (Nflag==2|Nflag==4))
if l(bfs.B(i))>-inf
len=len+1;
pr(len,:)=[i,abs((bfs.x(bfs.B(i))-l(bfs.B(i)))/d(i))];
end
elseif (d(i)>sval & (Nflag==2|Nflag==4)) | ...
(d(i)<-sval & (Nflag==1|Nflag==3))
if u(bfs.B(i))len=len+1;
pr(len,:)=[i,abs((bfs.x(bfs.B(i))-u(bfs.B(i)))/d(i))];
end
end

end

% Now look at the entering variable itself

if Nflag==1

% The entering variable is increasing

if u(pc)len=len+1;
pr(len,:)=[0,u(pc)-bfs.x(pc)];
end

elseif Nflag==2

% The entering variable is decreasing

if l(pc)>-inf
len=len+1;
pr(len,:)=[0,bfs.x(pc)-l(pc)];
end

end

if len==0

% No variable must leave the basis, so the LP is unbounded

done=1;
tflag=1;
return


end

% Now we can choose the candidates for the leaving variables

t=min(pr(:,2));
k=find(abs(pr(:,2)-t)
% Check to see if the entering variable should immediately leave

if pr(k(length(k)),1)==0

% The entering variable leave immediately. We just switch
% its index from N1 to N2 or vice versa

ipr=pc;
pr=0;
if Nflag==1
bfs.N2=[bfs.N2,bfs.N1(i1)];
bfs.N1=[bfs.N1(1:i1-1),bfs.N1(i1+1:n1)];
elseif Nflag==2
bfs.N1=[bfs.N1,bfs.N2(i2)];
bfs.N2=[bfs.N2(1:i2-1),bfs.N2(i2+1:n2)];
else
error('Inconsistency in entering-leaving variable')
end

elseif length(k)==1

% There is only one candidate for the leaving variable

ipr=bfs.B(pr(k,1));
pr=pr(k,1);

else

% There are multiple candidates to leave the basis.
% Choose the leaving variable according to the
% smallest-subscript rule.

[ipr,k1]=min(bfs.B(pr(k,1)));
pr=pr(k(k1),1);

end

% Finally, update the index sets and the new BFS

if Nflag==1 | Nflag==3 % Entering variable increases

bfs.x(bfs.B)=bfs.x(bfs.B)-t*d;
bfs.x(pc)=bfs.x(pc)+t;

else % Entering variable decreases

bfs.x(bfs.B)=bfs.x(bfs.B)+t*d;
bfs.x(pc)=bfs.x(pc)-t;

end

% Update the index sets unless the entering variable
% is also the leaving variable.
if pc~=ipr

if Nflag==1 & d(pr)>0
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N1(i1);
bfs.N1(i1)=tmp;
elseif Nflag==1 & d(pr)<0
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N1(i1);
bfs.N1=[bfs.N1(1:i1-1),bfs.N1(i1+1:n1)];
bfs.N2(n2+1)=tmp;
elseif Nflag==2 & d(pr)<0
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N2(i2);
bfs.N2=[bfs.N2(1:i2-1),bfs.N2(i2+1:n2)];
bfs.N1(n1+1)=tmp;
elseif Nflag==2 & d(pr)>0
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N2(i2);
bfs.N2(i2)=tmp;
elseif (Nflag==3 & d(pr)>0) | (Nflag==4 & d(pr)<0)
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N3(i3);
bfs.N3=[bfs.N3(1:i3-1),bfs.N3(i3+1:n3)];
bfs.N1(n1+1)=tmp;
else
tmp=bfs.B(pr);
bfs.B(pr)=bfs.N3(i3);
bfs.N3=[bfs.N3(1:i3-1),bfs.N3(i3+1:n3)];
bfs.N2(n2+1)=tmp;
end

end

end
tflag=0;

相关文档
最新文档