Skip to content

Commit

Permalink
Fix the SOLVERSTATS nightmare (#10207)
Browse files Browse the repository at this point in the history
- Use struct instead of int array to save solver statistics.
  • Loading branch information
AnHeuermann committed Feb 14, 2023
1 parent c05dfdf commit 56379c0
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 120 deletions.
16 changes: 8 additions & 8 deletions OMCompiler/SimulationRuntime/c/simulation/solver/cvode_solver.c
Expand Up @@ -780,10 +780,10 @@ int cvode_solver_deinitial(CVODE_SOLVER *cvodeData)
* If flag LOG_SOLVER_V is provided even more statistics will be collected.
*
* @param cvode_mem Pointer to CVODE memory block.
* @param solverStatsTmp Pointer to solverStatsTmp of solverInfo.
* @param solverStats Pointer to solverStats of solverInfo.
* @param threadData Thread data for error handling.
*/
void cvode_save_statistics(void *cvode_mem, unsigned int *solverStatsTmp, threadData_t *threadData)
void cvode_save_statistics(void *cvode_mem, SOLVERSTATS *solverStats, threadData_t *threadData)
{
/* Variables */
long int tmp1, tmp2;
Expand All @@ -794,32 +794,32 @@ void cvode_save_statistics(void *cvode_mem, unsigned int *solverStatsTmp, thread
tmp1 = 0;
flag = CVodeGetNumSteps(cvode_mem, &tmp1);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_CV_FLAG, "CVodeGetNumSteps");
solverStatsTmp[0] = tmp1;
solverStats->nStepsTaken = tmp1;

/* Get number of right hand side evaluations */
/* TODO: Is it okay to count number of rhs evaluations instead of residual evaluations? */
tmp1 = 0;
flag = CVodeGetNumRhsEvals(cvode_mem, &tmp1);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_CV_FLAG, "CVodeGetNumRhsEvals");
solverStatsTmp[1] = tmp1;
solverStats->nCallsODE = tmp1;

/* Get number of Jacobian evaluations */
tmp1 = 0;
flag = CVodeGetNumJacEvals(cvode_mem, &tmp1);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_CVLS_FLAG, "CVodeGetNumJacEvals");
solverStatsTmp[2] = tmp1;
solverStats->nCallsJacobian = tmp1;

/* Get number of local error test failures */
tmp1 = 0;
flag = CVodeGetNumErrTestFails(cvode_mem, &tmp1);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_CV_FLAG, "CVodeGetNumErrTestFails");
solverStatsTmp[3] = tmp1;
solverStats->nErrorTestFailures = tmp1;

/* Get number of nonlinear convergence failures */
tmp1 = 0;
flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &tmp1);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_CV_FLAG, "CVodeGetNumNonlinSolvConvFails");
solverStatsTmp[4] = tmp1;
solverStats->nConvergenveTestFailures = tmp1;

/* Get even more statistics */
if (useStream[LOG_SOLVER_V])
Expand Down Expand Up @@ -979,7 +979,7 @@ int cvode_solver_step(DATA *data, threadData_t *threadData, SOLVER_INFO *solverI
}

/* Save statistics */
cvode_save_statistics(cvodeData->cvode_mem, solverInfo->solverStatsTmp, threadData);
cvode_save_statistics(cvodeData->cvode_mem, &solverInfo->solverStatsTmp, threadData);

infoStreamPrint(LOG_SOLVER, 0, "##CVODE## Finished Integrator step.");
/* Measure time */
Expand Down
25 changes: 13 additions & 12 deletions OMCompiler/SimulationRuntime/c/simulation/solver/dassl.c
Expand Up @@ -708,6 +708,14 @@ int dassl_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo)
}


/* save dassl stats */
// TODO: Who thought this is an acceptable way to log stats in iwork? Never heard of structs?
solverInfo->solverStatsTmp.nStepsTaken = dasslData->iwork[10];
solverInfo->solverStatsTmp.nCallsODE = dasslData->iwork[11];
solverInfo->solverStatsTmp.nCallsJacobian = dasslData->iwork[12];
solverInfo->solverStatsTmp.nErrorTestFailures = dasslData->iwork[13];
solverInfo->solverStatsTmp.nConvergenveTestFailures = dasslData->iwork[14];

