Skip to content

Commit ef17c1b

Browse files
Improve initial guesses for GBODE (#14050)
Also check for NaN in xloc and generated calls Co-authored-by: bernhardbachmann <bernhardbachmann@users.noreply.github.com>
1 parent 7c720ed commit ef17c1b

File tree

4 files changed

+66
-10
lines changed

4 files changed

+66
-10
lines changed

OMCompiler/SimulationRuntime/c/simulation/solver/gbode_nls.c

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -502,17 +502,26 @@ NLS_SOLVER_STATUS solveNLS_gb(DATA *data, threadData_t *threadData, NONLINEAR_SY
502502
infoStreamPrint(OMC_LOG_GBODE_NLS, 0, "GBODE: Solution of NLS failedat time %g. Try with updated Jacobian.", gbData->time);
503503
set_kinsol_parameters(kin_mem, newtonMaxSteps, SUNFALSE, 1, newtonTol);
504504
solved = solveNLS(data, threadData, nlsData);
505-
if (!solved) {
506-
infoStreamPrint(OMC_LOG_STDOUT, 0, "GBODE: Solution of NLS failed at time %g, Try with less accuracy.", gbData->time);
507-
set_kinsol_parameters(kin_mem, newtonMaxSteps, SUNFALSE, 1, 10*newtonTol);
508-
solved = solveNLS(data, threadData, nlsData);
509-
}
505+
}
506+
if (!solved) {
507+
infoStreamPrint(OMC_LOG_GBODE_NLS, 0, "GBODE: Solution of NLS failed at time %g, Try with old start value.", gbData->time);
508+
memcpy(nlsData->nlsx, nlsData->nlsxOld, nlsData->size*sizeof(modelica_real));
509+
set_kinsol_parameters(kin_mem, newtonMaxSteps, SUNFALSE, 1, newtonTol);
510+
solved = solveNLS(data, threadData, nlsData);
511+
}
512+
if (!solved) {
513+
infoStreamPrint(OMC_LOG_STDOUT, 0, "GBODE: Solution of NLS failed at time %g, Try with less accuracy.", gbData->time);
514+
set_kinsol_parameters(kin_mem, newtonMaxSteps, SUNFALSE, 1, 10*newtonTol);
515+
solved = solveNLS(data, threadData, nlsData);
510516
}
511517
if (OMC_ACTIVE_STREAM(OMC_LOG_GBODE_NLS)) get_kinsol_statistics(kin_mem);
512518
} else {
513519
solved = solveNLS(data, threadData, nlsData);
514520
}
515521

