考虑帕累托最优的拓扑优化方法matlab仿真

function ParetoOptimalTracing(nelx,nely,desVolFrac,problem,volDecrMax,filterRadius)
% Generate pareto-optimal topologies via fixed point iteration
% Author: Krishnan Suresh; [email protected]
% Reference: "A 199-line Matlab Code for Pareto-Optimal Tracing in Topology Optimization", 
%             K. Suresh, Structural and Multidisciplinary Optimization, DOI:10.1007/s00158-010-0534-6
% Acknowledgements: "A 99 line topology optimization code written in Matlab"            
%                   by Ole Sigmund (2001), Structural and Multidisciplinary Optimization, 
%                   Vol 21, pp. 120--127.
if (nargin == 0)  % default values
    nelx = 60;nely = 30; % The grid size for topology optimization
    desVolFrac = 0.5;  % The final volume fraction desired
    problem = 1; % 1 or 2 for cantilevered beam problems
    volDecrMax = 0.05; % step-size for pareto-tracing
    JIncMax = 5; % For steep change in pareto-curve, use additional constraint
    filterRadius = 0.6; % Use for smoothening the topological sensitivity  field
end
voidEps = 1e-6; % Relative Young's Modulus of void region 
filter = fspecial('gaussian', [3 3],filterRadius); % smoothen topological sensitivity  field
totalIter = 0;
elemsIn = ones(nely,nelx); % intialize the domain 
U = FE(nelx,nely,elemsIn,voidEps,problem); % Solve FEA problem
T = ComputeT(U,elemsIn,voidEps); % Compute topological sensitivity
T = filter2(filter,T); % smoothen the field
J(1) = computeCompliance(nelx,nely,elemsIn,voidEps,U); % compute & store compliance
volIndex = 1;volFractions(1) = 1; volfrac = 1; % initialization
volDecrement = volDecrMax; % current decrement of volume fraction
JOld = J(1);
while (volfrac > desVolFrac)
    volfrac = max(desVolFrac,volfrac-volDecrement); % move to the next volume fraction
    volIndex = volIndex+1;
    volFractions(volIndex) = volfrac; % store the volume fraction
    iter = 0;  
    while (iter < 10) % to avoid cycles; typically 20 iterations is sufficient  
        totalIter= totalIter+1; 
        [isValid,isParetoOptimal] = analyzeTopology(T,elemsIn);
        if ((iter > 5)&&(isValid)&&(isParetoOptimal)) % done with current vol 
            break
        end
        % Find the level-set value such that the contour has given vol fraction
        value = findContourValueWithVolumeFraction(T,volfrac);
        [index] = find(T < value); % eliminate all elements less than this value
        elemsIn = ones(nely,nelx); % start with the full domain
        elemsIn(ind2sub(size(T),index)) = 0; % remove elements
        U = FE(nelx,nely,elemsIn,voidEps,problem); % FEA
        T = ComputeT(U,elemsIn,voidEps); % Topological Sensitivity
        T = filter2(filter,T); % Smoothen the field
        JTemp =  computeCompliance(nelx,nely,elemsIn,voidEps,U);
        if (abs(JTemp-JOld)/JTemp < 0.001) break; end
        JOld = JTemp;
        iter= iter+1;
    end
    J(volIndex) = JTemp;
    value = findContourValueWithVolumeFraction(T,volfrac); % as above
    plotContour(T,value,figure(1));
    title(['v=' num2str(volfrac) '; J = ' num2str(J(volIndex)) '; #FEA = ' num2str(totalIter)]); 
    pause(0.01);
    dJ =  J(volIndex)- J(volIndex-1);
    volDecrement = max(volDecrMax/10,min(volDecrement,JIncMax*volDecrement/dJ));
end
figure(2); plot(volFractions,J,volFractions,J,'*');
xlabel('Volume'); ylabel('Compliance'); grid on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [U]=FE(nelx,nely,elemsIn,voidEps,problem)
if (problem == 1) % Cantilevered beam; 
    fixeddofs = 1:2*(nely+1); % left edge
    forcedDof = 2*(nelx+1)*(nely+1)-nely; % y force
elseif (problem == 2) % MBB beam
    fixeddofs = 1:2*(nely+1); % left edge
    forcedDof = 2*(nelx+1)*(nely+1); % y force
end
K = sparse(2*(nelx+1)*(nely+1), 2*(nelx+1)*(nely+1));
F = sparse(2*(nely+1)*(nelx+1),1); U = zeros(2*(nely+1)*(nelx+1),1);
[KE] = lk;
for elx = 1:nelx
  for ely = 1:nely
    n1 = (nely+1)*(elx-1)+ely; 
    n2 = (nely+1)* elx   +ely;
    edof = [2*n1-1 2*n1 2*n2-1 2*n2 2*n2+1 2*n2+2 2*n1+1 2*n1+2]';
    alpha = (1-elemsIn(ely,elx))*voidEps + elemsIn(ely,elx);
    K(edof,edof) = K(edof,edof) + alpha*KE; % not the most efficient method
  end
end
F(forcedDof,1) = -1;
alldofs     = 1:2*(nely+1)*(nelx+1);
freedofs    = setdiff(alldofs,fixeddofs);
U(freedofs,:) = K(freedofs,freedofs) \ F(freedofs,:);      
U(fixeddofs,:)= 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [KE]=lk % element stiffness
E = 1.; nu = 0.3;
k=[ 1/2-nu/6   1/8+nu/8 -1/4-nu/12 -1/8+3*nu/8 ... 
   -1/4+nu/12 -1/8-nu/8  nu/6       1/8-3*nu/8];