if(ACTIVE_STREAM(LOG_DASSL))
{
infoStreamPrint(LOG_DASSL, 1, "dassl call statistics: ");
Expand All @@ -718,21 +726,14 @@ int dassl_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo)
infoStreamPrint(LOG_DASSL, 0, "step size used on last successful step: %0.4g", dasslData->rwork[6]);
infoStreamPrint(LOG_DASSL, 0, "the order of the method used on the last step: %d", dasslData->iwork[7]);
infoStreamPrint(LOG_DASSL, 0, "the order of the method to be attempted on the next step: %d", dasslData->iwork[8]);
infoStreamPrint(LOG_DASSL, 0, "number of steps taken so far: %d", (int)dasslData->iwork[10]);
infoStreamPrint(LOG_DASSL, 0, "number of calls of functionODE() : %d", (int)dasslData->iwork[11]);
infoStreamPrint(LOG_DASSL, 0, "number of calculation of jacobian : %d", (int)dasslData->iwork[12]);
infoStreamPrint(LOG_DASSL, 0, "total number of convergence test failures: %d", (int)dasslData->iwork[13]);
infoStreamPrint(LOG_DASSL, 0, "total number of error test failures: %d", (int)dasslData->iwork[14]);
infoStreamPrint(LOG_DASSL, 0, "number of steps taken so far: %d", solverInfo->solverStatsTmp.nStepsTaken);
infoStreamPrint(LOG_DASSL, 0, "number of calls of functionODE() : %d", solverInfo->solverStatsTmp.nCallsODE);
infoStreamPrint(LOG_DASSL, 0, "number of calculation of jacobian : %d", solverInfo->solverStatsTmp.nCallsJacobian);
infoStreamPrint(LOG_DASSL, 0, "total number of convergence test failures: %d", solverInfo->solverStatsTmp.nErrorTestFailures);
infoStreamPrint(LOG_DASSL, 0, "total number of error test failures: %d", solverInfo->solverStatsTmp.nConvergenveTestFailures);
messageClose(LOG_DASSL);
}

/* save dassl stats */
for(ui = 0; ui < numStatistics; ui++)
{
assert(10 + ui < dasslData->liw);
solverInfo->solverStatsTmp[ui] = dasslData->iwork[10 + ui];
}

infoStreamPrint(LOG_DASSL, 0, "Finished DASSL step.");
if (measure_time_flag) rt_accumulate(SIM_TIMER_SOLVER);

