-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_solver_spec.m
149 lines (125 loc) · 5.96 KB
/
test_solver_spec.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
classdef test_solver_spec < matlab.unittest.TestCase
% Unit test to ensure the solver satisfies the solver fundamental
% specification or assumption.
properties(TestParameter)
useSubCSD = struct('UseSubCSD', true, 'NoSubCSD', false);
solver = struct('Upwind', @upwind_solver, 'HRFVM', @hrfvm_solver);
end
methods(Test)
function test_growth_touch_boundary(testCase, useSubCSD, solver)
% When the solving steps touch the size grid boundary (right),
% the boundary should not affect the result of the other
% points.
% If this test passes, the boundary of the CSD, or the boundary
% of the subCSD does not affect those channel adjecent to the
% boundary. Therefore, cutting at the effective size should
% only affect the cut channels but does not affect those
% channel smaller than the cut.
props = parameterized_system_properties();
props.pnKp = 0;
props.snKb = 0;
g = size_grid(99, 100);
props.sizeGrids = g;
options = make_options();
options.useSubCSD = useSubCSD;
s = solver(options, props);
nonBoundaryCenter = 50;
nonBoundaryIc = make_states(props.solubility(60), normpdf(g.to_array(), nonBoundaryCenter, 5), props);
boundaryCenter = 90;
boundaryIc = make_states(props.solubility(60), normpdf(g.to_array(), boundaryCenter, 5), props);
in = make_inputs(25);
for tSpan = 25:25:100
nonBoundaryNextState = s.step(nonBoundaryIc, in, tSpan);
boundaryNextState = s.step(boundaryIc, in, tSpan);
testCase.assertEqual( ...
nonBoundaryNextState.csd(nonBoundaryCenter-5:nonBoundaryCenter+5), ...
boundaryNextState.csd(boundaryCenter-5:boundaryCenter+5), ...
'RelTol', 1e-3 ...
);
end
end
function test_dissolution_touch_boundary(testCase, useSubCSD, solver)
% Refer to test_growth_touch_boundary.
props = parameterized_system_properties();
props.pnKp = 0;
props.snKb = 0;
g = size_grid(99, 100);
props.sizeGrids = g;
options = make_options();
options.useSubCSD = useSubCSD;
s = solver(options, props);
nonBoundaryCenter = 50;
nonBoundaryIc = make_states(props.solubility(25), normpdf(g.to_array(), nonBoundaryCenter, 5), props);
boundaryCenter = 10;
boundaryIc = make_states(props.solubility(25), normpdf(g.to_array(), boundaryCenter, 5), props);
in = make_inputs(40);
tSpan = 10;
nonBoundaryNextState = s.step(nonBoundaryIc, in, tSpan);
boundaryNextState = s.step(boundaryIc, in, tSpan);
testCase.assertEqual( ...
nonBoundaryNextState.csd(nonBoundaryCenter-5:nonBoundaryCenter+5), ...
boundaryNextState.csd(boundaryCenter-5:boundaryCenter+5), ...
'RelTol', 1e-3 ...
);
end
function test_growth_only(testCase, useSubCSD, solver)
props = parameterized_system_properties;
props.pnKp = 0;
props.snKb = 0;
options = make_options();
options.useSubCSD = useSubCSD;
s = solver(options, props);
sizeGrid = props.sizeGrids;
g = sizeGrid.to_array();
ic = make_states(props.solubility(60), normpdf(g, 20, 10), props);
in = make_inputs(25);
tSpan = 300;
nextState = s.step(ic, in, tSpan);
% Peak position
[~, I] = max(nextState.csd);
testCase.assertEqual(I, 95, 'AbsTol', 1);
end
function test_dissolution_only(testCase, useSubCSD, solver)
props = parameterized_system_properties;
props.pnKp = 0;
props.snKb = 0;
options = make_options();
options.useSubCSD = useSubCSD;
s = solver(options, props);
sizeGrid = props.sizeGrids;
g = sizeGrid.to_array();
ic = make_states(props.solubility(25), normpdf(g, 50, 10), props);
in = make_inputs(60);
tSpan = 10;
nextState = s.step(ic, in, tSpan);
% Peak position
[~, I] = max(nextState.csd);
testCase.assertEqual(I, 35, 'AbsTol', 1);
end
function test_sub_csd_different_step(testCase, solver)
% This test checks with different time step scales, whether the
% concentration profile (by comparing the endpoints) are the
% same. Practically, it verifies that under the circumstance of
% enabled sub-CSD optimization, whether the problem of leaking
% channel is mitigated so that the result is reproducible at
% different time step scale.
scales = [0.3, 0.1, 0.05, 0.01];
cs = zeros('like', scales);
for i = 1: numel(scales)
props = parameterized_system_properties;
options = make_options();
options.useSubCSD = 0; % should be true
options.timeStepScale = scales(i);
s = solver(options, props);
ic = make_states(props.solubility(60), 0, props);
in = make_inputs(25);
tSpan = 500;
nextState = s.step(ic, in, tSpan);
cs(i) = nextState.conc;
end
stdDev = std(cs);
mu = repmat(mean(cs), size(cs));
testCase.assertEqual(mu, cs, 'AbsTol', 3*stdDev);
end
end
end