KE = E/(1-nu^2)*[ k(1) k(2) k(3) k(4) k(5) k(6) k(7) k(8)
                  k(2) k(1) k(8) k(7) k(6) k(5) k(4) k(3)
                  k(3) k(8) k(1) k(6) k(7) k(4) k(5) k(2)
                  k(4) k(7) k(6) k(1) k(8) k(3) k(2) k(5)
                  k(5) k(6) k(7) k(8) k(1) k(2) k(3) k(4)
                  k(6) k(5) k(4) k(3) k(2) k(1) k(8) k(7)
                  k(7) k(4) k(5) k(2) k(3) k(8) k(1) k(6)
                  k(8) k(3) k(2) k(5) k(4) k(7) k(6) k(1)];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
function [T] = ComputeT(U,elemsIn,voidEps)
% Compute the topological sensitivity at the center of each element
[nely,nelx] = size(elemsIn);
gradN =0.5*[-1 1 1 -1;-1 -1 1 1]; % at center
E0 = 1;nu = 0.3;
D0 = 1/(1-nu^2)*[1 nu 0; nu 1 0;0 0 (1-nu)/2]; % plane stress
T(1:nely,1:nelx) = 0; % initialize to 0
for elx = 1:nelx
  for ely = 1:nely
    n1 = (nely+1)*(elx-1)+ely; 
    n2 = (nely+1)* elx   +ely;
    edof = [2*n1-1 2*n1 2*n2-1 2*n2 2*n2+1 2*n2+2 2*n1+1 2*n1+2]';
    uGrad = gradN*U(edof(1:2:end));
    vGrad = gradN*U(edof(2:2:end));
    strains = [uGrad(1); vGrad(2); (uGrad(2)+vGrad(1)) ];
    alpha = (1-elemsIn(ely,elx))*voidEps + elemsIn(ely,elx);
    E = E0*alpha;
    stresses = D0*E*strains;
    stressTensor = [stresses(1) stresses(3); stresses(3) stresses(2)];
    strainTensor = [strains(1) strains(3)/2; strains(3)/2 strains(2)]; 
    if (elemsIn(ely,elx))
        T(ely,elx) = 4/(1+nu)*sum(sum(stressTensor.*strainTensor))- ...
         (1-3*nu)/(1-nu^2)*trace(stressTensor)*trace(strainTensor);
    else 
        T(ely,elx) = -4/(3-nu)*sum(sum(stressTensor.*strainTensor))-...
          (1-3*nu)/((1+nu)*(3-nu))*trace(stressTensor)*trace(strainTensor);
    end
  end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [J]=computeCompliance(nelx,nely,elemsIn,voidEps,U)
% Compute the compliance of the entire mesh
[KE] = lk;J = 0;
for elx = 1:nelx
  for ely = 1:nely
    n1 = (nely+1)*(elx-1)+ely; 
    n2 = (nely+1)* elx   +ely;
    edof = [2*n1-1 2*n1 2*n2-1 2*n2 2*n2+1 2*n2+2 2*n1+1 2*n1+2]';
    alpha = (1-elemsIn(ely,elx))*voidEps + elemsIn(ely,elx);
    Ue = U(edof);
    J = J + alpha*Ue'*KE*Ue; 
  end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function value = findContourValueWithVolumeFraction(field,volfrac)
 % Find the level-set value such that the contour has given vol fraction
 % The code computes the level-set value with desired external volume
[nely,nelx] = size(field);
externalVolumeDesired = nelx*nely*(1-volfrac);
field = -field; % reverse the sign to compute external volume
valMax = 0; valMin = min(field(:));
bufferedField = valMin*ones(nely+2,nelx+2);% Add buffer to get closed contours
bufferedField(2:end-1,2:end-1) = field;
iterMax = 50;iter = 1;
while (1) % A binary search is used to find the optimal level-set value
    valMid = (valMax+valMin)/2;
    extVol = computeAreaInContour(bufferedField,valMid);
    err = abs(extVol-externalVolumeDesired)/(extVol);
    if (err < 0.001) || (iter > iterMax)
        value = -valMid; % change the sign before return
        return;
    end
    if (extVol > externalVolumeDesired)
        valMin = valMid;
    else
        valMax = valMid;
    end
    iter = iter+1;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function area = computeAreaInContour(bufferedField,value)
% For a given level-set value, compute the area enclosed
% It is assumed that the field has been buffered; see code above
[cntr,h] = contours(bufferedField,[value value]);
indices = find(cntr(1,:) == value);area = 0;
for i = 1:numel(indices)
    startCol = indices(i)+1;
    endCol = startCol+ cntr(2,indices(i))-1;
    xPoly = cntr(1,startCol:endCol);
    yPoly = cntr(2,startCol:endCol);
    area = area + polyarea(xPoly,yPoly);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [isValid,isParetoOptimal] = analyzeTopology(T,elemsIn)
% Check if the Topological field is valid and/or pareto-optimal
T_SMin = min(T(elemsIn==1)); % Min of topological field inside the domain
T_AMax = max(T(elemsIn==0)); % Max of topological field outside the domain
T_AMin = min(T(elemsIn==0)); % Min of topological field outside the domain
isValid = 0; isParetoOptimal = 0;
if (T_SMin > 0.8*T_AMax), isValid = 1; end
if (T_AMin+T_SMin >= 0), isParetoOptimal = 1; end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function plotContour(T,value,fig)
%Use Matlab's built-in contour command to draw the optimal topology.
[nely,nelx] = size(T);
figure(fig);clf;fill([1 nelx nelx 1],[1 1 nely nely],'b'); hold on;
[cntr,h] =contourf(-T(end:-1:1,:),[-value -value]); % the second argument is essential
axis('equal'); axis tight;axis off;

猜你喜欢

转载自blog.csdn.net/qq_34763204/article/details/113805124
今日推荐