Expand Down
14 changes: 5 additions & 9 deletions OMCompiler/SimulationRuntime/c/simulation/solver/gbode_main.c
Expand Up @@ -931,11 +931,7 @@ int gbodef_main(DATA *data, threadData_t *threadData, SOLVER_INFO *solverInfo, d
memcpy(gbfData->yOld, sData->realVars, gbData->nStates * sizeof(double));

/* write statistics to the solverInfo data structure */
solverInfo->solverStatsTmp[0] = gbfData->stats.nStepsTaken;
solverInfo->solverStatsTmp[1] = gbfData->stats.nCallsODE;
solverInfo->solverStatsTmp[2] = gbfData->stats.nCallsJacobian;
solverInfo->solverStatsTmp[3] = gbfData->stats.nErrorTestFailures;
solverInfo->solverStatsTmp[4] = gbfData->stats.nConvergenveTestFailures;
memcpy(&solverInfo->solverStatsTmp, &gbfData->stats, sizeof(SOLVERSTATS));

// log the emitted result
if (ACTIVE_STREAM(LOG_GBODE)){
Expand Down Expand Up @@ -1421,7 +1417,7 @@ int gbode_birate(DATA *data, threadData_t *threadData, SOLVER_INFO *solverInfo)
memcpy(gbData->gbfData->yOld, sData->realVars, nStates * sizeof(double));

/* write statistics to the solverInfo data structure */
setSolverStats(solverInfo->solverStatsTmp, &gbData->stats);
memcpy(&solverInfo->solverStatsTmp, &gbData->stats, sizeof(SOLVERSTATS));

// log the emitted result
if (ACTIVE_STREAM(LOG_GBODE)){
Expand Down Expand Up @@ -1542,7 +1538,7 @@ int gbode_birate(DATA *data, threadData_t *threadData, SOLVER_INFO *solverInfo)
}
/* Write statistics to the solverInfo data structure */
logSolverStats(LOG_SOLVER_V, "gb_singlerate", solverInfo->currentTime, gbData->time, gbData->stepSize, &gbData->stats);
setSolverStats(solverInfo->solverStatsTmp, &gbData->stats);
memcpy(&solverInfo->solverStatsTmp, &gbData->stats, sizeof(SOLVERSTATS));

messageClose(LOG_SOLVER);
return 0;
Expand Down Expand Up @@ -1790,7 +1786,7 @@ int gbode_singlerate(DATA *data, threadData_t *threadData, SOLVER_INFO *solverIn
memcpy(gbData->yOld, sData->realVars, gbData->nStates * sizeof(double));

/* write statistics to the solverInfo data structure */
setSolverStats(solverInfo->solverStatsTmp, &gbData->stats);
memcpy(&solverInfo->solverStatsTmp, &gbData->stats, sizeof(SOLVERSTATS));

// log the emitted result
if (ACTIVE_STREAM(LOG_GBODE)){
Expand Down Expand Up @@ -1909,7 +1905,7 @@ int gbode_singlerate(DATA *data, threadData_t *threadData, SOLVER_INFO *solverIn
}
/* Write statistics to the solverInfo data structure */
logSolverStats(LOG_SOLVER_V, "gb_singlerate", solverInfo->currentTime, gbData->time, gbData->stepSize, &gbData->stats);
setSolverStats(solverInfo->solverStatsTmp, &gbData->stats);
memcpy(&solverInfo->solverStatsTmp, &gbData->stats, sizeof(SOLVERSTATS));

messageClose(LOG_SOLVER);
return 0;
Expand Down
27 changes: 0 additions & 27 deletions OMCompiler/SimulationRuntime/c/simulation/solver/gbode_util.c
Expand Up @@ -727,33 +727,6 @@ void logSolverStats(enum LOG_STREAM stream, const char* name, double timeValue,
}
}

/**
* @brief Set solver stats.
*
* @param solverStats Pointer to solverStats to set.
* @param stats Values to set in solverStats.
*/
void setSolverStats(unsigned int* solverStats, SOLVERSTATS* stats) {
solverStats[0] = stats->nStepsTaken;
solverStats[1] = stats->nCallsODE;
solverStats[2] = stats->nCallsJacobian;
solverStats[3] = stats->nErrorTestFailures;
solverStats[4] = stats->nConvergenveTestFailures;
}

/**
* @brief Set all solver stats to zero.
*
* @param stats Pointer to solver stats.
*/
void resetSolverStats(SOLVERSTATS* stats) {
stats->nStepsTaken = 0;
stats->nCallsODE = 0;
stats->nCallsJacobian = 0;
stats->nErrorTestFailures = 0;
stats->nConvergenveTestFailures = 0;
}

/**
* @brief Info message for GBODE replacement.
*
Expand Down
2 changes: 0 additions & 2 deletions OMCompiler/SimulationRuntime/c/simulation/solver/gbode_util.h
Expand Up @@ -74,8 +74,6 @@ void dumpFastStates_gbf(DATA_GBODE *gbData, double time, int rejectedType);
modelica_boolean checkFastStatesChange(DATA_GBODE* gbData);

void logSolverStats(enum LOG_STREAM stream, const char* name, double timeValue, double integratorTime, double stepSize, SOLVERSTATS* stats);
void setSolverStats(unsigned int* solverStats, SOLVERSTATS* stats);
void resetSolverStats(SOLVERSTATS* stats);

void deprecationWarningGBODE(enum SOLVER_METHOD method);

Expand Down
14 changes: 6 additions & 8 deletions OMCompiler/SimulationRuntime/c/simulation/solver/ida_solver.c
Expand Up @@ -1050,34 +1050,32 @@ int ida_solver_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInf
/* steps */
tmp = 0;
flag = IDAGetNumSteps(idaData->ida_mem, &tmp);
if (flag == IDA_SUCCESS)
{
solverInfo->solverStatsTmp[0] = tmp;
}
checkReturnFlag_SUNDIALS(flag, SUNDIALS_IDA_FLAG, "IDAGetNumSteps");
solverInfo->solverStatsTmp.nStepsTaken = tmp;

/* functionODE evaluations */
tmp = 0;
flag = IDAGetNumResEvals(idaData->ida_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_IDA_FLAG, "IDAGetNumResEvals");
solverInfo->solverStatsTmp[1] = tmp;
solverInfo->solverStatsTmp.nCallsODE = tmp;

/* Jacobians evaluations */
tmp = 0;
flag = IDAGetNumJacEvals(idaData->ida_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_IDA_FLAG, "IDAGetNumJacEvals");
solverInfo->solverStatsTmp[2] = tmp;
solverInfo->solverStatsTmp.nCallsJacobian = tmp;

/* local error test failures */
tmp = 0;
flag = IDAGetNumErrTestFails(idaData->ida_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_IDA_FLAG, "IDAGetNumErrTestFails");
solverInfo->solverStatsTmp[3] = tmp;
solverInfo->solverStatsTmp.nErrorTestFailures = tmp;

/* local error test failures */
tmp = 0;
flag = IDAGetNumNonlinSolvConvFails(idaData->ida_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_IDA_FLAG, "IDAGetNumNonlinSolvConvFails");
solverInfo->solverStatsTmp[4] = tmp;
solverInfo->solverStatsTmp.nConvergenveTestFailures = tmp;

/* get more statistics */
if (useStream[LOG_SOLVER_V])
Expand Down
6 changes: 3 additions & 3 deletions OMCompiler/SimulationRuntime/c/simulation/solver/irksco.c
Expand Up @@ -578,9 +578,9 @@ int irksco_midpoint_rule(DATA* data, threadData_t* threadData, SOLVER_INFO* solv
}

/* write stats */
solverInfo->solverStatsTmp[0] = userdata->stepsDone;
solverInfo->solverStatsTmp[1] = userdata->evalFunctionODE;
solverInfo->solverStatsTmp[2] = userdata->evalJacobians;
solverInfo->solverStatsTmp.nStepsTaken = userdata->stepsDone;
solverInfo->solverStatsTmp.nCallsODE = userdata->evalFunctionODE;
solverInfo->solverStatsTmp.nCallsJacobian = userdata->evalJacobians;

infoStreamPrint(LOG_SOLVER, 0, "Finished irksco step.");

Expand Down
Expand Up @@ -368,10 +368,7 @@ static void saveIntegratorStats(SOLVER_INFO* solverInfo)
int ui;
if (!(omc_flag[FLAG_NO_RESTART] && solverInfo->solverMethod==S_DASSL) && solverInfo->didEventStep)
{
for(ui=0; ui<numStatistics; ui++)
{
solverInfo->solverStats[ui] += solverInfo->solverStatsTmp[ui];
}
addSolverStats(&solverInfo->solverStats, &solverInfo->solverStatsTmp);
}
}

Expand Down
8 changes: 4 additions & 4 deletions OMCompiler/SimulationRuntime/c/simulation/solver/radau.c
Expand Up @@ -525,22 +525,22 @@ int kinsolOde(SOLVER_INFO* solverInfo) /* TODO: Unify this function with nlsKin

/* Update statistics */
/* TODO: Statistics are incomplete: If you retry you need to count that as well */
solverInfo->solverStatsTmp[0] += 1; /* Number of steps */
solverInfo->solverStatsTmp.nStepsTaken += 1; /* Number of steps */

tmp = 0;
flag = KINGetNumFuncEvals(kData->kin_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_KIN_FLAG, "KINGetNumFuncEvals");
solverInfo->solverStatsTmp[1] += tmp; /* functionODE evaluations */
solverInfo->solverStatsTmp.nCallsODE += tmp; /* functionODE evaluations */

tmp = 0;
flag = KINGetNumJacEvals(kData->kin_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_KIN_FLAG, "KINGetNumJacEvals");
solverInfo->solverStatsTmp[2] += tmp; /* Jacobians evaluations */
solverInfo->solverStatsTmp.nCallsJacobian += tmp; /* Jacobians evaluations */

tmp = 0;
flag = KINGetNumBetaCondFails(kData->kin_mem, &tmp);
checkReturnFlag_SUNDIALS(flag, SUNDIALS_KIN_FLAG, "KINSpilsGetNumJtimesEvals");
solverInfo->solverStatsTmp[4] += tmp; /* beta-condition failures evaluations */
solverInfo->solverStatsTmp.nErrorTestFailures += tmp; /* beta-condition failures evaluations */

if (solvedSuccessfully != 0) {
infoStreamPrint(LOG_SOLVER, 0, "##IMPRK## Integration step finished unsuccessful.");
Expand Down

0 comments on commit 56379c0

Please sign in to comment.