@@ -24,21 +24,30 @@ Newton::Newton(FuncEval& func) {
24
24
m_stp1.resize (m_nv);
25
25
m_upper_bounds.resize (m_nv, 0.0 );
26
26
m_lower_bounds.resize (m_nv, 0.0 );
27
- m_rtol_ss.resize (m_nv, 1.0e-4 );
28
- m_atol_ss.resize (m_nv, 1.0e-9 );
29
- // m_rtol_ts.resize(m_nv, 1.0e-4);
30
- // m_atol_ts.resize(m_nv, 1.0e-11);
27
+
28
+ m_directsolve_config.rtol .resize (m_nv, 1.0e-4 );
29
+ m_directsolve_config.atol .resize (m_nv, 1.0e-9 );
30
+ m_directsolve_config.convtol = 1.0e-14 ;
31
+ m_directsolve_config.dt = 0 ;
32
+ m_directsolve_config.jac_maxage = 5 ;
33
+ m_directsolve_config.jac_rtol = 1.0e-15 ;
34
+ m_directsolve_config.jac_atol = sqrt (std::numeric_limits<double >::epsilon ());
35
+
36
+ m_timestep_config.rtol .resize (m_nv, 1.0e-4 );
37
+ m_timestep_config.atol .resize (m_nv, 1.0e-11 );
38
+ m_timestep_config.convtol = 1.0e-14 ;
39
+ m_timestep_config.dt = 1.0e-5 ;
40
+ m_timestep_config.jac_maxage = 5 ;
41
+ m_timestep_config.jac_rtol = 1.0e-15 ;
42
+ m_timestep_config.jac_atol = sqrt (std::numeric_limits<double >::epsilon ());
43
+
44
+ m_config = &m_directsolve_config;
45
+
31
46
m_xlast.resize (m_nv);
32
47
m_xsave.resize (m_nv);
33
48
34
- m_converge_tol = 1.0e-14 ;
35
- m_rdt = 0 ;
36
-
37
49
m_jacobian = DenseMatrix (m_nv, m_nv);
38
50
m_jacAge = npos;
39
- m_jacMaxAge = 5 ;
40
- m_jacRtol = 1.0e-15 ;
41
- m_jacAtol = sqrt (std::numeric_limits<double >::epsilon ());
42
51
}
43
52
44
53
void Newton::evalJacobian (doublereal* x, doublereal* xdot) {
@@ -53,9 +62,9 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
53
62
// calculate the perturbation amount, preserving the sign of x[n]
54
63
double dx;
55
64
if (xsave >= 0 ) {
56
- dx = xsave*m_jacRtol + m_jacAtol ;
65
+ dx = xsave*m_config-> jac_rtol + m_config-> jac_atol ;
57
66
} else {
58
- dx = xsave*m_jacRtol - m_jacAtol ;
67
+ dx = xsave*m_config-> jac_rtol - m_config-> jac_atol ;
59
68
}
60
69
61
70
// perturb the solution vector
@@ -74,6 +83,13 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
74
83
x[n] = xsave;
75
84
}
76
85
86
+ // timestep components
87
+ if (m_rdt > 0 ) {
88
+ for (size_t i = 0 ; i < m_nv; i++) {
89
+ m_jacobian.value (i,i) -= m_rdt;
90
+ }
91
+ }
92
+
77
93
// for constant-valued components: 1 in diagonal position, all 0's in row and column
78
94
for (size_t i : m_constantComponents) {
79
95
for (size_t j = 0 ; j < m_nv; j++) {
@@ -83,13 +99,6 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
83
99
m_jacobian.value (i,i) = 1 ;
84
100
}
85
101
86
- // timestep components
87
- if (m_rdt > 0 ) {
88
- for (size_t i = 0 ; i < m_nv; i++) {
89
- m_jacobian.value (i,i) -= m_rdt;
90
- }
91
- }
92
-
93
102
// factor and save jacobian, will be reused for faster step computation
94
103
m_jacFactored = m_jacobian;
95
104
Cantera::factor (m_jacFactored);
@@ -100,7 +109,7 @@ doublereal Newton::weightedNorm(const doublereal* x, const doublereal* step) con
100
109
{
101
110
double square = 0.0 ;
102
111
for (size_t i = 0 ; i < m_nv; i++) {
103
- square += pow (step[i]/(x[i] + m_atol_ss [i]), 2 );
112
+ square += pow (step[i]/(x[i] + m_config-> atol [i]), 2 );
104
113
}
105
114
return sqrt (square/m_nv);
106
115
}
@@ -139,13 +148,15 @@ int Newton::hybridSolve() {
139
148
140
149
for (int i = 0 ; i < MAX; i++) {
141
150
newtonsolves++;
151
+ m_config = &m_directsolve_config;
142
152
if (solve (m_x.data ()) > 0 ) {
143
153
writelog (" \n Converged in {} newton solves, {} timesteps." , newtonsolves, timesteps);
144
154
return 1 ;
145
155
}
156
+ m_config = &m_timestep_config;
146
157
copy (m_xsave.begin (), m_xsave.end (), m_x.begin ());
147
158
for (int j = 0 ; j < MAX; j++) {
148
- if (solve (m_x.data (), 1.0e-5 ) < 0 ) {
159
+ if (solve (m_x.data ()) < 0 ) {
149
160
writelog (" \n Timestep failure after {} newton solves, {} timesteps." , newtonsolves, timesteps);
150
161
return -1 ;
151
162
}
@@ -161,22 +172,21 @@ int Newton::hybridSolve() {
161
172
// for time integration, input parameter `dt` != 0
162
173
// call without `dt`for direct nonlinear solution
163
174
// solution state available in *x* on return
164
- int Newton::solve (double * x, double dt )
175
+ int Newton::solve (double * x)
165
176
{
166
177
copy (&x[0 ], &x[m_nv], m_x.begin ());
178
+ m_jacAge = npos;
167
179
168
- if (dt) {
180
+ if (m_config-> dt ) {
169
181
copy (m_x.begin (), m_x.end (), m_xlast.begin ());
170
- m_rdt = 1 /dt;
171
- m_jacAge = npos;
182
+ m_rdt = 1 /m_config->dt ;
172
183
} else {
173
184
m_rdt = 0 ;
174
185
}
175
186
176
187
while (true ) {
177
-
178
188
// Check whether the Jacobian should be re-evaluated.
179
- if (m_jacAge > m_jacMaxAge ) {
189
+ if (m_jacAge > m_config-> jac_maxage ) {
180
190
evalJacobian (&m_x[0 ], &m_stp[0 ]);
181
191
m_jacAge = 0 ;
182
192
}
@@ -224,7 +234,7 @@ int Newton::solve(double* x, double dt)
224
234
double nextstep_rms = weightedNorm (&m_x1[0 ], &m_stp1[0 ]);
225
235
226
236
// converged solution criteria
227
- if (nextstep_rms < m_converge_tol ) {
237
+ if (nextstep_rms < m_config-> convtol ) {
228
238
copy (m_x1.begin (), m_x1.end (), &x[0 ]);
229
239
return 1 ;
230
240
}
0 commit comments