forked from lyc102/ifem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdivDarcy.m
89 lines (84 loc) · 3 KB
/
divDarcy.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
function u = divDarcy(M,B,f,g,u,node,elem,edge,elem2edge,freeEdge)
%% u = DIVDARCY
%
% Find a u such at Bu = g
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.
showmesh(node,elem);
%% Isolate equations
pdeg = full(sum(spones(B),2));
isIsoElem = (pdeg == 1);
isoElem = find(isIsoElem);
[ii,jj,ss] = find(B(isIsoElem,:));
u(jj) = g(isoElem(ii))./ss;
%% Data structure
N = max(elem(:));
NT = size(elem,1);
NE = size(edge,1);
validEdge = 1:NE;
validEdge(freeEdge(jj)) = []; % remove isolate edges
e2v = sparse([validEdge,validEdge], double(edge(validEdge,:)), 1, NE, N);
validElem = find(~isIsoElem); % remove isolate element
t2v = sparse([validElem,validElem,validElem], elem(validElem,:), 1, NT, N);
oppe2v = sparse(double(elem2edge(:)), elem(:), 1, NE, N);
% In e2v, remove isolated edges dof since their values are determined. But
% they are remained in oppe2v as boundary dofs
%% Index map and indicator of elements
idxMap = zeros(NE,1);
idxMap(freeEdge) = 1:length(freeEdge);
isOpenElem = true(NT,1);
isSolvedElem = false(NT,1);
isSolvedElem(isoElem) = true;
% In solved elements: Bu = g
temp = abs(g-B*u);
idx = temp<1e-14;
findelem(node,elem,idx,'index','FaceColor','c');
%% Overlapping Schwarz smoother
for i = 1:N
findnode(node,i);
starElem = find(t2v(:,i));
if all(isSolvedElem(starElem)) % all elements are solved
continue;
end
starEdge = idxMap(find(e2v(:,i))); %#ok<*FNDSB>
starBdEdge = idxMap(find(oppe2v(:,i))); % edge opposite to a vertex
domainStarEdgeIdx = (starEdge == 0); % remove fixed edge d.o.f.
starEdge(domainStarEdgeIdx) = [];
domainBdEdgeIdx = (starBdEdge == 0);
starBdEdge(domainBdEdgeIdx) = [];
% solve loccal problem
locM = M(starEdge,[starEdge; starBdEdge]);
locB = B(starElem,[starEdge; starBdEdge]);
% update right hand side
locf = f(starEdge) - locM*u([starEdge; starBdEdge]);
locg = g(starElem) - locB*u([starEdge; starBdEdge]);
locF = [locf; locg];
Nf = length(locf);
Ng = length(locg);
locM = locM(:,1:Nf);
locB = locB(:,1:Nf);
locL = [locM locB'; locB zeros(Ng)];
% local problem is unique up to a constant
% leave an open element non-solved
locOpenElem = find(isOpenElem(starElem));
if ~isempty(locOpenElem)
locOpenElem = locOpenElem(1);
else
locOpenElem = Ng; % chose the last one if no elem open
end
activeIdx = true(Nf+Ng,1);
activeIdx(Nf+locOpenElem) = false;
locep = locL(activeIdx,activeIdx)\locF(activeIdx);
u(starEdge) = u(starEdge) + locep(1:Nf);
isSolvedElem(starElem) = true;
locResidual = abs(locg(locOpenElem) - locB(locOpenElem,:)*locep(1:Nf));
if locResidual > 1e-14 % check the residual of the open element
isSolvedElem(starElem(locOpenElem)) = false;
end
isOpenElem(starElem) = false;
% debug: plot open elem and check residual of each element
findelem(node,elem,starElem(locOpenElem),'index','FaceColor','r');
temp = abs(g-B*u);
idx = temp<1e-14;
findelem(node,elem,idx,'index','FaceColor','c');
end