522+
if (solved)
523+
infoStreamPrint(OMC_LOG_GBODE_NLS_V, 0, "GBODE: NLS solved.");
524+
516525
if (OMC_ACTIVE_STREAM(OMC_LOG_GBODE_NLS)) {
517526
cpu_time_used = rt_ext_tp_tock(&clock);
518527
infoStreamPrint(OMC_LOG_GBODE_NLS, 0, "Time needed for solving the NLS: %20.16g", cpu_time_used);
@@ -551,9 +560,13 @@ void residual_MS(RESIDUAL_USERDATA* userData, const double *xloc, double *res, c
551560
const int nStages = gbData->tableau->nStages;
552561

553562
// Set states
563+
for (i = 0; i < nStates; i++)
564+
assertStreamPrint(threadData, !isnan(xloc[i]), "residual_MS: xloc is NAN");
554565
memcpy(sData->realVars, xloc, nStates*sizeof(modelica_real));
555566
// Evaluate right hand side of ODE
556567
gbode_fODE(data, threadData, &(gbData->stats.nCallsODE));
568+
for (i = 0; i < nStates; i++)
569+
assertStreamPrint(threadData, !isnan(fODE[i]), "residual_MS: fODE is NAN");
557570

558571
// Evaluate residuals
559572
for (i = 0; i < nStates; i++) {
@@ -596,6 +609,7 @@ void residual_MS_MR(RESIDUAL_USERDATA* userData, const double *xloc, double *res
596609
// Set fast states
597610
// ph: are slow states interpolated and set correctly?
598611
for (ii = 0; ii < nFastStates; ii++) {
612+
assertStreamPrint(threadData, !isnan(xloc[ii]), "residual_MS_MR: xloc is NAN");
599613
i = gbfData->fastStatesIdx[ii];
600614
sData->realVars[i] = xloc[ii];
601615
}
@@ -605,9 +619,10 @@ void residual_MS_MR(RESIDUAL_USERDATA* userData, const double *xloc, double *res
605619
// Evaluate residuals
606620
for (ii = 0; ii < nFastStates; ii++) {
607621
i = gbfData->fastStatesIdx[ii];
622+
assertStreamPrint(threadData, !isnan(fODE[i]), "residual_MS_MR: fODE is NAN");
608623
res[ii] = gbfData->res_const[i]
609624
- xloc[ii] * gbfData->tableau->c[nStages-1]
610-
+ fODE[ i] * gbfData->tableau->b[nStages-1] * gbfData->stepSize;
625+
+ fODE[i] * gbfData->tableau->b[nStages-1] * gbfData->stepSize;
611626
}
612627
}
613628

@@ -639,15 +654,19 @@ void residual_DIRK(RESIDUAL_USERDATA* userData, const double *xloc, double *res,
639654
const int nStates = data->modelData->nStates;
640655
const int nStages = gbData->tableau->nStages;
641656
const int stage_ = gbData->act_stage;
657+
const modelica_real fac = gbData->stepSize * gbData->tableau->A[stage_ * nStages + stage_];
642658

643659
// Set states
660+
for (i = 0; i < nStates; i++)
661+
assertStreamPrint(threadData, !isnan(xloc[i]), "residual_DIRK: xloc is NAN");
644662
memcpy(sData->realVars, xloc, nStates*sizeof(double));
645663
// Evaluate right hand side of ODE
646664
gbode_fODE(data, threadData, &(gbData->stats.nCallsODE));
647665

648666
// Evaluate residuals
649667
for (i = 0; i < nStates; i++) {
650-
res[i] = gbData->res_const[i] - xloc[i] + gbData->stepSize * gbData->tableau->A[stage_ * nStages + stage_] * fODE[i];
668+
assertStreamPrint(threadData, !isnan(fODE[i]), "residual_DIRK: fODE is NAN");
669+
res[i] = gbData->res_const[i] - xloc[i] + fac * fODE[i];
651670
}
652671

653672
if (OMC_ACTIVE_STREAM(OMC_LOG_GBODE_NLS)) {
@@ -694,6 +713,7 @@ void residual_DIRK_MR(RESIDUAL_USERDATA* userData, const double *xloc, double *r
694713
// Set fast states
695714
// ph: are slow states interpolated and set correctly?
696715
for (ii = 0; ii < nFastStates; ii++) {
716+
assertStreamPrint(threadData, !isnan(xloc[ii]), "residual_DIRK_MR: xloc is NAN");
697717
i = gbfData->fastStatesIdx[ii];
698718
sData->realVars[i] = xloc[ii];
699719
}
@@ -703,6 +723,7 @@ void residual_DIRK_MR(RESIDUAL_USERDATA* userData, const double *xloc, double *r
703723
// Evaluate residuals
704724
for (ii = 0; ii < nFastStates; ii++) {
705725
i = gbfData->fastStatesIdx[ii];
726+
assertStreamPrint(threadData, !isnan(fODE[i]), "residual_DIRK_MR: fODE is NAN");
706727
res[ii] = gbfData->res_const[i] - xloc[ii] + fac * fODE[i];
707728
}
708729
}
@@ -735,13 +756,18 @@ void residual_IRK(RESIDUAL_USERDATA* userData, const double *xloc, double *res,
735756
const int nStates = data->modelData->nStates;
736757
int stage, stage_;
737758

759+
for (i = 0; i < nStages*nStates; i++)
760+
assertStreamPrint(threadData, !isnan(xloc[i]), "residual_IRK: xloc is NAN");
761+
738762
// Update the derivatives for current estimate of the states
739763
for (stage_ = 0; stage_ < nStages; stage_++) {
740764
/* Evaluate ODE for each stage_ */
741765
if (!gbData->tableau->isKLeftAvailable || stage_ > 0) {
742766
sData->timeValue = gbData->time + gbData->tableau->c[stage_] * gbData->stepSize;
743767
memcpy(sData->realVars, xloc + stage_ * nStates, nStates*sizeof(double));
744768
gbode_fODE(data, threadData, &(gbData->stats.nCallsODE));
769+
for (i = 0; i < nStates; i++)
770+
assertStreamPrint(threadData, !isnan(fODE[i]), "residual_IRK: fODE is NAN");
745771
memcpy(gbData->k + stage_ * nStates, fODE, nStates*sizeof(double));
746772
} else {
747773
// memcpy(sData->realVars, gbData->yLeft, nStates*sizeof(double));
@@ -801,6 +827,7 @@ int jacobian_SR_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian,
801827
}
802828

803829
for (i = 0; i < jacobian->sizeCols; i++) {
830+
assertStreamPrint(threadData, !isnan(jacobian_ODE->resultVars[i]), "jacobian_SR_column: jacobian_ODE is NAN");
804831
jacobian->resultVars[i] = fac * jacobian_ODE->resultVars[i] - jacobian->seedVars[i];
805832
}
806833

@@ -854,6 +881,7 @@ int jacobian_MR_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian,
854881

855882
for (ii = 0; ii < nFastStates; ii++) {
856883
i = gbData->fastStatesIdx[ii];
884+
assertStreamPrint(threadData, !isnan(jacobian_ODE->resultVars[i]), "jacobian_MR_column: jacobian_ODE is NAN");
857885
jacobian->resultVars[ii] = fac * jacobian_ODE->resultVars[i] - jacobian->seedVars[ii];
858886
}
859887

@@ -909,6 +937,8 @@ int jacobian_IRK_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian
909937

910938
// call jacobian_ODE with the mapped seedVars
911939
data->callback->functionJacA_column(data, threadData, jacobian_ODE, NULL);
940+
for (i = 0; i < nStates; i++)
941+
assertStreamPrint(threadData, !isnan(jacobian_ODE->resultVars[i]), "jacobian_SR_column: jacobian_ODE is NAN");
912942

913943
/* Update resultVars array for corresponding jacobian->seedVars*/
914944
for (stage = 0; stage < nStages; stage++) {

OMCompiler/SimulationRuntime/c/simulation/solver/gbode_step.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,14 @@ int expl_diag_impl_RK(DATA* data, threadData_t* threadData, SOLVER_INFO* solverI
292292

293293
// Set start vector
294294
memcpy(nlsData->nlsx, gbData->yOld, nStates*sizeof(modelica_real));
295-
memcpy(nlsData->nlsxOld, gbData->yOld, nStates*sizeof(modelica_real));
296-
extrapolation_gb(gbData, nlsData->nlsxExtrapolation, gbData->time + gbData->tableau->c[stage_] * gbData->stepSize);
295+
addSmultVec_gb(nlsData->nlsxOld, gbData->yv, gbData->kv, gbData->time + gbData->tableau->c[stage_] * gbData->stepSize - gbData->tv[0], nStates);
296+
297+
if (stage>1) {
298+
extrapolation_hermite_gb(nlsData->nlsxExtrapolation, gbData->nStates, gbData->time + gbData->tableau->c[stage_-2] * gbData->stepSize, gbData->x + (stage_-2) * nStates, gbData->k + (stage_-2) * nStates,
299+
gbData->time + gbData->tableau->c[stage_-1] * gbData->stepSize, gbData->x + (stage_-1) * nStates, gbData->k + (stage_-1) * nStates, gbData->time + gbData->tableau->c[stage_] * gbData->stepSize);
300+
} else {
301+
extrapolation_gb(gbData, nlsData->nlsxExtrapolation, gbData->time + gbData->tableau->c[stage_] * gbData->stepSize);
302+
}
297303

298304
solved = solveNLS_gb(data, threadData, nlsData, gbData);
299305

@@ -315,6 +321,7 @@ int expl_diag_impl_RK(DATA* data, threadData_t* threadData, SOLVER_INFO* solverI
315321
// copy last calculation of fODE, which should coincide with k[i], here, it yields stage == stage_
316322
memcpy(gbData->k + stage_ * nStates, fODE, nStates*sizeof(double));
317323
}
324+
infoStreamPrint(OMC_LOG_GBODE_NLS_V, 0, "GBODE: all stages done.");
318325

319326
// Apply RK-scheme for determining the approximations at (gbData->time + gbData->stepSize)
320327
// y = yold+h*sum(b[stage_] * k[stage_], stage_=1..nStages);

OMCompiler/SimulationRuntime/c/simulation/solver/gbode_util.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void addSmultVec_gbf(double* a, double* b, double *c, double s, int nIdx, int* i
6262
}
6363

6464
/**
65-
* @brief Scalar multiplication and vector addition a = b + s*c for selected indices.
65+
* @brief Scalar multiplication and vector addition a = b + s*c.
6666
*
6767
* Determines the scalar multiplication of an vector and adds the result
6868
* to another vector.
@@ -386,6 +386,24 @@ void extrapolation_gbf(DATA_GBODE* gbData, double* nlsxExtrapolation, double tim
386386
}
387387
}
388388

389+
/**
390+
* @brief Extrapolation for all states.
391+
*
392+
* Using interpolation method specified in gbData->interpolation.
393+
*
394+
* @param gbData Generic ODE solver data.
395+
* @param nlsxExtrapolation On output contains function values at extrapolation point time.
396+
* @param time Extrapolation time.
397+
*/
398+
void extrapolation_hermite_gb(double* nlsxExtrapolation, int nStates, double t0, double *x0, double* k0, double t1, double *x1, double* k1, double time)
399+
{
400+
gb_interpolation(GB_INTERPOL_HERMITE,
401+
t0, x0, k0,
402+
t1, x1, k1,
403+
time, nlsxExtrapolation,
404+
nStates, NULL, nStates, NULL, NULL, NULL);
405+
}
406+
389407
/**
390408
* @brief Extrapolation for all states.
391409
*

OMCompiler/SimulationRuntime/c/simulation/solver/gbode_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void gb_interpolation(enum GB_INTERPOL_METHOD interpolMethod, double ta, double*
5555
int nIdx, int* idx, int nStates, BUTCHER_TABLEAU* tableau, double* x, double *k);
5656
double error_interpolation_gb(DATA_GBODE* gbData, int nIdx, int* idx, double tol);
5757
void extrapolation_gb(DATA_GBODE* gbData, double* nlsxExtrapolation, double time);
58+
void extrapolation_hermite_gb(double* nlsxExtrapolation, int nStates, double t0, double *x0, double* k0, double t1, double *x1, double* k1, double time);
5859
void extrapolation_gbf(DATA_GBODE* gbData, double* nlsxExtrapolation, double time);
5960

6061
// Copy only specific values referenced by an index vector

0 commit comments

Comments
 (0)