1+ %% Convergence Test for Cuvilinear Operators
2+ %
3+ % In 2D space, MOLE operators can only calculate the xi and eta derivatives
4+ % On a curvilinear domain, the x and xi, and y and eta directions are
5+ % not always the same. We can assume a transformation of x = x(xi, eta)
6+ % and y = y(xi, eta) with Jacobian J = x_xi y_eta - x_eta y_xi.
7+ %
8+ % If we have a function u(x,y), via chain rule we get:
9+ % u_xi = u_x x_xi + u_y y_xi
10+ % u_eta = u_x x_eta + u_y y_eta
11+ %
12+ % Assuming a non-zero Jacobian, we can invert the mapping to obtain:
13+ % u_x = (u_xi y_eta - u_eta y_xi) / J
14+ % u_y = (u_eta x_xi - u_xi x_eta) / J
15+ %
16+ % Everything on the right is easily calculable using MOLE's operators
17+ %
18+
19+ %% Comparison between current implementation and new implementation
20+ %
21+ % Current Implementation:
22+ % - Nodal Jacobian derivatives
23+ % - MATLAB interpolation (2nd order)
24+ % - Hard to understand implementation (DI2 and GI2 functions: It is
25+ % obvious what they are doing, but not how they are doing it.)
26+ % - Cannot handle periodic domains
27+ %
28+ % New Implementation
29+ % - MOLE gradient used to calculate Jacobian derivatives
30+ % - MOLE interpolators
31+ % - Easy to understand implementation
32+ % - Can handle periodic domains
33+ %
34+
35+ %% Problem
36+ %
37+ % ∆u = 0
38+ %
39+ % 1 < R < 2
40+ % 0 < θ < pi
41+ %
42+ % x = R cos(θ)
43+ % y = R sin(θ)
44+ %
45+ % Dirichlet Boundary Conditions
46+ %
47+ % Exact Solution: (many options)
48+ % u(x,y) = sin(x) sinh(y)
49+ % u(x,y) = x^2 - y^2
50+ % u(x,y) = ln(x^2 + y^2)
51+ % u(x,y) = x^3 - 3 x y^2
52+ %
53+ close all ; clear ; clc ;
54+
55+
56+ %% Fixed mesh, varying k Comparison
57+ % Parameters
58+ k = [2 4 6 8 ];
59+ m = 100 ;
60+ n = 25 ;
61+ numCenters = (m + 2 ) * (n + 2 );
62+ dx = pi / m ;
63+ dy = 1 / n ;
64+
65+ % ue = @(X,Y) sin(X) .* sinh(Y);
66+ % ue = @(X,Y) X.^2 - Y.^2;
67+ % ue = @(X,Y) log(X.^2 + Y.^2);
68+ ue = @(X ,Y ) X .^ 3 - 3 * X .* Y .^ 2 ;
69+
70+ errorCur = zeros(size(k ));
71+ errorNew = zeros(size(k ));
72+
73+ dc = [1 ;1 ;1 ;1 ]; nc = [0 ;0 ;0 ;0 ];
74+
75+ for i = 1 : numel(k )
76+
77+ fprintf(" Starting k = %d\n" , k(i ))
78+ % Nodes to make current operators
79+ rsN = 1 : dy : 2 ; tsN = pi : -dx : 0 ;
80+ [TSN ,RSN ] = meshgrid(tsN ,rsN );
81+ xn = RSN .* cos(TSN );
82+ yn = RSN .* sin(TSN );
83+
84+ % Centers to make new operators
85+ rsC = [1 1 + dy / 2 : dy : 2 - dy / 2 2 ];
86+ tsC = [pi pi - dx / 2 : -dx : dx / 2 0 ];
87+ [TSC ,RSC ] = meshgrid(tsC ,rsC );
88+ X = RSC .* cos(TSC );
89+ Y = RSC .* sin(TSC );
90+
91+ % Build operators
92+ curG = grad2DCurv(k(i ),xn ,yn );
93+ curD = div2DCurv(k(i ),xn ,yn );
94+ curL = curD * curG ;
95+
96+ newG = grad2DCurv(k(i ),X ,Y ,dc ,nc );
97+ newD = div2DCurv(k(i ),X ,Y ,dc ,nc );
98+ newL = newD * newG ;
99+
100+ % Boundary Conditions
101+ u = ue(X ,Y );
102+
103+ l = u(: ,1 ); r = u(: ,end );
104+ b = u(1 ,: )' ; t = u(end ,: )' ;
105+ v = {l(2 : end - 1 );r(2 : end - 1 );b ;t };
106+ B = zeros(numCenters ,1 );
107+ [curL ,B ] = addScalarBC2D(curL ,B ,k(i ),m ,dx ,n ,dy ,dc ,nc ,v );
108+ [newL ,B ] = addScalarBC2D(newL ,B ,k(i ),m ,dx ,n ,dy ,dc ,nc ,v );
109+
110+ curU = curL \ B ;
111+ newU = newL \ B ;
112+
113+ curU = reshape(curU ,m + 2 ,n + 2 )' ;
114+ newU = reshape(newU ,m + 2 ,n + 2 )' ;
115+
116+ % Maximum Absolute Error
117+ errorCur(i ) = max(max(abs(u - curU )));
118+ errorNew(i ) = max(max(abs(u - newU )));
119+
120+ end
121+
122+ % Plot results
123+ figure
124+ hold on
125+ plot(k , errorCur , ' LineWidth' , 2 )
126+ plot(k , errorNew , ' LineWidth' , 2 )
127+ hold off
128+ yscale log
129+ xlim([k(1 ), k(end )])
130+ xlabel(' k' )
131+ ylabel(' Maximum Absolute Error' )
132+ legend(' Current Implementation' , ' New Implementation' ,' Location' ,' southwest' )
133+ grid on
134+ title(" Maximum Absolute Error vs k" )
135+ subtitle(" ∆u = 0, 1 < R < 2, 0 < theta < π, m = 100, n = 25" )
136+
137+
138+ %% Fixed k, varying mesh Comparison
139+ k = 4 ;
140+ minCells = 2 * k + 1 ;
141+ m = [4 8 16 32 64 ] * minCells ;
142+ n = [1 2 4 8 16 ] * minCells ;
143+ numCenters = (m + 2 ) .* (n + 2 );
144+ dx = pi ./ m ;
145+ dy = 1 ./ n ;
146+
147+ errorCur = zeros(size(numCenters ));
148+ errorNew = zeros(size(numCenters ));
149+
150+ dc = [1 ;1 ;1 ;1 ]; nc = [0 ;0 ;0 ;0 ];
151+
152+ for i = 1 : numel(numCenters )
153+
154+ fprintf(" Starting m = %d, n = %d\n" , m(i ),n(i ))
155+ % Nodes for current operators
156+ rsN = 1 : dy(i ): 2 ; tsN = pi : -dx(i ): 0 ;
157+ [TSN ,RSN ] = meshgrid(tsN ,rsN );
158+ xn = RSN .* cos(TSN );
159+ yn = RSN .* sin(TSN );
160+
161+ % Centers for new operators
162+ rsC = [1 1 + dy(i )/2 : dy(i ): 2 - dy(i )/2 2 ];
163+ tsC = [pi pi - dx(i )/2 : -dx(i ): dx(i )/2 0 ];
164+ [TSC ,RSC ] = meshgrid(tsC ,rsC );
165+ X = RSC .* cos(TSC );
166+ Y = RSC .* sin(TSC );
167+
168+ % Build operators
169+ curG = grad2DCurv(k ,xn ,yn );
170+ curD = div2DCurv(k ,xn ,yn );
171+ curL = curD * curG ;
172+
173+ newG = grad2DCurv(k ,X ,Y ,dc ,nc );
174+ newD = div2DCurv(k ,X ,Y ,dc ,nc );
175+ newL = newD * newG ;
176+
177+ % Boundary Conditions
178+ u = ue(X ,Y );
179+
180+ l = u(: ,1 ); r = u(: ,end );
181+ b = u(1 ,: )' ; t = u(end ,: )' ;
182+ v = {l(2 : end - 1 );r(2 : end - 1 );b ;t };
183+ B = zeros(numCenters(i ),1 );
184+ [curL ,B ] = addScalarBC2D(curL ,B ,k ,m(i ),dx(i ),n(i ),dy(i ),dc ,nc ,v );
185+ [newL ,B ] = addScalarBC2D(newL ,B ,k ,m(i ),dx(i ),n(i ),dy(i ),dc ,nc ,v );
186+
187+ curU = curL \ B ;
188+ newU = newL \ B ;
189+
190+ curU = reshape(curU ,m(i )+2 ,n(i )+2 )' ;
191+ newU = reshape(newU ,m(i )+2 ,n(i )+2 )' ;
192+
193+ % Maximum Absolute Error
194+ errorCur(i ) = max(max(abs(u - curU )));
195+ errorNew(i ) = max(max(abs(u - newU )));
196+
197+ end
198+
199+ % Plot results
200+ h = numCenters .^-0.5 ;
201+ refCur = errorCur(1 ) * (h / h(1 )).^k ;
202+ refNew = errorNew(1 ) * (h / h(1 )).^k ;
203+ figure
204+ hold on
205+ plot(h , errorCur , ' LineWidth' , 2 )
206+ plot(h , errorNew , ' LineWidth' , 2 )
207+ plot(h , refCur , ' LineWidth' , 1.5 , ' Color' , ' k' , ' LineStyle' , ' --' )
208+ plot(h , refNew , ' LineWidth' , 1.5 , ' Color' , ' k' , ' LineStyle' , ' --' )
209+ hold off
210+ xscale log
211+ yscale log
212+ xlim([min(h ) max(h )])
213+ xlabel(' 1 / sqrt(Number of Centers)' )
214+ ylabel(' Maximum Absolute Error' )
215+ legend(' Current Implementation' , ' New Implementation' ," k = " + k + " Reference Line" ,' Location' ,' southeast' )
216+ grid on
217+ title(" Maximum Absolute Error vs 1 / sqrt(Number of Centers)" )
218+ subtitle(" ∆u = 0, 1 < R < 2, 0 < theta < π, k = " + k )
0 commit comments