Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 863c7b7

Browse files
rfrankeOpenModelica-Hudson
authored andcommitted
Let Newton solver catch errors from analytic Jacobian
1 parent 3821a19 commit 863c7b7

File tree

2 files changed

+22
-17
lines changed

2 files changed

+22
-17
lines changed

SimulationRuntime/cpp/Include/Solver/Newton/Newton.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ class Newton : public IAlgLoopSolver
5454
void calcFunction(const double* y, double* residual);
5555

5656
/// Encapsulation of determination of Jacobian
57-
void calcJacobian(bool getSymbolicJac);
58-
57+
void calcJacobian(double *jac, double *fNominal);
5958

6059
// Member variables
6160
//---------------------------------------------------------------

SimulationRuntime/cpp/Solver/Newton/Newton.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,7 @@ void Newton::solve()
213213
LOG_VEC(_algLoop, "y" + to_string(totSteps), _y, _lc, LL_DEBUG);
214214
LOG_VEC(_algLoop, "f" + to_string(totSteps), _f, _lc, LL_DEBUG);
215215

216-
calcJacobian(true);
217-
LOG_VEC(_algLoop, "fNominal" + to_string(totSteps), _fNominal, _lc, LL_DEBUG);
216+
calcJacobian(_jac, _fNominal);
218217

219218
// check stopping criterion
220219
_iterationStatus = DONE;
@@ -375,24 +374,30 @@ void Newton::stepCompleted(double time)
375374

376375
}
377376

378-
void Newton::calcJacobian(bool getSymbolicJac)
377+
void Newton::calcJacobian(double *jac, double *fNominal)
379378
{
380-
const double *jac = NULL;
381-
std::fill(_fNominal, _fNominal + _dimSys, _newtonSettings->getAtol());
379+
const double *Adata = NULL;
380+
std::fill(fNominal, fNominal + _dimSys, _newtonSettings->getAtol());
382381
// Use analytic Jacobian if available
383-
if (getSymbolicJac) {
382+
try {
384383
matrix_t A = _algLoop->getSystemMatrix();
385384
if (A.size1() == _dimSys && A.size2() == _dimSys) {
386-
jac = A.data().begin();
387-
std::copy(jac, jac + _dimSys*_dimSys, _jac);
388-
for (int i = 0; i < _dimSys; i++)
389-
for (int j = 0, idx = i; j < _dimSys; j++, idx += _dimSys)
390-
_fNominal[i] = std::max(std::abs(_jac[idx]) * _yNominal[j], _fNominal[i]);
385+
Adata = A.data().begin();
386+
std::copy(Adata, Adata + _dimSys * _dimSys, jac);
387+
for (int j = 0, idx = 0; j < _dimSys; j++)
388+
for (int i = 0; i < _dimSys; i++, idx++)
389+
fNominal[i] = std::max(std::abs(jac[idx]) * _yNominal[j], fNominal[i]);
391390
}
392391
}
392+
catch (ModelicaSimulationError& ex) {
393+
LOGGER_WRITE("Analytic Jacobian failed for eq" +
394+
to_string(_algLoop->getEquationIndex()) + " at time " +
395+
to_string(_algLoop->getSimTime()) + ": " + ex.what(),
396+
_lc, LL_WARNING);
397+
}
393398
// Alternatively apply finite differences
394-
if (jac == NULL) {
395-
for (int j = 0; j < _dimSys; ++j) {
399+
if (Adata == NULL) {
400+
for (int j = 0; j < _dimSys; j++) {
396401
// Reset variables for every column
397402
std::copy(_y, _y + _dimSys, _yHelp);
398403
double stepsize = 100.0 * _newtonSettings->getRtol() * _yNominal[j];
@@ -404,13 +409,14 @@ void Newton::calcJacobian(bool getSymbolicJac)
404409

405410
// Build Jacobian in Fortran format
406411
for (int i = 0, idx = j * _dimSys; i < _dimSys; i++, idx++) {
407-
_jac[idx] = (_fHelp[i] - _f[i]) / stepsize;
408-
_fNominal[i] = std::max(std::abs(_jac[idx]) * _yNominal[j], _fNominal[i]);
412+
jac[idx] = (_fHelp[i] - _f[i]) / stepsize;
413+
fNominal[i] = std::max(std::abs(jac[idx]) * _yNominal[j], fNominal[i]);
409414
}
410415

411416
_yHelp[j] -= stepsize;
412417
}
413418
}
419+
LOG_VEC(_algLoop, "fNominal", fNominal, _lc, LL_DEBUG);
414420
}
415421

416422
void Newton::restoreOldValues()

0 commit comments

Comments
 (0)