-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolve_sparse_leastnorm_constraint1.m
69 lines (66 loc) · 2.3 KB
/
solve_sparse_leastnorm_constraint1.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
function changedArea = solve_sparse_leastnorm_constraint1(areaToChange,area,ncell);
nz = find(areaToChange>0);
changedArea = areaToChange;
numnz = (1:length(nz))';
posI = zeros(ncell*ncell,1);
posJ = zeros(ncell*ncell,1);
posZ = zeros(ncell*ncell,1);
bConst = zeros(2*ncell,1);
bConst(1:ncell) = area; % local mass conservation (need to change if non-div free velocity field)
bConst(ncell+1:2*ncell) = area; % global mass conservation
ctr=1;
for i=1:ncell
nzCol = find(areaToChange(:,i)>0);
nzColLoc = nzCol + (i-1)*(ncell);
for j=1:length(nzColLoc)
%constraint for local mass cons
if ~isempty(numnz(nz==nzColLoc(j)))
posI(ctr)=i;
posJ(ctr)=numnz(nz==nzColLoc(j));
posZ(ctr)=areaToChange(nz(numnz(nz==nzColLoc(j))));
ctr=ctr+1;
end
end
nzRow = find(areaToChange(i,:)>0);
nzRowLoc = (nzRow-1)*(ncell)+i;
for j=1:length(nzRowLoc)
% constraint for global mass cons
if ~isempty(numnz(nz==nzRowLoc(j)))
posI(ctr)=i+ncell;
posJ(ctr)=numnz(nz==nzRowLoc(j));
posZ(ctr)=areaToChange(nz(numnz(nz==nzRowLoc(j))));
ctr=ctr+1;
end
end
end
posI(posI==0)=[];
posJ(posJ==0)=[];
posZ(posZ==0)=[];
Aconst = sparse(posI,posJ,posZ);
lb = -1+1e-4*ones(size(nz));
ub = 1-1e-4*ones(size(nz));
Aconst = Aconst(1:2*ncell-1,:);
bConst = bConst(1:2*ncell-1);
bConst = bConst -Aconst*ones(size(nz));
H=speye(length(nz));
xadj = quadprog(H,[],[],[],Aconst,bConst,lb,ub);
% options = optimset('Display','off');
% xadj = quadprog(H,[],[],[],Aconst,bConst,lb,[],[],options);
%% alternative way to solve for xadj using sparse
% x = optimvar('x',length(nz));
% qprob = optimproblem;
% options = optimoptions('quadprog','Algorithm','interior-point-convex',...
% 'LinearSolver','sparse','StepTolerance',0);
% obj = 1/2*x'*H*x;
% qprob.Objective = obj;
% cons1 = bConst-Aconst*areaToChange(nz)-Aconst*x ==0;
% cons2 = x+changedArea(nz)-0.01*min(areaToChange(nz))>=0;
% qprob.Constraints.cons1 = cons1;
% qprob.Constraints.cons2 = cons2;
% xadj = solve(qprob,'Options',options);
% if ~isempty(xadj)
% changedArea(nz) = xadj.x+changedArea(nz);
% end
if ~isempty(xadj)
changedArea(nz) = changedArea(nz) + xadj.*changedArea(nz);
end