-
Notifications
You must be signed in to change notification settings - Fork 0
/
InvHomoIPOPT.m
129 lines (112 loc) · 4.21 KB
/
InvHomoIPOPT.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
classdef InvHomoIPOPT < handle
properties
fem, Ctar, plot_freq
beta, eta
xbar, xhat, Md, UA, CH
vf_scale, delC_scale
flist
end
methods
function obj = InvHomoIPOPT(fem, Ctar, plot_freq)
if nargin < 3
obj.plot_freq = 0;
else
obj.plot_freq = plot_freq;
end
obj.fem = fem;
obj.Ctar = Ctar;
obj.beta = 1;
obj.eta = 0.5;
end
function f = objective(obj, x)
% Filtering
obj.xbar = obj.fem.H * x;
% Projection
obj.xhat = projectDensity(obj.xbar, obj.beta, obj.eta);
obj.Md = 400 * mean(obj.xhat .* (1 - obj.xhat));
% Evaluate volume fraction
vf = mean(obj.xhat);
if isempty(obj.vf_scale)
obj.vf_scale = 1 / vf;
end
% Homogenization
[obj.CH, obj.UA] = computeHomo(obj.xhat, obj.fem);
% Evaluate constraint
delC = obj.CH([1, 5, 9, 8, 7, 4]) - obj.Ctar;
delC = sum(delC.^2);
if isempty(obj.delC_scale)
obj.delC_scale = 100 / delC;
end
f = obj.delC_scale * delC + obj.vf_scale * vf;
end
function g = gradient(obj, x)
% Compute gradient
dxdx = deprojectDensity(obj.xbar, obj.beta, obj.eta);
dvf = ones(obj.fem.num_elems, 1) / obj.fem.num_elems;
dvf = obj.fem.H * (dvf .* dxdx);
% Compute jacobian
dxdx = deprojectDensity(obj.xbar, obj.beta, obj.eta);
dCH = computeHomoGrad(obj.xhat, obj.UA, obj.fem);
delC = obj.CH([1, 5, 9, 8, 7, 4]) - obj.Ctar;
idx = [1, 5, 9, 8, 7, 4];
ddelC = zeros(6, obj.fem.num_elems);
for i = 1:6
ddelC(i, :) = (obj.fem.H * (dCH{idx(i)} .* dxdx))';
end
ddelC = 2 * delC * ddelC;
g = obj.delC_scale * ddelC' + obj.vf_scale * dvf;
end
function x = optim(obj, x0, max_iter)
% Initialize
f0 = obj.objective(x0);
obj.flist = f0;
% Options
options.lb = zeros(obj.fem.num_elems, 1);
options.ub = ones(obj.fem.num_elems, 1);
options.ipopt.hessian_approximation = 'limited-memory';
options.ipopt.max_iter = max_iter;
options.ipopt.acceptable_tol = 1e-2;
options.ipopt.print_level = 0;
% Functions
funcs.objective = @obj.objective;
funcs.gradient = @obj.gradient;
funcs.iterfunc = @obj.callback;
% Strat optimization
x = x0;
while true
x = ipopt(x, funcs, options);
if obj.Md > 15
obj.beta = min(16, 2 * obj.beta);
else
break
end
end
end
function b = callback(obj, iter, f, x)
b = true;
% Record
obj.flist = cat(1, obj.flist, f);
% if mod(iter, 10) == 0 && iter > 50 && obj.Md > 15
% obj.beta = min(8, 1.1 * obj.beta);
% end
% Monitor
if mod(iter, obj.plot_freq) == 0 && obj.plot_freq > 0
subplot(2, 2, 1); cla
patch('faces', obj.fem.elems, 'vertices', obj.fem.nodes, ...
'facecolor', 'flat', 'edgecolor', 'none', ...
'facevertexcdata', obj.xhat);
axis image;
colormap(flipud(gray));
caxis([0, 1])
colorbar;
title(sprintf('[%3d] f=%.3e', iter, f))
subplot(2, 2, 2);
bar([obj.CH([1, 5, 9, 8, 7, 4]); obj.Ctar]')
subplot(2, 2, [3, 4]); cla
semilogy(obj.flist, 'r');
title(sprintf('Md=%.2f, beta=%.1f', obj.Md, obj.beta))
drawnow;
end
end
end
end