using LinearAlgebra
using Plots
import JSON
using SparseArrays
using Images
using StaticArrays, BenchmarkTools
nelx=25;
nely=50;
X=ones(nelx,nely)*0.85;
fxF= zeros(Int,2,3);
fxF[1,1]=2 .*((nely)/2*(nelx+1));
fxF[1,2]=-100;
fxF[2,1]=2 .*((nely)/2*(nelx+1)+1);
fxF[2,2]=-100;
fxF[:,3].=1;
fxU=zeros(Int,3,3);
fxU[1,1]=2 .*(nelx+1);
fxU[2,1]=2 .*(nelx+1)+1;
fxU[3,1]=2 .*(nelx+1)*(nely+1);
fxU[:,3].=1;
Ymod=20 ;
nu=0.3;
p=3;
#equilibrium value
tgS=ones(nelx,nely)*5.0;
rho=2e-3;
w=0.25;
U=2261;
M=nelx*nely*2.0*1e-3;
tgS=ones(nelx,nely).*((1-w)/w*U/M*rho/p);
tgS=ones(nelx,nely).*1.8084;
#tgS=ones(nelx,nely)*(w*rho/p);
s=0.02;
scond=2;
# 3 #strict surface condition
# 2 #soft surface condition
# proportional gain cp cy
ct=0.2;
cp=0.2/tgS[1];
cp=0.4;
cI=0.4/tgS[1];
cD=0.2/tgS[1];
cII=0.4;
k=[ct,cp,cI,cD,cII];#0.2/1.8084
#Extended Moore (N=24), MvonN (N=12), Moore (N=8) ,von Newmann (N=4), > 24 # Global (nelx*ney-1)
neighbors=8;
# bcond==2 %periodic bcond bcond==1 %fixed bcond
bcond=1;
itmax=120;
vtol=2.5e-3;
ctype= "e";# f' 'p' 'i' 'd' 'e' 'n' 'pi' 'pd' 'id' 'pid'
ttype= 2; #or 2??
T=10;#????
movflg= 0;
matflg=0;
filestr="";
xfilter=true; #effective relative mass
sfilter=true; #EFFECTIVE STIMULUS
function hcastruc1(X, fxF, fxU, Ymod, nu, p, tgS, s, scond, k, neighbors, bcond, itmax, vtol, ctype, ttype, T, xfilter, sfilter)
states=[]
anim=Animation()
# INPUT PARAMETERS
nely, nelx = size(X);
# CORRECT DENSITY
X[X .< 0.001] .= 0.001;
X[X .> 1.000] .= 1.000;
# START HCA ALGORITHM
println("running hca...")
# FE-ANALYSIS
SED = fea(copy(X), fxF, fxU, Ymod, nu, p);
# MECHANICAL STIMULUS
S=zeros(size(X))
if ttype==1
S = SED;
else
S = SED./X;
end
# PLOT
it = 0;
SE = sum(sum(SED,dims=1));
M = sum(sum(X,dims=1));
println("t: $it, SE: $SE, M: $M")
# hfig = imagesc(-X,[-1 0]); axis equal; axis tight; axis off;
# str = [ " t: " sprintf("#4i",it) ...
# " SE: " sprintf("#10.4f",SE) ...
# " M: " sprintf("#6.3f",M)];
# title(str); pause(1e-6); disp(str);
efX=zeros(size(X))
efS=zeros(size(X))
# EFFECTIVE RELATIVE MASS
if xfilter
if bcond==1 #fixed bcond
efX = doavgf(X,neighbors,0);
elseif bcond==2 #periodic bcond bcond==1 #fixed bcond
efX = doavgp(X,neighbors);
end
else
efX .= X;
end
# EFFECTIVE STIMULUS
if sfilter
if bcond==1 #fixed bcond
efS = doavgf(S,neighbors,0);
elseif bcond==2 #periodic bcond
efS = doavgp(S,neighbors);
end
else
efS = copy(S);
end
# EFFECTIVE ERROR SIGNAL
efE = zeros(size(efS));
efE[efS .> tgS] .= efS[efS .> tgS] .- (1+s)*tgS[efS .> tgS];
efE[efS .< tgS] .= efS[efS .< tgS] .- (1-s)*tgS[efS .< tgS];
# FOR INTEGRAL CONTROL: CREATE HISTORY OF STATES FOR INTEGRAL CONTROL
efEhis = zeros(size(efE,1),size(efE,2),T+2);
efEsum = zeros(size(efE,1),size(efE,2));
# FOR CONVERGENCE
Mtol = Inf;
# FOR CONVERGENCE PLOT
ITplt = 0; SEplt = SE; Mplt = M;
# FOR DERIVATIVE CONTROL
efEold = efE; #default
#efEold = zeros(size(efE)); #modified
# LOOP
Xnew = copy(X);
Mold = 0;
while (it<itmax && Mtol>vtol)
it = it + 1;
# SURFACE CONDITION
xid = efE .!=0;
sneighbors = 4;
if scond==2 #soft surface condition
if bcond==1 #fixed bcond
sfX = doavgf(X,sneighbors,0); #average in N+1 neighbors
elseif bcond==2 #periodic bcond
sfX = doavgf(X,sneighbors,0); #average in N+1 neighbors
end
xid=(sfX.<1.000) .& (sfX.>0.001)
# x=[1 2 3;5 3 1]
# m=(x.<3) .& (x.>1)
# yyy=zeros(Int,size(sfX));zzz=zeros(Int,size(sfX))
# yyy[sfX.<1.000 ].=1;zzz[sfX.>0.001].=1
# xid = yyy .& zzz
#xid .= (sfX.<1.000 .& sfX.>0.001);
elseif scond==3 #strict surface condition
if bcond==1 #fixed bcond
sfX = doavgf(X,sneighbors,0); #avg in N+1 neighbors
lzX = lookznf(X,sneighbors,0); #look for zeros around
loX = lookonf(X,sneighbors,0); #look for ones around
elseif bcond==2 #periodic bcond
sfX = doavgp(X,sneighbors); #average in N+1 neighbors
lzX = lookznp(X,sneighbors); #look for zeros around
loX = lookonp(X,sneighbors); #look for ones around
end
xid=(sfX.<0.999) .& (sfX.>0.001)
#xid .= (sfX.<0.999 .& sfX.>0.001);# | (X<0.999 & X>0.001);
xid[X.<=0.001] .= loX[X.<=0.001];
xid[X.>=1.000] .= lzX[X.>=1.000];
end
# UPDATE RULE
if ctype== "f"
Xnew[xid] .= efX[xid] + k[1]*sign.(efE[xid]);
elseif ctype== "p"
Xnew[xid] .= efX[xid] + k[2]*efE[xid]./tgS[xid];
elseif ctype== "i"
Xnew[xid] .= efX[xid] + k[3]*efEsum[xid]./tgS[xid];
elseif ctype== "d"
Xnew[xid] .= efX[xid] + k[4]*(efE[xid] - efEold[xid])./tgS[xid];
elseif ctype=="e" #ratio approach
if ttype==1
Xnew[xid] = k[5]*efX[xid].*(efS[xid]./tgS[xid]).^(1.0/p);
elseif ttype==2
Xnew[xid] = k[5]*efX[xid].*(tgS[xid]./efS[xid]).^(1.0/p-1.0);
end
elseif ctype== "n" #ratio approach variable set point
if ttype==1
Xnew[xid] .= k[5].*efX[xid].*(S[xid]./efS[xid]).^(1/p);
elseif ttype==2
Xnew[xid] .= k[5].*efX[xid].*(efS[xid]./S[xid]).^(1.0/p-1.0);
end
elseif ctype== "pi"
Xnew[xid] = efX[xid] + k[2]*efE[xid]./tgS[xid];
Xnew[xid] = Xnew[xid] + k[3]*efEsum[xid]./tgS[xid];
elseif ctype== "pd"
Xnew[xid] = efX[xid] + k[2]*efE[xid]./tgS[xid];
Xnew[xid] = Xnew[xid] + k[4]*(efE[xid] - efEold[xid])./tgS[xid];
elseif ctype== "id"
Xnew[xid] = efX[xid] + k[3]*efEsum[xid]./tgS[xid];
Xnew[xid] = Xnew[xid] + k[4]*(efE[xid] - efEold[xid])./tgS[xid];
elseif ctype== "pid"
Xnew[xid] = efX[xid] + k[2]*efE[xid]./tgS[xid];
Xnew[xid] = Xnew[xid] + k[3]*efEsum[xid]./tgS[xid];
Xnew[xid] = Xnew[xid] + k[4]*(efE[xid] - efEold[xid])./tgS[xid];
end
# FE-ANALYSIS
SEDnew = fea(copy(Xnew), fxF, fxU, Ymod, nu, p);
# MECHANICAL STIMULUS
if ttype==1
Snew = SEDnew;
else
Snew = SEDnew./Xnew;
end
# CONVERGENCE
Mnew = sum(sum(Xnew,dims=1));
Mtol = (abs(Mnew - M) .+ abs(M - Mold))./2.0;
# UPDATE
SED = SEDnew;
X = Xnew;
S = Snew;
Mold = M;
M = Mnew;
# FOR DERIVATIVE CONTROL
efEold = efE;
# EFFECTIVE RELATIVE MASS
if xfilter
if bcond==1 #fixed bcond
efX = doavgf(X,neighbors,0);
elseif bcond==2 #periodic bcond
efX = doavgp(X,neighbors);
end
else
efX = X;
end
# EFFECTIVE STIMULUS
if sfilter
if bcond==1 #fixed bcond
efS = doavgf(S,neighbors,0);
elseif bcond==2 #periodic bcond
efS = doavgp(S,neighbors);
end
else
efS = S;
end
# EFFECTIVE ERROR SIGNAL
efE = zeros(size(S));
efE[efS .> tgS] .= efS[efS .> tgS] .- (1+s).*tgS[efS .> tgS];
efE[efS .< tgS] .= efS[efS .< tgS] .- (1-s).*tgS[efS .< tgS];
# FOR INTEGRAL CONTROL: SUM OF STORED EFFECTIVE STIMULI EST
efEsum .= efEsum .+ efE .- efEhis[:,:,1];
efEhis[:,:,T+2] .= efE;
for t in 1:T+1
efEhis[:,:,t] .= efEhis[:,:,t+1];
end
# PLOT DENSITIES
SE = sum(sum(SED));
println("t: $it, SE: $SE, M: $M")
# STORE FOR CONVERGENCE PLOT
display(Gray.(Xnew))
heatmap(clamp.(Xnew,0,1),xaxis=nothing,yaxis=nothing,legend=nothing,c=:greys,title="it: $it")
append!(states,[clamp.(Xnew,0,1)])
frame(anim)
end
# SAVE FINAL RESULTS
cells = Xnew;
return anim,cells,states
end
function doavgf(c,neighbors,val)
# DOAVGF(X, neighbors,val) sums around each X using fixed boundary
# conditions. val is the fixed value.
# if nargin <3
# val=0;
# end
nely,nelx = size(c);
cext=zeros(nely+2,nelx+2);
cextm=zeros(nely+4,nelx+4);
if neighbors > 24 # Global (nelx*ney-1)
csum = ones(size(c))*sum(sum(c));
else
csum = c; # no neighbors (N=0)
if neighbors > 0 # von Newmann (N=4) > 24 # Global (nelx*ney-1)
# extends c field for fixed BC
cext[nely+2, nelx+2] = val;
cext[2:nely+1, 2:nelx+1] = c;
x = 2:nelx+1;
y = 2:nely+1;
csum = csum +
cext[y,x.+1] + cext[y,x.-1] +
cext[y.+1,x] + cext[y.-1,x];
if neighbors > 4 # Moore (N=8)von Newmann (N=4) > 24 # Global (nelx*ney-1)
csum = csum +
cext[y.+1,x.+1] + cext[y.-1,x.-1] +
cext[y.+1,x.-1] + cext[y.-1,x.+1];
if neighbors > 8 # MvonN (N=12)Moore (N=8)von Newmann (N=4) > 24 # Global (nelx*ney-1)
cextm[nely+4, nelx+4] = val;
cextm[3:nely+2, 3:nelx+2] = c;
y = 3:nely+2; x = 3:nelx+2;
csum = csum +
cextm[y.-2, x] + cextm[y.+2, x] +
cextm[y, x.-2] + cextm[y, x.+2];
if neighbors > 12 # Extended Moore (N=24)MvonN (N=12)Moore (N=8)von Newmann (N=4) > 24 # Global (nelx*ney-1)
csum = csum +
cextm[y.-2, x.-2] + cextm[y.-2, x.-1] +
cextm[y.-2, x.+1] + cextm[y.-2, x.+2] +
cextm[y.+2, x.-2] + cextm[y.+2, x.-1] +
cextm[y.+2, x.+1] + cextm[y.+2, x.+2] +
cextm[y.-1, x.-2] + cextm[y.+1, x.-2] +
cextm[y.-1, x.+2] + cextm[y.+1, x.+2];
end
end
end
end
end
cavg = csum./(neighbors+1); # average csum (matrix)
return cavg
end
#-----------------------------------------------------------------
function doavgp(c,neighbors)
# DOAVGNP(X, neighbors) sums around each X using fixed periodic
# conditions
nely,nelx = size(c);
x = 1:nelx;
y = 1:nely;
if neighbors > 24 # Global (nelx*ney-1)
csum = ones(size(c))*sum(sum(c))-c;
else
csum = zeros(size(c)); # no neighbors (N=0)
if neighbors > 0 # von Newmann (N=4)
csum[mod(y,nely)+1, mod(x,nelx)+1] = csum[mod(y,nely)+1, mod(x,nelx)+1] +
c[mod(y,nely)+1, mod(x.+1,nelx)+1] +
c[mod(y,nely)+1, mod(x.-1,nelx)+1] +
c[mod(y.+1,nely)+1, mod(x,nelx)+1] +
c[mod(y.-1,nely)+1, mod(x,nelx)+1];
if neighbors > 4 # Moore (N=8)
csum[mod(y,nely)+1, mod(x,nelx)+1] = csum[mod(y,nely)+1, mod(x,nelx)+1] +
c[mod(y+1,nely)+1, mod(x+1,nelx)+1] +
c[mod(y-1,nely)+1, mod(x-1,nelx)+1] +
c[mod(y+1,nely)+1, mod(x-1,nelx)+1] +
c[mod(y-1,nely)+1, mod(x+1,nelx)+1];
if neighbors > 8 # MvonN (N=12)
csum[mod(y,nely)+1, mod(x,nelx)+1] = csum[mod(y,nely)+1, mod(x,nelx)+1] +
c[mod(y.-2,nely)+1, mod(x,nelx)+1] +
c[mod(y.+2,nely)+1, mod(x,nelx)+1] +
c[mod(y,nely)+1, mod(x.-2,nelx)+1] +
c[mod(y,nely)+1, mod(x.+2,nelx)+1];
if neighbors > 12 # Extended Moore (N=24)
csum[mod(y,nely)+1, mod(x,nelx)+1] = csum[mod(y,nely)+1, mod(x,nelx)+1] +
c[mod(y.-2,nely)+1, mod(x.-2,nelx)+1] +
c[mod(y.-2,nely)+1, mod(x.-1,nelx)+1] +
c[mod(y.-2,nely)+1, mod(x.+1,nelx)+1] +
c[mod(y.-2,nely)+1, mod(x.+2,nelx)+1] +
c[mod(y.+2,nely)+1, mod(x.-2,nelx)+1] +
c[mod(y.+2,nely)+1, mod(x.-1,nelx)+1] +
c[mod(y.+2,nely)+1, mod(x.+1,nelx)+1] +
c[mod(y.+2,nely)+1, mod(x.+2,nelx)+1] +
c[mod(y.-1,nely)+1, mod(x.-2,nelx)+1] +
c[mod(y.+1,nely)+1, mod(x.-2,nelx)+1] +
c[mod(y.-1,nely)+1, mod(x.+2,nelx)+1] +
c[mod(y.+1,nely)+1, mod(x.+2,nelx)+1];
end
end
end
end
end
cavg = csum./(neighbors); # average csum (matrix)
return cavg
end
function lookznf(c,neighbors,val)
# LOOKZNF(X, neighbors) products around each X using fixed boundary
# conditions
# if nargin <3
# val=0;
# end
c[c.<=0.001].=0;
nely,nelx = size(c);
cext=zeros(nely+2,nelx+2);
cextm=zeros(nely+4,nelx+4);
cpro = copy(c);
if neighbors <= 24
cpro = c; # no neighbors (N=0)
if neighbors > 0 # von Newmann (N=4)
# extends c field for fixed BC
cext[nely+2, nelx+2] = val;
cext[2:nely+1, 2:nelx+1] = c;
x = 2:nelx+1;
y = 2:nely+1;
cpro = 1*
cext[y,x.+1] .* cext[y,x.-1] .*
cext[y.+1,x] .* cext[y.-1,x];
if neighbors > 4 # Moore (N=8)
cpro = cpro .*
cext[y.+1,x.+1] .* cext[y.-1,x.-1] .*
cext[y.+1,x.-1] .* cext[y.-1,x.+1];
if neighbors > 8 # MvonN (N=12)
cextm[nely+4, nelx+4] = val;
cextm[3:nely+2, 3:nelx+2] = c;
y = 3:nely+2; x = 3:nelx+2;
cpro = cpro .*
cextm[y.-2, x] .* cextm[y.+2, x] .*
cextm[y, x.-2] .* cextm[y, x.+2];
if neighbors > 12 # Extended Moore (N=24)
csum = csum .*
cextm[y.-2, x.-2] .* cextm[y.-2, x.-1] .*
cextm[y.-2, x.+1] .* cextm[y.-2, x.+2] .*
cextm[y.+2, x.-2] .* cextm[y.+2, x.-1] .*
cextm[y.+2, x.+1] .* cextm[y.+2, x.+2] .*
cextm[y.-1, x.-2] .* cextm[y.+1, x.-2] .*
cextm[y.-1, x.+2] .* cextm[y.+1, x.+2];
end
end
end
end
end
cproy=copy(cpro)
cpro[cproy.>0].=0
cpro[cproy.==0].=1
return cpro
end
#-----------------------------------------------------------------
function lookznp(c,neighbors)
# LOOKZNP(X, neighbors) products around each X using fixed periodic
# conditions
c[c.<=0.001].=0;
nely,nelx = size(c);
x = 1:nelx;
y = 1:nely;
cpro = copy(c);
if neighbors <= 24
if neighbors > 0 # von Newmann (N=4)
cpro[mod.(y,nely).+1, mod.(x,nelx).+1] =
c[mod.(y,nely).+1, mod.(x+1,nelx).+1] .*
c[mod.(y,nely).+1, mod.(x-1,nelx).+1] .*
c[mod.(y.+1,nely).+1, mod.(x,nelx).+1] .*
c[mod.(y.-1,nely).+1, mod.(x,nelx).+1];
if neighbors > 4 # Moore (N=8)
cpro[mod(y,nely)+1, mod(x,nelx)+1] =
cpro[mod.(y,nely).+1, mod.(x,nelx).+1] .*
c[mod.(y.+1,nely).+1, mod.(x.+1,nelx).+1] .*
c[mod.(y.-1,nely).+1, mod.(x.-1,nelx).+1] .*
c[mod.(y.+1,nely).+1, mod.(x.-1,nelx).+1] .*
c[mod.(y.-1,nely).+1, mod.(x.+1,nelx).+1];
if neighbors > 8 # MvonN (N=12)
cpro[mod(y,nely)+1, mod(x,nelx)+1] =
cpro[mod(y,nely)+1, mod.(x,nelx)+1] .*
c[mod.(y.-2,nely)+1, mod.(x,nelx)+1] .*
c[mod.(y.+2,nely)+1, mod.(x,nelx)+1] .*
c[mod.(y,nely)+1, mod.(x.-2,nelx)+1] .*
c[mod.(y,nely)+1, mod.(x.+2,nelx)+1];
if neighbors > 12 # Extended Moore (N=24)
cpro[mod(y,nely)+1, mod(x,nelx)+1] =
cpro[mod(y,nely)+1, mod(x,nelx)+1] .*
c[mod.(y.-2,nely).+1, mod.(x.-2,nelx).+1] .*
c[mod.(y.-2,nely).+1, mod.(x.-1,nelx).+1] .*
c[mod.(y.-2,nely).+1, mod.(x.+1,nelx).+1] .*
c[mod.(y.-2,nely).+1, mod.(x.+2,nelx).+1] .*
c[mod.(y.+2,nely).+1, mod.(x.-2,nelx).+1] .*
c[mod.(y.+2,nely).+1, mod.(x.-1,nelx).+1] .*
c[mod.(y.+2,nely).+1, mod.(x.+1,nelx).+1] .*
c[mod.(y.+2,nely).+1, mod.(x.+2,nelx).+1] .*
c[mod.(y.-1,nely).+1, mod.(x.-2,nelx).+1] .*
c[mod.(y.+1,nely).+1, mod.(x.-2,nelx).+1] .*
c[mod.(y.-1,nely).+1, mod.(x.+2,nelx).+1] .*
c[mod.(y.+1,nely).+1, mod.(x.+2,nelx).+1];
end
end
end
end
end
cproy=copy(cpro)
cpro[cproy.>0].=0
cpro[cproy.==0].=1
return cpro
end
function lookonf(c,neighbors,val)
# LOOKONF(X, neighbors) sums around each X using fixed boundary
# conditions
# if nargin <3
# val=0;
# end
c[c.>=0.999].=1;
c[c.<0.999].=0;
nely,nelx = size(c);
cext=zeros(nely+2,nelx+2);
cextm=zeros(nely+4,nelx+4);
if neighbors <= 24 # Global (nelx*ney-1)
csum = zeros(size(c)); # no neighbors (N=0)
if neighbors > 0 # von Newmann (N=4)
# extends c field for fixed BC
cext[nely+2, nelx+2] = val;
cext[2:nely+1, 2:nelx+1] = c;
x = 2:nelx+1;
y = 2:nely+1;
csum = csum + cext[y,x+1] + cext[y,x-1] +
cext[y.+1,x] + cext[y.-1,x];
if neighbors > 4 # Moore (N=8)
csum = csum + cext[y.+1,x.+1] + cext[y.-1,x.-1] +
cext[y.+1,x.-1] + cext[y.-1,x.+1];
if neighbors > 8 # MvonN (N=12)
cextm[nely+4, nelx+4] = val;
cextm[3:nely+2, 3:nelx+2] = c;
y = 3:nely+2; x = 3:nelx+2;
csum = csum + cextm[y-2, x] + cextm[y+2, x] +
cextm[y, x.-2] + cextm[y, x.+2];
if neighbors > 12 # Extended Moore (N=24)
csum = csum +
cextm[y.-2, x.-2] + cextm[y.-2, x.-1] +
cextm[y.-2, x.+1] + cextm[y.-2, x.+2] +
cextm[y.+2, x.-2] + cextm[y.+2, x.-1] +
cextm[y.+2, x.+1] + cextm[y.+2, x.+2] +
cextm[y.-1, x.-2] + cextm[y.+1, x.-2] +
cextm[y.-1, x.+2] + cextm[y.+1, x.+2];
end
end
end
end
end
cavg = csum./(neighbors); # average csum (matrix)
cout = cavg > 0;
return cout
end
#-----------------------------------------------------------------
function looknp(c,neighbors)
# LOOKONP(X, neighbors) sums around each X using fixed periodic
# conditions
c[c.>=0.999].=1;
c[c.<0.999].=0;
nely,nelx = size(c);
x = 1:nelx;
y = 1:nely;
if neighbors <= 24
csum = zeros(size(c)); # no neighbors (N=0)
if neighbors > 0 # von Newmann (N=4)
csum[mod.(y,nely).+1, mod.(x,nelx)+1] =
csum[mod(y,nely).+1, mod.(x,nelx).+1] +
c[mod.(y,nely).+1, mod.(x.+1,nelx).+1] +
c[mod.(y,nely).+1, mod.(x.-1,nelx).+1] +
c[mod.(y.+1,nely).+1, mod.(x,nelx).+1] +
c[mod.(y.-1,nely).+1, mod.(x,nelx).+1];
if neighbors > 4 # Moore (N=8)
csum[mod.(y,nely)+1, mod.(x,nelx).+1] =
csum[mod.(y,nely).+1, mod.(x,nelx).+1] +
c[mod.(y.+1,nely).+1, mod.(x.+1,nelx).+1] +
c[mod.(y.-1,nely).+1, mod.(x.-1,nelx).+1] +
c[mod.(y.+1,nely).+1, mod.(x.-1,nelx).+1] +
c[mod.(y.-1,nely).+1, mod.(x.+1,nelx).+1];
if neighbors > 8 # MvonN (N=12)
csum[mod(y,nely)+1, mod(x,nelx)+1] =
csum[mod.(y,nely).+1, mod.(x,nelx).+1] +
c[mod.(y.-2,nely).+1, mod.(x,nelx).+1] +
c[mod.(y.+2,nely).+1, mod.(x,nelx).+1] +
c[mod.(y,nely).+1, mod.(x.-2,nelx).+1] +
c[mod.(y,nely).+1, mod.(x.+2,nelx).+1];
if neighbors > 12 # Extended Moore (N=24)
csum[mod(y,nely)+1, mod(x,nelx)+1] =
csum[mod(y,nely)+1, mod(x,nelx)+1] +
c[mod.(y.-2,nely).+1, mod.(x.-2,nelx).+1] +
c[mod.(y.-2,nely).+1, mod.(x.-1,nelx).+1] +
c[mod.(y.-2,nely).+1, mod.(x.+1,nelx).+1] +
c[mod.(y.-2,nely).+1, mod.(x.+2,nelx).+1] +
c[mod.(y.+2,nely).+1, mod.(x.-2,nelx).+1] +
c[mod.(y.+2,nely).+1, mod.(x.-1,nelx).+1] +
c[mod.(y.+2,nely).+1, mod.(x.+1,nelx).+1] +
c[mod.(y.+2,nely).+1, mod.(x.+2,nelx).+1] +
c[mod.(y.-1,nely).+1, mod.(x.-2,nelx).+1] +
c[mod.(y.+1,nely).+1, mod.(x.-2,nelx).+1] +
c[mod.(y.-1,nely).+1, mod.(x.+2,nelx).+1] +
c[mod.(y.+1,nely).+1, mod.(x.+2,nelx).+1];
end
end
end
end
end
cavg = csum./(neighbors); # average csum (matrix)
cout = cavg>0;
return cout
end
function fea(x, fxF, fxU, E, nu, p)
nelx = size(x,2);
nely = size(x,1);
lcase = convert(Int,maximum(fxF[:,3]));
# Element stiffness matrix for a bilinear element
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[0+1] k[1+1] k[2+1] k[3+1] k[4+1] k[5+1] k[6+1] k[7+1];
k[1+1] k[0+1] k[7+1] k[6+1] k[5+1] k[4+1] k[3+1] k[2+1];
k[2+1] k[7+1] k[0+1] k[5+1] k[6+1] k[3+1] k[4+1] k[1+1];
k[3+1] k[6+1] k[5+1] k[0+1] k[7+1] k[2+1] k[1+1] k[4+1];
k[4+1] k[5+1] k[6+1] k[7+1] k[0+1] k[1+1] k[2+1] k[3+1];
k[5+1] k[4+1] k[3+1] k[2+1] k[1+1] k[0+1] k[7+1] k[6+1];
k[6+1] k[3+1] k[4+1] k[1+1] k[2+1] k[7+1] k[0+1] k[5+1];
k[7+1] k[2+1] k[1+1] k[4+1] k[3+1] k[6+1] k[5+1] k[0+1] ];
# Global stiffness matrix, and force and displacement vectors
K = spzeros(2*(nelx+1)*(nely+1), 2*(nelx+1)*(nely+1));
F = spzeros(2*(nely+1)*(nelx+1), lcase);
U = spzeros(2*(nely+1)*(nelx+1), lcase);
# Obtain global stiffness matrix
for ely = 1:nely
for elx = 1:nelx
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];
K[edof,edof] = K[edof,edof] + x[ely,elx]^p*KE;
end
end
# DEFINE LOADS AND SUPPORTS
# loads
for i = 1:size(fxF,1)
F[fxF[i,1],fxF[i,3]] = F[fxF[i,1],fxF[i,3]] + fxF[i,2];
end
# supports
for lc = 1:lcase
fxdof = fxU[fxU[:,3].==lc, 1];
fxdis = fxU[fxU[:,3].==lc, 2];
if isempty(fxdof)
fxdof = fxU[fxU[:,3].==1, 1];
fxdis = fxU[fxU[:,3].==1, 2];
end
alldof = 1:2*(nely+1)*(nelx+1);
freedof = setdiff(alldof,fxdof);
# solution
U[freedof,lc] = K[freedof,freedof] \ Array(F[freedof,lc]);
U[fxdof,lc] = fxdis;
end
# STRAIN ENERGY DENSITIES AND SENSITIVITIES
SEDt = zeros(nely,nelx,lcase);
SED = zeros(nely,nelx);
for ely = 1:nely
for elx = 1:nelx
n1 = (nely+1)*(elx-1)+ely;
n2 = (nely+1)* elx +ely;
# dc=zeros(ely,elx)
# dc(ely,elx) = 0.;
for lc = 1:lcase
Ue = U[[2*n1-1;2*n1; 2*n2-1;2*n2; 2*n2+1;2*n2+2; 2*n1+1;2*n1+2], lc];
SEDi = 1/2*x[ely,elx]^p*Ue'*KE*Ue;
xi = x[ely,elx];
if lcase >1
SEDt[ely,elx,lc] = SEDi;
end
SED[ely,elx] = SED[ely,elx] + SEDi;
end
end
end
SED=SED/lcase;
# SEDt
return SED
end
# SED = fea(X, fxF, fxU, Ymod, nu, p)
# size(SED)
(anim,cells,states)=hcastruc1(X, fxF, fxU, Ymod, nu, p, tgS, s, scond, k, neighbors, bcond, itmax, vtol, ctype, ttype, T, xfilter, sfilter)
gif(anim,"hca.gif", fps=5)
X=clamp.(cells,0,1)
nel=(nelx+1)*(nely+1)
ind=1:nel
function getIndex(i,j,nelx,nely)
return (i-1)*(nely+1)+(j-1)+1
end
function getIndex(ind,nelx,nely)
j=mod((ind-1),nely+1)
i=(ind-1)÷(nely+1)
return (i+1),(j+1)
end
nel=(nelx)*(nely)
ind=1:nel
function getIndex(i,j,nelx,nely)
return (i-1)*(nely)+(j-1)+1
end
function getIndex(ind,nelx,nely)
j=mod((ind-1),nely)
i=(ind-1)÷(nely)
return (i+1),(j+1)
end
#8 neighbours
neigh=[]
indIJ=zeros(nel,2)
XIJ=zeros(nel)
for ii in ind
n=[]
(i,j)=getIndex(ii,nelx,nely)
indIJ[ii,1]=i
indIJ[ii,2]=j
XIJ[ii]=X[i,j]
if i>1
append!(n,[[i-1,j]])
if j>1
append!(n,[[i-1,j-1]])
end
if j<=nely
append!(n,[[i-1,j+1]])
end
end
if i<nelx
append!(n,[[i+1,j]])
if j>1
append!(n,[[i+1,j-1]])
end
if j<=nely
append!(n,[[i+1,j+1]])
end
end
if j>1
append!(n,[[i,j-1]])
end
if j<nely
append!(n,[[i,j+1]])
end
append!(neigh,[n])
end
neigh;
#4 neighbours
neigh=[]
indIJ=zeros(Int,nel,2)
XIJ=zeros(nel)
for ii in ind
n=[]
(i,j)=getIndex(ii,nelx,nely)
indIJ[ii,1]=i
indIJ[ii,2]=j
XIJ[ii]=X[i,j]
if i>1
append!(n,[[i-1,j]])
end
if i<nelx
append!(n,[[i+1,j]])
end
if j>1
append!(n,[[i,j-1]])
end
if j<nely
append!(n,[[i,j+1]])
end
append!(neigh,[n])
end
neigh;
links=[]
XIJE=[]
for i in ind
for j in 1:length(neigh[i])
append!(links,[[[indIJ[i,2],neigh[i][j][2]],[indIJ[i,1],neigh[i][j][1]]]])
append!(XIJE,min(X[indIJ[i,1],indIJ[i,2]],X[neigh[i][j][1],neigh[i][j][2]]))
end
end
XIJEs=[]
for ii in 1:length(states)
xx=[]
for i in ind
for j in 1:length(neigh[i])
append!(xx,min(reverse(states[ii],dims=1)[indIJ[i,1],indIJ[i,2]],reverse(states[ii],dims=1)[neigh[i][j][1],neigh[i][j][2]]))
end
end
append!(XIJEs,[xx])
end
XIJEs;
linkss=zeros(length(links),2,2)
for i in 1:length(links)
for j in 1:2
for k in 1:2
linkss[i,j,k]=links[i][j][k]
end
end
end
linkss[:,1,:]
scatter(indIJ[:,2],indIJ[:,1],color=:black,label="",markeralpha = XIJ, aspect_ratio=:equal,xlim=(0,nely+2),ylim=(0,nelx+2))
for i in ind
for j in 1:length(neigh[i])
plot!([indIJ[i,2],neigh[i][j][2]],[indIJ[i,1],neigh[i][j][1]],label="",color=:blue,linewidth = 1,linealpha = XIJ[i])
end
end
plot!()
scatter(indIJ[:,2],indIJ[:,1],color=:black,label="",markeralpha = XIJ, aspect_ratio=:equal,xlim=(0,nely+2),ylim=(0,nelx+2))
plot!(linkss[:,1,:]',linkss[:,2,:]',label="",color=:blue,linealpha = XIJE',linewidth = 1)
# for i in 1:length(XIJE)
# plot!(links[i][1],links[i][2],label="",color=:blue,linewidth = 1,linealpha = XIJE[i])
# end
# plot!()
anim1=Animation()
######
i=0
display(i)
scatter(indIJ[:,2],indIJ[:,1],color=:black,label="",markeralpha = 0.85, aspect_ratio=:equal,xlim=(0,nely+2),ylim=(0,nelx+2),title="it: $i")
plot!(linkss[:,1,:]',linkss[:,2,:]',label="",color=:blue,linealpha = 1,linewidth = 0.85)
frame(anim1)
####
# for i in 1:length(states)
for i in 1:10
display(i)
scatter(indIJ[:,2],indIJ[:,1],color=:black,label="",markeralpha = reverse(states[i],dims=1)'[:], aspect_ratio=:equal,xlim=(0,nely+2),ylim=(0,nelx+2),title="it: $i")
plot!(linkss[:,1,:]',linkss[:,2,:]',label="",color=:blue,linealpha = XIJEs[i]',linewidth = 1)
frame(anim1)
end
gif(anim1,"hca_strut.gif", fps=1)
display(1)
i=10
scatter(indIJ[:,2],indIJ[:,1],color=:black,label="",markeralpha = reverse(states[i],dims=1)'[:], aspect_ratio=:equal,xlim=(0,nely+2),ylim=(0,nelx+2),title="it: $i")
plot!(linkss[:,1,:]',linkss[:,2,:]',label="",color=:blue,linealpha = XIJEs[i]',linewidth = 1)
reverse