Skip to content
Snippets Groups Projects
concurrent3d.jl 18.56 KiB
# Amira Abdel-Rahman
# (c) Massachusetts Institute of Technology 2020

function ConTop3D(Macro_struct, Micro_struct, penal, rmin)
    # USER-DEFINED LOOP PARAMETERS
    maxloop = 200; displayflag = 1; E0 = 1; Emin = 1e-9; nu = 0.3;
    Macro_length = Macro_struct[1]; Macro_width = Macro_struct[2]; Macro_Height = Macro_struct[3];
    Micro_length = Micro_struct[1]; Micro_width = Micro_struct[2]; Micro_Height = Micro_struct[3];
    Macro_nelx   = Macro_struct[4]; Macro_nely  = Macro_struct[5]; Macro_nelz   = Macro_struct[6];
    Micro_nelx   = Micro_struct[4]; Micro_nely  = Micro_struct[5]; Micro_nelz   = Micro_struct[6];
    Macro_Vol = Macro_struct[7]; Micro_Vol = Micro_struct[7];
    Macro_Elex   = Macro_length/Macro_nelx; Macro_Eley = Macro_width/Macro_nely; Macro_Elez = Macro_Height/Macro_nelz;
    Macro_nele = Macro_nelx*Macro_nely*Macro_nelz; Micro_nele = Micro_nelx*Micro_nely*Micro_nelz;
    Macro_ndof = 3*(Macro_nelx+1)*(Macro_nely+1)*(Macro_nelz+1);
    # PREPARE FINITE ELEMENT ANALYSIS
    [load_x,load_y,load_z] = meshgrid(Macro_nelx/2, Macro_nely, Macro_nelz/2);
    loadnid = load_z*(Macro_nelx+1)*(Macro_nely+1)+load_x*(Macro_nely+1)+(Macro_nely+1-load_y);
    F = sparse(3*loadnid[:] - 1,1,-1,Macro_ndof,1);
    U = zeros(Macro_ndof,1);
    [fixed_x,fixed_y,fixed_z] = meshgrid( [0 Macro_nelx],0,[0 Macro_nelz] );
    fixednid = fixed_z*(Macro_nelx+1)*(Macro_nely+1)+fixed_x*(Macro_nely+1)+(Macro_nely+1-fixed_y);
    fixeddofs = [3*fixednid[:]; 3*fixednid[:]-1; 3*fixednid[:]-2];
    freedofs = setdiff(1:Macro_ndof,fixeddofs);
    nodegrd = reshape(1:(Macro_nely+1)*(Macro_nelx+1),Macro_nely+1,Macro_nelx+1);
    nodeids = reshape(nodegrd[1:end-1,1:end-1],Macro_nely*Macro_nelx,1);
    nodeidz = 0:(Macro_nely+1)*(Macro_nelx+1):(Macro_nelz-1)*(Macro_nely+1)*(Macro_nelx+1);
    nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids));
    edofMat = repmat(3*nodeids[:]+1,1,24)+ repmat( [0 1 2 3*Macro_nely + [3 4 5 0 1 2] -3 -2 -1  
        3*(Macro_nely+1)*(Macro_nelx+1)+[0 1 2 3*Macro_nely + [3 4 5 0 1 2] -3 -2 -1]],Macro_nele,1);
    iK = reshape(kron(edofMat,ones(24,1))',24*24*Macro_nele,1);
    jK = reshape(kron(edofMat,ones(1,24))',24*24*Macro_nele,1);
    # PREPARE FILTER
    Macro_H,Macro_Hs = filtering3d(Macro_nelx, Macro_nely, Macro_nelz, Macro_nele, rmin);
    Micro_H,Micro_Hs = filtering3d(Micro_nelx, Micro_nely, Micro_nelz, Micro_nele, rmin);
    # INITIALIZE ITERATION
    Macro_x = repmat(Macro_Vol,[Macro_nely,Macro_nelx,Macro_nelz] );
    Micro_x = ones(Micro_nely,Micro_nelx,Micro_nelz);
    Micro_x[Micro_nely/2:Micro_nely/2+1,Micro_nelx/2:Micro_nelx/2+1,Micro_nelz/2:Micro_nelz/2+1] = 0;
    beta = 1;
    Macro_xTilde = Macro_x; Micro_xTilde = Micro_x;
    Macro_xPhys = 1-exp(-beta*Macro_xTilde)+Macro_xTilde*exp(-beta);
    Micro_xPhys = 1-exp(-beta*Micro_xTilde)+Micro_xTilde*exp(-beta);
    loopbeta = 0; loop = 0; Macro_change = 1; Micro_change = 1;
    while loop < maxloop || Macro_change > 0.01 || Micro_change > 0.01
        loop = loop+1; loopbeta = loopbeta+1;
        # FE-ANALYSIS AT TWO SCALES
        DH, dDH = EBHM3D(Micro_xPhys, Micro_length, Micro_width, Micro_Height, E0, Emin, nu, penal);
        Ke = elementMatVec3D(Macro_Elex/2, Macro_Eley/2, Macro_Elez/2, DH);
        sK = reshape(Ke[:]*(Emin+Macro_xPhys[:]'.^penal*(1-Emin)),24*24*Macro_nele,1);
        K = sparse(iK,jK,sK); K = (K+K')/2;
        U[freedofs,:] = K[freedofs,freedofs]\F[freedofs,:];
        # OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS
        ce = reshape(sum((U[edofMat]*Ke).*U[edofMat],2),[Macro_nely,Macro_nelx,Macro_nelz] );
        c = sum(sum(sum((Emin+Macro_xPhys.^penal*(1-Emin)).*ce)));
        Macro_dc = -penal*(1-Emin)*Macro_xPhys.^(penal-1).*ce;
        Macro_dv = ones(Macro_nely, Macro_nelx, Macro_nelz);
        Micro_dc = zeros(Micro_nely, Micro_nelx, Micro_nelz);
        for i = 1:Micro_nele
            dDHe = [dDH[1,1][i] dDH[1,2][i] dDH[1,3][i] dDH[1,4][i] dDH[1,5][i] dDH[1,6][i];
                    dDH[2,1][i] dDH[2,2][i] dDH[2,3][i] dDH[2,4][i] dDH[2,5][i] dDH[2,6][i];
                    dDH[3,1][i] dDH[3,2][i] dDH[3,3][i] dDH[3,4][i] dDH[3,5][i] dDH[3,6][i];
                    dDH[4,1][i] dDH[4,2][i] dDH[4,3][i] dDH[4,4][i] dDH[4,5][i] dDH[4,6][i];
                    dDH[5,1][i] dDH[5,2][i] dDH[5,3][i] dDH[5,4][i] dDH[5,5][i] dDH[5,6][i];
                    dDH[6,1][i] dDH[6,2][i] dDH[6,3][i] dDH[6,4][i] dDH[6,5][i] dDH[6,6][i]];
            dKE = elementMatVec3D(Macro_Elex, Macro_Eley, Macro_Elez, dDHe);
            dce = reshape(sum((U[edofMat]*dKE).*U[edofMat],2),[Macro_nely,Macro_nelx,Macro_nelz] );
            Micro_dc[i] = -sum(sum(sum((Emin+Macro_xPhys.^penal*(1-Emin)).*dce)));
        end
        Micro_dv = ones(Micro_nely, Micro_nelx, Micro_nelz);
        # FILTERING AND MODIFICATION OF SENSITIVITIES
        Macro_dx = beta*exp(-beta*Macro_xTilde)+exp(-beta); Micro_dx = beta*exp(-beta*Micro_xTilde)+exp(-beta);
        Macro_dc[:] = Macro_H*(Macro_dc[:].*Macro_dx[:]./Macro_Hs); Macro_dv[:] = Macro_H*(Macro_dv[:].*Macro_dx[:]./Macro_Hs);
        Micro_dc[:] = Micro_H*(Micro_dc[:].*Micro_dx[:]./Micro_Hs); Micro_dv[:] = Micro_H*(Micro_dv[:].*Micro_dx[:]./Micro_Hs);
        # OPTIMALITY CRITERIA UPDATE MACRO AND MICRO ELELMENT DENSITIES
        Macro_x, Macro_xPhys, Macro_change = OC(Macro_x, Macro_dc, Macro_dv, Macro_H, Macro_Hs, Macro_Vol, Macro_nele, 0.02, beta);
        Micro_x, Micro_xPhys, Micro_change = OC(Micro_x, Micro_dc, Micro_dv, Micro_H, Micro_Hs, Micro_Vol, Micro_nele, 0.02, beta);
        Macro_xPhys = reshape(Macro_xPhys, Macro_nely, Macro_nelx, Macro_nelz);
        Micro_xPhys = reshape(Micro_xPhys, Micro_nely, Micro_nelx, Micro_nelz);
        # PRINT RESULTS
        # display(' It.:#5i Obj.:#11.4f Macro_Vol.:#7.3f Micro_Vol.:#7.3f Macro_ch.:#7.3f Micro_ch.:#7.3f\n', loop,c,mean(Macro_xPhys[:] ),mean(Micro_xPhys[:] ), Macro_change, Micro_change);
        # if displayflag, clf; display_3D(Macro_xPhys); end
        # if displayflag, clf; display_3D(Micro_xPhys); end
        # UPDATE HEAVISIDE REGULARIZATION PARAMETER
        if beta < 512 && (loopbeta >= 50 || Macro_change <= 0.01 || Micro_change <= 0.01 )
            beta = 2*beta; loopbeta = 0; Macro_change = 1; Micro_change = 1;
            display("Parameter beta increased to $beta.");
        end
    end
end

## SUB FUNCTION:filtering3D
function filtering3d(nelx, nely, nelz, nele, rmin)
    iH = ones(nele*(2*(ceil(rmin)-1)+1)^2,1);
    jH = ones(size(iH));
    sH = zeros(size(iH));
    k = 0;
    for k1 = 1:nelz
        for i1 = 1:nelx
            for j1 = 1:nely
                e1 = (k1-1)*nelx*nely + (i1-1)*nely+j1;
                for k2 = max(k1-(ceil(rmin)-1),1):min(k1+(ceil(rmin)-1),nelz)
                    for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx)
                        for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely)
                            e2 = (k2-1)*nelx*nely + (i2-1)*nely+j2;
                            k = k+1;
                            iH[k] = e1;
                            jH[k] = e2;
                            sH[k] = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2));
                        end
                    end
                end
            end
        end
    end
    H = sparse(iH,jH,sH); Hs = sum(H,2);
    return H,Hs
end


## SUB FUNCTION: EBHM3D
function EBHM3D(den, lx, ly, lz, E0, Emin, nu, penal)
    # the initial definitions of the PUC
    D0 = E0/(1+nu)/(1-2*nu)*
        [ 1-nu   nu   nu     0          0          0     ;
            nu 1-nu   nu     0          0          0     ;
            nu   nu 1-nu     0          0          0     ;
             0    0    0 (1-2*nu)/2     0          0     ;
             0    0    0     0      (1-2*nu)/2     0     ;
             0    0    0     0          0      (1-2*nu)/2];
    nely, nelx, nelz = size(den); nele = nelx*nely*nelz;
    dx = lx/nelx; dy = ly/nely; dz = lz/nelz;
    Ke = elementMatVec3D(dx/2, dy/2, dz/2, D0);
    Num_node = (1+nely)*(1+nelx)*(1+nelz);
    nodenrs = reshape(1:Num_node,1+nely,1+nelx,1+nelz);
    edofVec = reshape(3*nodenrs[1:end-1,1:end-1,1:end-1]+1,nelx*nely*nelz,1);
    edofMat = repmat(edofVec,1,24)+repmat( [0 1 2 3*nely+[3 4 5 0 1 2] -3 -2 -1 
        3*(nelx+1)*(nely+1)+[0 1 2 3*nely+[3 4 5 0 1 2] -3 -2 -1]], nele, 1);
    # 3D periodic boundary formulation
    # the nodes classification
    n1 = [nodenrs[end, [1 end], 1] nodenrs[1, [end 1], 1] nodenrs[end, [1 end], end] nodenrs[1, [end 1], end]];
    d1 = reshape( [3*n1-2; 3*n1-1; 3*n1],3*numel(n1),1);
    
    n3 = [reshape(squeeze(nodenrs[end,1,2:end-1] ),1,numel(squeeze(nodenrs[end,1,2:end-1] )))               # AE
          reshape(squeeze(nodenrs[1, 1, 2:end-1] ),1,numel(squeeze(nodenrs[1, 1, 2:end-1] )))               # DH
          reshape(squeeze(nodenrs[end,2:end-1,1] ),1,numel(squeeze(nodenrs[end,2:end-1,1] )))               # AB
          reshape(squeeze(nodenrs[1, 2:end-1, 1] ),1,numel(squeeze(nodenrs[1, 2:end-1, 1] )))               # DC
          reshape(squeeze(nodenrs[2:end-1, 1, 1] ),1,numel(squeeze(nodenrs[2:end-1, 1, 1] )))               # AD
          reshape(squeeze(nodenrs[2:end-1,1,end] ),1,numel(squeeze(nodenrs[2:end-1,1,end] )))               # EH
          reshape(squeeze(nodenrs[2:end-1, 2:end-1, 1] ),1,numel(squeeze(nodenrs[2:end-1, 2:end-1, 1] )))   # ABCD
          reshape(squeeze(nodenrs[2:end-1, 1, 2:end-1] ),1,numel(squeeze(nodenrs[2:end-1, 1, 2:end-1] )))   # ADHE
          reshape(squeeze(nodenrs[end,2:end-1,2:end-1] ),1,numel(squeeze(nodenrs[end,2:end-1,2:end-1] )))];   # ABFE                   
    d3 = reshape( [3*n3-2; 3*n3-1; 3*n3],3*numel(n3),1);
    n4 = [reshape(squeeze(nodenrs[1, end, 2:end-1] ),1,numel(squeeze(nodenrs[1, end, 2:end-1] )))           # CG
          reshape(squeeze(nodenrs[end,end,2:end-1] ),1,numel(squeeze(nodenrs[end,end,2:end-1] )))           # BF
          reshape(squeeze(nodenrs[1, 2:end-1, end] ),1,numel(squeeze(nodenrs[1, 2:end-1, end] )))           # HG
          reshape(squeeze(nodenrs[end,2:end-1,end] ),1,numel(squeeze(nodenrs[end,2:end-1,end] )))           # EF
          reshape(squeeze(nodenrs[2:end-1,end,end] ),1,numel(squeeze(nodenrs[2:end-1,end,end] )))           # FG
          reshape(squeeze(nodenrs[2:end-1, end, 1] ),1,numel(squeeze(nodenrs[2:end-1, end, 1] )))           # BC
          reshape(squeeze(nodenrs[2:end-1,2:end-1,end] ),1,numel(squeeze(nodenrs[2:end-1,2:end-1,end] )))   # EFGH
          reshape(squeeze(nodenrs[2:end-1,end,2:end-1] ),1,numel(squeeze(nodenrs[2:end-1,end,2:end-1] )))   # BCGF
          reshape(squeeze(nodenrs[1, 2:end-1, 2:end-1] ),1,numel(squeeze(nodenrs[1, 2:end-1, 2:end-1] )))];   # DCGH
    d4 = reshape( [3*n4-2; 3*n4-1; 3*n4],3*numel(n4),1);
    n2 = setdiff(nodenrs[:],[n1[:];n3[:];n4[:]] ); d2 = reshape( [3*n2-2; 3*n2-1; 3*n2],3*numel(n2),1);
    # the imposing of six linearly independent unit test strains
    e = Matrix(1.0I, 6, 6); 
    ufixed = zeros(24,6);
    vert_cor = [0  lx lx  0  0 lx lx  0;
                0   0 ly ly  0  0 ly ly;
                0   0  0  0 lz lz lz lz];
    for i = 1:6
        epsilon = [  e[i,1] e[i,4]/2 e[i,6]/2;
                   e[i,4]/2   e[i,2] e[i,5]/2;
                   e[i,6]/2 e[i,5]/2   e[i,3]];
        ufixed[:,i] = reshape(epsilon*vert_cor,24,1);
    end
    # 3D boundary constraint equations
    wfixed = [repmat(ufixed[  7:9,:],numel(squeeze(nodenrs[end,1,2:end-1] )),1);                    # C
              repmat(ufixed[  4:6,:]-ufixed[10:12,:],numel(squeeze(nodenrs[1, 1, 2:end-1] )),1);    # B-D
              repmat(ufixed[22:24,:],numel(squeeze(nodenrs[end,2:end-1,1] )),1);                    # H
              repmat(ufixed[13:15,:]-ufixed(10:12,:),numel(squeeze(nodenrs[1, 2:end-1, 1] )),1);    # E-D
              repmat(ufixed[16:18,:],numel(squeeze(nodenrs[2:end-1, 1, 1] )),1);                    # F
              repmat(ufixed[  4:6,:]-ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1,1,end] )),1);    # B-E
              repmat(ufixed[13:15,:],numel(squeeze(nodenrs[2:end-1, 2:end-1, 1] )),1);              # E
              repmat(ufixed[  4:6,:],numel(squeeze(nodenrs[2:end-1, 1, 2:end-1] )),1);              # B
              repmat(ufixed[10:12,:],numel(squeeze(nodenrs[end,2:end-1,2:end-1] )),1)];             # D
    # the reduced elastic equilibrium equation to compute the induced displacement field
    iK = reshape(kron(edofMat,ones(24,1))',24*24*nele,1);
    jK = reshape(kron(edofMat,ones(1,24))',24*24*nele,1);

    sK = reshape(Ke[:]*(Emin+den[:]'.^penal*(1-Emin)),24*24*nele,1);
    K = sparse(iK[:], jK[:], sK[:] ); K = (K+K')/2;
    Kr = [K[d2,d2], K[d2,d3]+K[d2,d4]; K[d3,d2]+K[d4,d2],K[d3,d3]+K[d4,d3]+K[d3,d4]+K[d4,d4]];
    U[d1,:]= ufixed;
    U[ [d2;d3],:] = Kr\(-[K[d2,d1];K[d3,d1]+K[d4,d1]]*ufixed-[K[d2,d4];K[d3,d4]+K[d4,d4]]*wfixed);
    U[d4,:] = U[d3,:] + wfixed;

    # homogenization to evaluate macroscopic effective properties
    qe = Array{Any,2}(undef, 6, 6);
    DH = zeros(6,6); 
    dDH = Array{Any,2}(undef, 6, 6);
    cellVolume = lx*ly*lz;
    for i = 1:6
        for j = 1:6
            U1 = U[:,i]; U2 = U[:,j];
            qe[i,j] = reshape(sum((U1[edofMat]*Ke).*U2[edofMat],dims=2),nely,nelx,nelz);
            DH[i,j] = 1/cellVolume*sum(sum(sum((Emin+den.^penal*(1-Emin)).*qe{i,j})));
            dDH[i,j] = 1/cellVolume*(penal*(1-Emin)*den.^(penal-1).*qe{i,j});
        end
    end
    # disp('--- Homogenized elasticity tensor ---'); disp(DH)
    return DH, dDH
end


## SUB FUNCTION: elementMatVec3D
function elementMatVec3D(a, b, c, DH)
    GN_x=[-1/sqrt(3),1/sqrt(3)]; GN_y=GN_x; GN_z=GN_x; GaussWeigh=[1,1];
    Ke = zeros(24,24); L = zeros(6,9);
    L[1,1] = 1; L[2,5] = 1; L[3,9] = 1;
    L[4,2] = 1; L[4,4] = 1; L[5,6] = 1;
    L[5,8] = 1; L[6,3] = 1; L[6,7] = 1;
    for ii=1:length(GN_x)
        for jj=1:length(GN_y)
            for kk=1:length(GN_z)
                x = GN_x[ii];y = GN_y[jj];z = GN_z[kk];
                dNx = 1/8*[-(1-y)*(1-z)  (1-y)*(1-z)  (1+y)*(1-z) -(1+y)*(1-z) -(1-y)*(1+z)  (1-y)*(1+z)  (1+y)*(1+z) -(1+y)*(1+z)];
                dNy = 1/8*[-(1-x)*(1-z) -(1+x)*(1-z)  (1+x)*(1-z)  (1-x)*(1-z) -(1-x)*(1+z) -(1+x)*(1+z)  (1+x)*(1+z)  (1-x)*(1+z)];
                dNz = 1/8*[-(1-x)*(1-y) -(1+x)*(1-y) -(1+x)*(1+y) -(1-x)*(1+y)  (1-x)*(1-y)  (1+x)*(1-y)  (1+x)*(1+y)  (1-x)*(1+y)];
                J = [dNx;dNy;dNz]*[ -a  a  a  -a  -a  a  a  -a ;  -b  -b  b  b  -b  -b  b  b; -c -c -c -c  c  c  c  c]';
                G = [inv(J) zeros(3) zeros(3);zeros(3) inv(J) zeros(3);zeros(3) zeros(3) inv(J)];
                dN=zeros(9,24)
                dN[1,1:3:24] = dNx; dN[2,1:3:24] = dNy; dN[3,1:3:24] = dNz;
                dN[4,2:3:24] = dNx; dN[5,2:3:24] = dNy; dN[6,2:3:24] = dNz;
                dN[7,3:3:24] = dNx; dN[8,3:3:24] = dNy; dN[9,3:3:24] = dNz;
                Be = L*G*dN;
                Ke = Ke + GaussWeigh[ii]*GaussWeigh[jj]*GaussWeigh[kk]*det(J)*(Be'*DH*Be);
            end
        end
    end
    return Ke
end


## SUB FUNCTION: OC
function OC(x, dc, dv, H, Hs, volfrac, nele, move, beta)
    l1 = 0; l2 = 1e9;
    while (l2-l1)/(l1+l2) > 1e-3
        lmid = 0.5*(l2+l1);
        xnew = max(0,max(x-move,min(1,min(x+move,x.*sqrt(-dc./dv/lmid)))));
        xTilde[:] = (H*xnew[:] )./Hs; xPhys = 1-exp(-beta*xTilde)+xTilde*exp(-beta);
        if sum(xPhys[:] ) > volfrac*nele
            l1 = lmid; 
        else
            l2 = lmid; 
        end
    end
    change = max(abs(xnew[:]-x[:] )); x = xnew;
    return x, xPhys, change
end


## SUB FUNCTION: display_3D
function display_3D(rho)
    [nely,nelx,nelz] = size(rho);
    hx = 1; hy = 1; hz = 1;
    face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8];
    # set(gcf,'Name','ISO display','NumberTitle','off');
    for k = 1:nelz
        z = (k-1)*hz;
        for i = 1:nelx
            x = (i-1)*hx;
            for j = 1:nely
                y = nely*hy - (j-1)*hy;
                if (rho[j,i,k] > 0)
                    vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx];
                    vert[:,[2 3]] = vert[:,[3 2]]; vert[:,2,:] = -vert[:,2,:];
                    # patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))] );
                    # hold on;
                end
            end
        end
    end
    # axis equal; axis tight; axis off; box on; view( [30,30] ); pause(1e-6);
end
#======================================================================================================================#
# Function ConTop3D:                                                                                                   #
# A compact and efficient MATLAB code for Concurrent topology optimization of multiscale composite structures          #
# in Matlab.                                                                                                           #
#                                                                                                                      #
# Developed by: Jie Gao, Zhen Luo, Liang Xia and Liang Gao*                                                            #
# Email: gaoliang@mail.hust.edu.cn (GabrielJie_Tian@163.com)                                                           #
#                                                                                                                      #
# Main references:                                                                                                     #
#                                                                                                                      #
# (1) Jie Gao, Zhen Luo, Liang Xia, Liang Gao. Concurrent topology optimization of multiscale composite structures     #
# in Matlab. Accepted in Structural and multidisciplinary optimization.                                                #
#                                                                                                                      #
# (2) Xia L, Breitkopf P. Design of materials using topology optimization and energy-based homogenization approach in  #
# Matlab. # Structural and multidisciplinary optimization, 2015, 52(6): 1229-1241.                                     #
#                                                                                                                      #
# *********************************************   Disclaimer   ******************************************************* #
# The authors reserve all rights for the programs. The programs may be distributed and used for academic and           #
# educational purposes. The authors do not guarantee that the code is free from errors,and they shall not be liable    #
# in any event caused by the use of the program.                                                                       #
#======================================================================================================================#