15
15
import unittest
16
16
17
17
18
- def errors (pts , function , method_options ):
18
+ def errors (pts , function , method_options , bcs = None ):
19
19
20
20
domain = "test"
21
21
x = pybamm .SpatialVariable ("x" , domain = domain )
@@ -33,6 +33,12 @@ def errors(pts, function, method_options):
33
33
left_extrap = pybamm .BoundaryValue (var , "left" )
34
34
right_extrap = pybamm .BoundaryValue (var , "right" )
35
35
36
+ if bcs :
37
+ model = pybamm .BaseBatteryModel ()
38
+ bc_dict = {var : bcs }
39
+ model .boundary_conditions = bc_dict
40
+ disc .bcs = disc .process_boundary_conditions (model )
41
+
36
42
submesh = mesh ["test" ]
37
43
y , l_true , r_true = function (submesh [0 ].nodes )
38
44
@@ -46,13 +52,13 @@ def errors(pts, function, method_options):
46
52
return l_error , r_error
47
53
48
54
49
- def get_errors (function , method_options , pts ):
55
+ def get_errors (function , method_options , pts , bcs = None ):
50
56
51
57
l_errors = np .zeros (pts .shape )
52
58
r_errors = np .zeros (pts .shape )
53
59
54
60
for i , pt in enumerate (pts ):
55
- l_errors [i ], r_errors [i ] = errors (pt , function , method_options )
61
+ l_errors [i ], r_errors [i ] = errors (pt , function , method_options , bcs )
56
62
57
63
return l_errors , r_errors
58
64
@@ -126,9 +132,116 @@ def x_cubed(x):
126
132
np .testing .assert_array_almost_equal (l_quad_rates , 3 )
127
133
np .testing .assert_array_almost_equal (r_quad_rates , 3 , decimal = 3 )
128
134
129
- def test_extrapolation_with_bcs (self ):
135
+ def test_extrapolation_with_bcs_right_neumann (self ):
136
+ # simple particle with a flux bc
137
+
138
+ pts = 10 ** np .arange (1 , 6 , 1 )
139
+ dx = 1 / pts
140
+
141
+ left_val = 1
142
+ right_flux = 2
143
+
144
+ def x_cubed (x ):
145
+ n = 3
146
+ f_x = x ** n
147
+ f_l = 0
148
+ fp_r = n
149
+ y = f_x + (right_flux - fp_r ) * x + (left_val - f_l )
150
+
151
+ true_left = left_val
152
+ true_right = 1 + (right_flux - fp_r ) + (left_val - f_l )
153
+
154
+ return y , true_left , true_right
155
+
156
+ bcs = {"left" : (left_val , "Dirichlet" ), "right" : (right_flux , "Neumann" )}
157
+
158
+ linear = {"extrapolation" : {"order" : "linear" , "use bcs" : True }}
159
+ quad = {"extrapolation" : {"order" : "quadratic" , "use bcs" : True }}
160
+ l_errors_lin_no_bc , r_errors_lin_no_bc = get_errors (x_cubed , linear , pts ,)
161
+ l_errors_quad_no_bc , r_errors_quad_no_bc = get_errors (x_cubed , quad , pts ,)
162
+
163
+ l_errors_lin_with_bc , r_errors_lin_with_bc = get_errors (
164
+ x_cubed , linear , pts , bcs
165
+ )
166
+ l_errors_quad_with_bc , r_errors_quad_with_bc = get_errors (
167
+ x_cubed , quad , pts , bcs
168
+ )
169
+
170
+ # test that with bc is better than without
171
+
172
+ np .testing .assert_array_less (l_errors_lin_with_bc , l_errors_lin_no_bc )
173
+ np .testing .assert_array_less (r_errors_lin_with_bc , r_errors_lin_no_bc )
174
+ np .testing .assert_array_less (l_errors_quad_with_bc , l_errors_quad_no_bc )
175
+ np .testing .assert_array_less (r_errors_quad_with_bc , r_errors_quad_no_bc )
176
+
177
+ # note that with bcs we now obtain the left Dirichlet condition exactly
178
+
179
+ r_lin_rates_bc = np .log (
180
+ r_errors_lin_with_bc [:- 1 ] / r_errors_lin_with_bc [1 :]
181
+ ) / np .log (dx [:- 1 ] / dx [1 :])
182
+ r_quad_rates_bc = np .log (
183
+ r_errors_quad_with_bc [:- 1 ] / r_errors_quad_with_bc [1 :]
184
+ ) / np .log (dx [:- 1 ] / dx [1 :])
185
+
186
+ # check convergence is about the correct order
187
+ np .testing .assert_array_almost_equal (r_lin_rates_bc , 2 , decimal = 2 )
188
+ np .testing .assert_array_almost_equal (r_quad_rates_bc , 3 , decimal = 1 )
189
+
190
+ def test_extrapolation_with_bcs_left_neumann (self ):
130
191
# simple particle with a flux bc
131
192
193
+ pts = 10 ** np .arange (1 , 5 , 1 )
194
+ dx = 1 / pts
195
+
196
+ left_flux = 2
197
+ right_val = 1
198
+
199
+ def x_cubed (x ):
200
+ n = 3
201
+ f_x = x ** n
202
+ fp_l = 0
203
+ f_r = 1
204
+ y = f_x + (left_flux - fp_l ) * x + (right_val - f_r - left_flux + fp_l )
205
+
206
+ true_left = right_val - f_r - left_flux + fp_l
207
+ true_right = right_val
208
+
209
+ return y , true_left , true_right
210
+
211
+ bcs = {"left" : (left_flux , "Neumann" ), "right" : (right_val , "Dirichlet" )}
212
+
213
+ linear = {"extrapolation" : {"order" : "linear" , "use bcs" : True }}
214
+ quad = {"extrapolation" : {"order" : "quadratic" , "use bcs" : True }}
215
+ l_errors_lin_no_bc , r_errors_lin_no_bc = get_errors (x_cubed , linear , pts ,)
216
+ l_errors_quad_no_bc , r_errors_quad_no_bc = get_errors (x_cubed , quad , pts ,)
217
+
218
+ l_errors_lin_with_bc , r_errors_lin_with_bc = get_errors (
219
+ x_cubed , linear , pts , bcs
220
+ )
221
+ l_errors_quad_with_bc , r_errors_quad_with_bc = get_errors (
222
+ x_cubed , quad , pts , bcs
223
+ )
224
+
225
+ # test that with bc is better than without
226
+
227
+ np .testing .assert_array_less (l_errors_lin_with_bc , l_errors_lin_no_bc )
228
+ np .testing .assert_array_less (r_errors_lin_with_bc , r_errors_lin_no_bc )
229
+ np .testing .assert_array_less (l_errors_quad_with_bc , l_errors_quad_no_bc )
230
+ np .testing .assert_array_less (r_errors_quad_with_bc , r_errors_quad_no_bc )
231
+
232
+ # note that with bcs we now obtain the right Dirichlet condition exactly
233
+
234
+ l_lin_rates_bc = np .log (
235
+ l_errors_lin_with_bc [:- 1 ] / l_errors_lin_with_bc [1 :]
236
+ ) / np .log (dx [:- 1 ] / dx [1 :])
237
+ l_quad_rates_bc = np .log (
238
+ l_errors_quad_with_bc [:- 1 ] / l_errors_quad_with_bc [1 :]
239
+ ) / np .log (dx [:- 1 ] / dx [1 :])
240
+
241
+ # check convergence is about the correct order
242
+ np .testing .assert_array_less (2 , l_lin_rates_bc )
243
+ np .testing .assert_array_almost_equal (l_quad_rates_bc , 3 , decimal = 1 )
244
+
132
245
133
246
if __name__ == "__main__" :
134
247
print ("Add -v for more debug output" )
0 commit comments