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

Commit 5614078

Browse files
Willi BraunOpenModelica-Hudson
authored andcommitted
[C Runtime] added symbolical jacobian support to ida
Belonging to [master]: - #2181 - OpenModelica/OpenModelica-testsuite#847
1 parent de1bcf8 commit 5614078

File tree

3 files changed

+142
-81
lines changed

3 files changed

+142
-81
lines changed

SimulationRuntime/c/simulation/solver/ida_solver.c

Lines changed: 141 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@
7272
#include <idas/idas_spbcgs.h>
7373
#include <idas/idas_sptfqmr.h>
7474

75-
static int callDenseNumJac(long int Neq, double tt, double cj,
75+
static int callDenseJacobian(long int Neq, double tt, double cj,
7676
N_Vector yy, N_Vector yp, N_Vector rr,
7777
DlsMat Jac, void *user_data,
7878
N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
7979

80-
static int jacobianSparseNum(realtype tt, realtype cj,
80+
static int callSparseJacobian(realtype tt, realtype cj,
8181
N_Vector yy, N_Vector yp, N_Vector rr, SlsMat Jac, void *user_data,
8282
N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
8383

@@ -403,7 +403,7 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
403403
}
404404

405405

406-
/* if FLAG_JACOBIAN is set, choose dassl jacobian calculation method */
406+
/* if FLAG_JACOBIAN is set, choose jacobian calculation method */
407407
if (omc_flag[FLAG_JACOBIAN])
408408
{
409409
for(i=1; i< JAC_MAX;i++)
@@ -413,6 +413,11 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
413413
break;
414414
}
415415
}
416+
if(idaData->daeMode && ( idaData->jacobianMethod == COLOREDSYMJAC || idaData->jacobianMethod == SYMJAC ))
417+
{
418+
warningStreamPrint(LOG_STDOUT, 1, "Symbolic Jacobians are currently not supported by DAE Mode. Switch back to numerical Jacobian!");
419+
idaData->jacobianMethod = COLOREDNUMJAC;
420+
}
416421
if(idaData->jacobianMethod == JAC_UNKNOWN)
417422
{
418423
if (ACTIVE_WARNING_STREAM(LOG_SOLVER))
@@ -430,21 +435,13 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
430435
}
431436
else
432437
{
433-
if (idaData->linearSolverMethod == IDA_LS_KLU)
434-
{
435-
idaData->jacobianMethod = KLUSPARSE;
436-
}
437-
else
438-
{
439-
idaData->jacobianMethod = COLOREDNUMJAC;
440-
}
438+
idaData->jacobianMethod = COLOREDNUMJAC;
441439
}
442440

443441
/* selects the calculation method of the jacobian */
444442
/* in daeMode sparse pattern is already initialized in DAEMODE_DATA */
445443
if(!idaData->daeMode && (idaData->jacobianMethod == COLOREDNUMJAC ||
446444
idaData->jacobianMethod == COLOREDSYMJAC ||
447-
idaData->jacobianMethod == KLUSPARSE ||
448445
idaData->jacobianMethod == SYMJAC))
449446
{
450447
if (data->callback->initialAnalyticJacobianA(data, threadData))
@@ -466,6 +463,7 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
466463
{
467464
idaData->NNZ = data->simulationInfo->daeModeData->sparsePattern->numberOfNoneZeros;
468465
flag = IDAKLU(idaData->ida_mem, idaData->N, idaData->NNZ);
466+
idaData->jacobianMethod = COLOREDNUMJAC; /* In DAE mode only numerical matrix is supported */
469467
}
470468
else
471469
{
@@ -479,11 +477,14 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
479477
}
480478

481479
switch (idaData->jacobianMethod){
482-
case KLUSPARSE:
483-
flag = IDASlsSetSparseJacFn(idaData->ida_mem, jacobianSparseNum);
480+
case SYMJAC:
481+
case NUMJAC:
482+
case COLOREDSYMJAC:
483+
case COLOREDNUMJAC:
484+
flag = IDASlsSetSparseJacFn(idaData->ida_mem, callSparseJacobian);
484485
break;
485486
default:
486-
throwStreamPrint(threadData,"For the klu solver jacobian calculation method has to be %s", JACOBIAN_METHOD[KLUSPARSE]);
487+
throwStreamPrint(threadData,"For the klu solver jacobian calculation method has to be %s or %s", JACOBIAN_METHOD[COLOREDSYMJAC], JACOBIAN_METHOD[COLOREDNUMJAC]);
487488
break;
488489
}
489490
}
@@ -492,12 +493,10 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
492493
switch (idaData->jacobianMethod){
493494
case SYMJAC:
494495
case COLOREDSYMJAC:
495-
infoStreamPrint(LOG_STDOUT, 0, "The symbolic jacobian is not implemented, yet! Switch back to internal.");
496-
break;
497496
case COLOREDNUMJAC:
498497
case NUMJAC:
499498
/* set jacobian function */
500-
flag = IDADlsSetDenseJacFn(idaData->ida_mem, callDenseNumJac);
499+
flag = IDADlsSetDenseJacFn(idaData->ida_mem, callDenseJacobian);
501500
break;
502501
case INTERNALNUMJAC:
503502
break;
@@ -1268,7 +1267,7 @@ int rootsFunctionIDA(double time, N_Vector yy, N_Vector yp, double *gout, void*
12681267
* into a dense DlsMat matrix
12691268
*/
12701269
static
1271-
int jacOwnNumColoredIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat Jac, double cj, void *userData)
1270+
int jacColoredNumericalDense(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat Jac, double cj, void *userData)
12721271
{
12731272
TRACE_PUSH
12741273
IDA_SOLVER* idaData = (IDA_SOLVER*)userData;
@@ -1365,69 +1364,60 @@ int jacOwnNumColoredIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat
13651364
}
13661365

13671366
/*
1368-
* function calculates a jacobian matrix by
1369-
* numerical method finite differences without coloring
1370-
* into a dense DlsMat matrix
1367+
* function calculates the Jacobian matrix symbolical
1368+
* with considering also the coloring and pass it in a
1369+
* dense DlsMat matrix.
13711370
*/
13721371
static
1373-
int jacOwnNumIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat Jac, double cj, void *userData)
1372+
int jacColoredSymbolicalDense(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat Jac, double cj, void *userData)
13741373
{
13751374
TRACE_PUSH
13761375
IDA_SOLVER* idaData = (IDA_SOLVER*)userData;
13771376
DATA* data = (DATA*)(((IDA_USERDATA*)idaData->simData)->data);
1377+
threadData_t* threadData = (threadData_t*)(((IDA_USERDATA*)idaData->simData)->threadData);
13781378
void* ida_mem = idaData->ida_mem;
1379+
const int index = data->callback->INDEX_JAC_A;
1380+
unsigned int i,ii,j, nth;
1381+
ANALYTIC_JACOBIAN* jacData = &(data->simulationInfo->analyticJacobians[index]);
1382+
SPARSE_PATTERN* sparsePattern = &(jacData->sparsePattern);
13791383

13801384
/* prepare variables */
13811385
double *states = N_VGetArrayPointer(yy);
13821386
double *yprime = N_VGetArrayPointer(yp);
1383-
double *delta = N_VGetArrayPointer(rr);
1384-
double *newdelta = N_VGetArrayPointer(idaData->newdelta);
1385-
double *errwgt = N_VGetArrayPointer(idaData->errwgt);
1386-
1387-
double ysave, ypsave;
1388-
1389-
double delta_h = numericalDifferentiationDeltaXsolver;
1390-
double delta_hh;
1391-
double delta_hhh;
1392-
double deltaInv;
1393-
long int i,j;
1394-
1395-
double currentStep;
1396-
1397-
/* set values */
1398-
IDAGetCurrentStep(ida_mem, &currentStep);
1399-
if (!idaData->disableScaling){
1400-
IDAGetErrWeights(ida_mem, idaData->errwgt);
1401-
}
14021387

14031388
setContext(data, &tt, CONTEXT_JACOBIAN);
14041389

1405-
for(i = 0; i < idaData->N; i++)
1390+
for(i = 0; i < sparsePattern->maxColors; i++)
14061391
{
1407-
delta_hhh = currentStep * yprime[i];
1408-
delta_hh = delta_h * fmax(fmax(fabs(states[i]),fabs(delta_hhh)),fabs(1./errwgt[i]));
1409-
delta_hh = (delta_hhh >= 0 ? delta_hh : -delta_hh);
1410-
delta_hh = (states[i] + delta_hh) - states[i];
1411-
deltaInv = 1. / delta_hh;
1412-
ysave = states[i];
1413-
states[i] += delta_hh;
1414-
if (idaData->daeMode){
1415-
ypsave = yprime[i];
1416-
yprime[i] += cj * delta_hh;
1392+
for(ii=0; ii < idaData->N; ii++)
1393+
{
1394+
if(sparsePattern->colorCols[ii]-1 == i)
1395+
{
1396+
jacData->seedVars[ii] = 1;
1397+
}
14171398
}
14181399

1419-
(*idaData->residualFunction)(tt, yy, yp, idaData->newdelta, userData);
1420-
1400+
data->callback->functionJacA_column(data, threadData);
14211401
increaseJacContext(data);
14221402

1423-
for(j = 0; j < idaData->N; j++)
1403+
for(ii = 0; ii < idaData->N; ii++)
14241404
{
1425-
DENSE_ELEM(Jac, j, i) = (newdelta[j] - delta[j]) * deltaInv;
1426-
1405+
if(sparsePattern->colorCols[ii]-1 == i)
1406+
{
1407+
nth = sparsePattern->leadindex[ii];
1408+
while(nth < sparsePattern->leadindex[ii+1])
1409+
{
1410+
j = sparsePattern->index[nth];
1411+
infoStreamPrint(LOG_JAC, 0, "### symbolical jacobian at [%d,%d] = %f ###", j, ii, jacData->resultVars[j]);
1412+
DENSE_ELEM(Jac, j, ii) = jacData->resultVars[j];
1413+
nth++;
1414+
};
1415+
}
14271416
}
1428-
states[i] = ysave;
1429-
if (idaData->daeMode){
1430-
yprime[i] = ypsave;
1417+
1418+
for(ii=0; ii < idaData->N; ii++)
1419+
{
1420+
jacData->seedVars[ii] = 0;
14311421
}
14321422
}
14331423
unsetContext(data);
@@ -1437,9 +1427,9 @@ int jacOwnNumIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, DlsMat Jac, d
14371427
}
14381428

14391429
/*
1440-
* provides a numerical Jacobian
1430+
* wrapper function to call dense Jacobian
14411431
*/
1442-
static int callDenseNumJac(long int Neq, double tt, double cj,
1432+
static int callDenseJacobian(long int Neq, double tt, double cj,
14431433
N_Vector yy, N_Vector yp, N_Vector rr,
14441434
DlsMat Jac, void *user_data,
14451435
N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
@@ -1452,13 +1442,17 @@ static int callDenseNumJac(long int Neq, double tt, double cj,
14521442
/* profiling */
14531443
rt_tick(SIM_TIMER_JACOBIAN);
14541444

1455-
if (idaData->jacobianMethod == COLOREDNUMJAC)
1445+
if (idaData->jacobianMethod == COLOREDNUMJAC || idaData->jacobianMethod == NUMJAC)
14561446
{
1457-
retVal = jacOwnNumColoredIDA(tt, yy, yp, rr, Jac, cj, user_data);
1447+
retVal = jacColoredNumericalDense(tt, yy, yp, rr, Jac, cj, user_data);
14581448
}
1459-
else if (idaData->jacobianMethod == NUMJAC)
1449+
else if (idaData->jacobianMethod == COLOREDSYMJAC || idaData->jacobianMethod == SYMJAC)
14601450
{
1461-
retVal = jacOwnNumIDA(tt, yy, yp, rr, Jac, cj, user_data);
1451+
retVal = jacColoredSymbolicalDense(tt, yy, yp, rr, Jac, cj, user_data);
1452+
}
1453+
else
1454+
{
1455+
throwStreamPrint(threadData, "##IDA## Something goes wrong while obtain jacobian matrix!");
14621456
}
14631457

14641458
/* profiling */
@@ -1514,7 +1508,7 @@ static void finishSparseColPtr(SlsMat mat, int nnz)
15141508
* into a sparse SlsMat matrix
15151509
*/
15161510
static
1517-
int jacobianSparseNumIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, SlsMat Jac, double cj, void *userData)
1511+
int jacoColoredNumericalSparse(double tt, N_Vector yy, N_Vector yp, N_Vector rr, SlsMat Jac, double cj, void *userData)
15181512
{
15191513
TRACE_PUSH
15201514
IDA_SOLVER* idaData = (IDA_SOLVER*)userData;
@@ -1645,15 +1639,83 @@ int jacobianSparseNumIDA(double tt, N_Vector yy, N_Vector yp, N_Vector rr, SlsMa
16451639
return 0;
16461640
}
16471641

1642+
/* \fn jacColoredSymbolicalSparse(double tt, N_Vector yy, N_Vector yp, N_Vector rr, SlsMat Jac, double cj, void *userData)
1643+
*
1644+
*
1645+
* This function calculates symbolically the jacobian matrix and exploiting the coloring.
1646+
*/
1647+
int
1648+
jacColoredSymbolicalSparse(double tt, N_Vector yy, N_Vector yp, N_Vector rr, SlsMat Jac, double cj, void *userData)
1649+
{
1650+
TRACE_PUSH
1651+
IDA_SOLVER* idaData = (IDA_SOLVER*)userData;
1652+
DATA* data = (DATA*)(((IDA_USERDATA*)idaData->simData)->data);
1653+
threadData_t* threadData = (threadData_t*)(((IDA_USERDATA*)idaData->simData)->threadData);
1654+
void* ida_mem = idaData->ida_mem;
1655+
const int index = data->callback->INDEX_JAC_A;
1656+
unsigned int i,ii,j,nth;
1657+
1658+
/* prepare variables */
1659+
double *states = N_VGetArrayPointer(yy);
1660+
double *yprime = N_VGetArrayPointer(yp);
1661+
1662+
ANALYTIC_JACOBIAN* jacData = &(data->simulationInfo->analyticJacobians[index]);
1663+
SPARSE_PATTERN* sparsePattern = &(jacData->sparsePattern);
1664+
1665+
/* it's needed to clear the matrix */
1666+
SlsSetToZero(Jac);
1667+
1668+
setContext(data, &tt, CONTEXT_JACOBIAN);
1669+
1670+
for(i = 0; i < sparsePattern->maxColors; i++)
1671+
{
1672+
for(ii=0; ii < idaData->N; ii++)
1673+
{
1674+
if(sparsePattern->colorCols[ii]-1 == i)
1675+
{
1676+
jacData->seedVars[ii] = 1;
1677+
}
1678+
}
1679+
1680+
data->callback->functionJacA_column(data, threadData);
1681+
increaseJacContext(data);
1682+
1683+
for(ii = 0; ii < idaData->N; ii++)
1684+
{
1685+
if(sparsePattern->colorCols[ii]-1 == i)
1686+
{
1687+
nth = sparsePattern->leadindex[ii];
1688+
while(nth < sparsePattern->leadindex[ii+1])
1689+
{
1690+
j = sparsePattern->index[nth];
1691+
setJacElementKluSparse(j, ii, jacData->resultVars[j], nth, Jac);
1692+
nth++;
1693+
};
1694+
}
1695+
}
1696+
1697+
for(ii=0; ii < idaData->N; ii++)
1698+
{
1699+
jacData->seedVars[ii] = 0;
1700+
}
1701+
}
1702+
finishSparseColPtr(Jac, sparsePattern->numberOfNoneZeros);
1703+
unsetContext(data);
1704+
1705+
TRACE_POP
1706+
return 0;
1707+
}
1708+
16481709
/*
1649-
* Wrapper function for jacobianSparseNumIDA
1710+
* Wrapper function to call numerical or symbolical jacobian matrix
16501711
*/
1651-
static int jacobianSparseNum(double tt, double cj,
1712+
static int callSparseJacobian(double tt, double cj,
16521713
N_Vector yy, N_Vector yp, N_Vector rr,
16531714
SlsMat Jac, void *user_data,
16541715
N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
16551716
{
16561717
TRACE_PUSH
1718+
int retVal;
16571719

16581720
IDA_SOLVER* idaData = (IDA_SOLVER*)user_data;
16591721
DATA* data = (DATA*)(((IDA_USERDATA*)idaData->simData)->data);
@@ -1662,11 +1724,13 @@ static int jacobianSparseNum(double tt, double cj,
16621724
/* profiling */
16631725
rt_tick(SIM_TIMER_JACOBIAN);
16641726

1665-
if(jacobianSparseNumIDA(tt, yy, yp, rr, Jac, cj, user_data))
1727+
if (idaData->jacobianMethod == COLOREDSYMJAC || idaData->jacobianMethod == SYMJAC)
16661728
{
1667-
throwStreamPrint(threadData, "Error, can not get Matrix A ");
1668-
TRACE_POP
1669-
return 1;
1729+
retVal = jacColoredSymbolicalSparse(tt, yy, yp, rr, Jac, cj, user_data);
1730+
}
1731+
else if (idaData->jacobianMethod == COLOREDNUMJAC || idaData->jacobianMethod == NUMJAC)
1732+
{
1733+
retVal = jacoColoredNumericalSparse(tt, yy, yp, rr, Jac, cj, user_data);
16701734
}
16711735

16721736
/* profiling */
@@ -1692,7 +1756,7 @@ static int jacobianSparseNum(double tt, double cj,
16921756
}
16931757

16941758
TRACE_POP
1695-
return 0;
1759+
return retVal;
16961760
}
16971761

16981762
static
@@ -1727,13 +1791,13 @@ int getScalingFactors(DATA* data, IDA_SOLVER *idaData, SlsMat inScaleMatrix)
17271791
if (idaData->linearSolverMethod == IDA_LS_KLU)
17281792
{
17291793
scaleMatrix = NewSparseMat(idaData->N, idaData->N, idaData->NNZ);
1730-
jacobianSparseNum(data->localData[0]->timeValue, 1.0, idaData->y, idaData->yp, rres,
1794+
callSparseJacobian(data->localData[0]->timeValue, 1.0, idaData->y, idaData->yp, rres,
17311795
scaleMatrix, idaData, tmp1, tmp2, tmp3);
17321796
}
17331797
else
17341798
{
17351799
DlsMat denseMatrix = NewDenseMat(idaData->N, idaData->N);
1736-
callDenseNumJac(idaData->N, data->localData[0]->timeValue, 1.0, idaData->y, idaData->yp, rres,
1800+
callDenseJacobian(idaData->N, data->localData[0]->timeValue, 1.0, idaData->y, idaData->yp, rres,
17371801
denseMatrix, idaData, tmp1, tmp2, tmp3);
17381802
scaleMatrix = SlsConvertDls(denseMatrix);
17391803
}

0 commit comments

Comments
 (0)