Skip to content

Commit 21d9b20

Browse files
committed
Add configurations, for alt settings btwn solver modes
1 parent 5d015ee commit 21d9b20

File tree

3 files changed

+54
-42
lines changed

3 files changed

+54
-42
lines changed

include/cantera/numerics/Newton.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
namespace Cantera
1313
{
1414

15+
struct Configuration {
16+
vector_fp rtol;
17+
vector_fp atol;
18+
double convtol;
19+
double dt;
20+
size_t jac_maxage;
21+
double jac_rtol;
22+
double jac_atol;
23+
};
24+
1525
/**
1626
* A Newton solver.
1727
*/
@@ -36,7 +46,7 @@ class Newton
3646

3747
int hybridSolve();
3848

39-
int solve(double* x, double dt=0);
49+
int solve(double* x);
4050

4151
//TODO: implement get methods
4252
//nice implementation for steady vs transient below
@@ -69,20 +79,13 @@ class Newton
6979
//! number of variables
7080
size_t m_nv;
7181

72-
//! solution converged if [weightedNorm(sol, step) < m_convergenceThreshold]
73-
doublereal m_converge_tol;
74-
7582
DenseMatrix m_jacobian, m_jacFactored;
76-
size_t m_jacAge, m_jacMaxAge;
77-
doublereal m_jacRtol, m_jacAtol;
78-
83+
size_t m_jacAge;
7984

8085
//! work arrays of size #m_nv used in solve().
8186
vector_fp m_x, m_x1, m_stp, m_stp1;
8287

8388
vector_fp m_upper_bounds, m_lower_bounds;
84-
vector_fp m_rtol_ss, m_rtol_ts;
85-
vector_fp m_atol_ss, m_atol_ts;
8689

8790
vector_fp m_xlast, m_xsave;
8891

@@ -91,6 +94,10 @@ class Newton
9194

9295
//! current timestep reciprocal
9396
doublereal m_rdt = 0;
97+
98+
Configuration m_directsolve_config;
99+
Configuration m_timestep_config;
100+
Configuration* m_config;
94101
};
95102

96103
// //! Returns the weighted Root Mean Square Deviation given a vector of residuals and

src/numerics/Newton.cpp

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,30 @@ Newton::Newton(FuncEval& func) {
2424
m_stp1.resize(m_nv);
2525
m_upper_bounds.resize(m_nv, 0.0);
2626
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+
3146
m_xlast.resize(m_nv);
3247
m_xsave.resize(m_nv);
3348

34-
m_converge_tol = 1.0e-14;
35-
m_rdt = 0;
36-
3749
m_jacobian = DenseMatrix(m_nv, m_nv);
3850
m_jacAge = npos;
39-
m_jacMaxAge = 5;
40-
m_jacRtol = 1.0e-15;
41-
m_jacAtol = sqrt(std::numeric_limits<double>::epsilon());
4251
}
4352

4453
void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
@@ -53,9 +62,9 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
5362
// calculate the perturbation amount, preserving the sign of x[n]
5463
double dx;
5564
if (xsave >= 0) {
56-
dx = xsave*m_jacRtol + m_jacAtol;
65+
dx = xsave*m_config->jac_rtol + m_config->jac_atol;
5766
} else {
58-
dx = xsave*m_jacRtol - m_jacAtol;
67+
dx = xsave*m_config->jac_rtol - m_config->jac_atol;
5968
}
6069

6170
// perturb the solution vector
@@ -74,6 +83,13 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
7483
x[n] = xsave;
7584
}
7685

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+
7793
// for constant-valued components: 1 in diagonal position, all 0's in row and column
7894
for (size_t i : m_constantComponents) {
7995
for (size_t j = 0; j < m_nv; j++) {
@@ -83,13 +99,6 @@ void Newton::evalJacobian(doublereal* x, doublereal* xdot) {
8399
m_jacobian.value(i,i) = 1;
84100
}
85101

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-
93102
// factor and save jacobian, will be reused for faster step computation
94103
m_jacFactored = m_jacobian;
95104
Cantera::factor(m_jacFactored);
@@ -100,7 +109,7 @@ doublereal Newton::weightedNorm(const doublereal* x, const doublereal* step) con
100109
{
101110
double square = 0.0;
102111
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);
104113
}
105114
return sqrt(square/m_nv);
106115
}
@@ -139,13 +148,15 @@ int Newton::hybridSolve() {
139148

140149
for(int i = 0; i < MAX; i++) {
141150
newtonsolves++;
151+
m_config = &m_directsolve_config;
142152
if(solve(m_x.data()) > 0) {
143153
writelog("\nConverged in {} newton solves, {} timesteps.", newtonsolves, timesteps);
144154
return 1;
145155
}
156+
m_config = &m_timestep_config;
146157
copy(m_xsave.begin(), m_xsave.end(), m_x.begin());
147158
for(int j = 0; j < MAX; j++) {
148-
if (solve(m_x.data(), 1.0e-5) < 0) {
159+
if (solve(m_x.data()) < 0) {
149160
writelog("\nTimestep failure after {} newton solves, {} timesteps.", newtonsolves, timesteps);
150161
return -1;
151162
}
@@ -161,22 +172,21 @@ int Newton::hybridSolve() {
161172
// for time integration, input parameter `dt` != 0
162173
// call without `dt`for direct nonlinear solution
163174
// solution state available in *x* on return
164-
int Newton::solve(double* x, double dt)
175+
int Newton::solve(double* x)
165176
{
166177
copy(&x[0], &x[m_nv], m_x.begin());
178+
m_jacAge = npos;
167179

168-
if (dt) {
180+
if (m_config->dt) {
169181
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;
172183
} else {
173184
m_rdt = 0;
174185
}
175186

176187
while (true) {
177-
178188
// Check whether the Jacobian should be re-evaluated.
179-
if (m_jacAge > m_jacMaxAge) {
189+
if (m_jacAge > m_config->jac_maxage) {
180190
evalJacobian(&m_x[0], &m_stp[0]);
181191
m_jacAge = 0;
182192
}
@@ -224,7 +234,7 @@ int Newton::solve(double* x, double dt)
224234
double nextstep_rms = weightedNorm(&m_x1[0], &m_stp1[0]);
225235

226236
// converged solution criteria
227-
if (nextstep_rms < m_converge_tol) {
237+
if (nextstep_rms < m_config->convtol) {
228238
copy(m_x1.begin(), m_x1.end(), &x[0]);
229239
return 1;
230240
}

src/zeroD/ReactorNet.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,6 @@ double ReactorNet::solveSteady()
425425

426426
m_newt->setConstants({1});
427427
// m_newt->setConstants({0,1,2,11,12});
428-
// m_newt->setConstant(0, true);
429-
// m_newt->setConstant(1, true);
430-
// m_newt->setConstant(2, true);
431-
// m_newt->setConstant(11, true);
432-
// m_newt->setConstant(12, true);
433428

434429
return m_newt->hybridSolve();
435430
}

0 commit comments

Comments
 (0)