Skip to content

Commit d6ca858

Browse files
authored
[C] Unify Jacobian evaluation (wip) (#13709)
TODO: - sparse memory format - unify remaining functions - numeric jacobian - scaling (x, residual?)
1 parent 15b549b commit d6ca858

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+486
-904
lines changed

OMCompiler/Compiler/Template/CodegenC.tpl

Lines changed: 39 additions & 38 deletions
Large diffs are not rendered by default.

OMCompiler/SimulationRuntime/c/dataReconciliation/dataReconciliation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ matrixData getJacobianMatrixF(DATA * data, threadData_t * threadData, ofstream &
14891489
{
14901490
// initialize the jacobian call
14911491
const int index = data->callback->INDEX_JAC_F;
1492-
ANALYTIC_JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
1492+
JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
14931493
data->callback->initialAnalyticJacobianF(data, threadData, jacobian);
14941494
int cols = jacobian->sizeCols;
14951495
int rows = jacobian->sizeRows;
@@ -1533,7 +1533,7 @@ matrixData getJacobianMatrixH(DATA * data, threadData_t * threadData, ofstream &
15331533
{
15341534
// initialize the jacobian call
15351535
const int index = data->callback->INDEX_JAC_H;
1536-
ANALYTIC_JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
1536+
JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
15371537
data->callback->initialAnalyticJacobianH(data, threadData, jacobian);
15381538
int cols = jacobian->sizeCols;
15391539
int rows = jacobian->sizeRows;

OMCompiler/SimulationRuntime/c/linearization/linearize.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ int functionJacBD_num(DATA* data, threadData_t *threadData, double *matrixB, dou
332332
int functionJacA(DATA* data, threadData_t *threadData, double* jac){
333333

334334
const int index = data->callback->INDEX_JAC_A;
335-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
335+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
336336
unsigned int i,j,k;
337337
k = 0;
338338
if (jacobian->constantEqns != NULL) {
@@ -378,7 +378,7 @@ int functionJacA(DATA* data, threadData_t *threadData, double* jac){
378378
int functionJacB(DATA* data, threadData_t *threadData, double* jac){
379379

380380
const int index = data->callback->INDEX_JAC_B;
381-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
381+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
382382

383383
unsigned int i,j,k;
384384
k = 0;
@@ -424,7 +424,7 @@ int functionJacB(DATA* data, threadData_t *threadData, double* jac){
424424
int functionJacC(DATA* data, threadData_t *threadData, double* jac){
425425

426426
const int index = data->callback->INDEX_JAC_C;
427-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
427+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
428428
unsigned int i,j,k;
429429
k = 0;
430430
if (jacobian->constantEqns != NULL) {
@@ -467,7 +467,7 @@ int functionJacC(DATA* data, threadData_t *threadData, double* jac){
467467
int functionJacD(DATA* data, threadData_t *threadData, double* jac){
468468

469469
const int index = data->callback->INDEX_JAC_D;
470-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
470+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[index]);
471471
unsigned int i,j,k;
472472
k = 0;
473473
if (jacobian->constantEqns != NULL) {
@@ -572,7 +572,7 @@ int linearize(DATA* data, threadData_t *threadData)
572572
if (data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A].sizeTmpVars > 0){
573573
/* Retrieve symbolic Jacobian */
574574
/* Determine Matrix A */
575-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A]);
575+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A]);
576576
if(!data->callback->initialAnalyticJacobianA(data, threadData, jacobian)){
577577
assertStreamPrint(threadData,0==functionJacA(data, threadData, matrixA),"Error, can not get Matrix A ");
578578
}

OMCompiler/SimulationRuntime/c/openmodelica_func.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,12 @@ struct OpenModelicaGeneratedFunctionCallbacks {
274274
/*
275275
* These functions calculate specific jacobian column.
276276
*/
277-
analyticalJacobianColumn_func_ptr functionJacA_column;
278-
analyticalJacobianColumn_func_ptr functionJacB_column;
279-
analyticalJacobianColumn_func_ptr functionJacC_column;
280-
analyticalJacobianColumn_func_ptr functionJacD_column;
281-
analyticalJacobianColumn_func_ptr functionJacF_column;
282-
analyticalJacobianColumn_func_ptr functionJacH_column;
277+
jacobianColumn_func_ptr functionJacA_column;
278+
jacobianColumn_func_ptr functionJacB_column;
279+
jacobianColumn_func_ptr functionJacC_column;
280+
jacobianColumn_func_ptr functionJacD_column;
281+
jacobianColumn_func_ptr functionJacF_column;
282+
jacobianColumn_func_ptr functionJacH_column;
283283
/*#endif*/
284284

285285
const char *(*linear_model_frame)(void); /* printf format-string with holes for 6 strings */
@@ -373,14 +373,14 @@ struct OpenModelicaGeneratedFunctionCallbacks {
373373
* FMU continuous partial derivative functions
374374
*/
375375
initialAnalyticalJacobian_func_ptr initialPartialFMIDER;
376-
analyticalJacobianColumn_func_ptr functionJacFMIDER_column;
376+
jacobianColumn_func_ptr functionJacFMIDER_column;
377377
const int INDEX_JAC_FMIDER;
378378

379379
/*
380380
* FMU partial derivative functions for initilization DAE
381381
*/
382382
initialAnalyticalJacobian_func_ptr initialPartialFMIDERINIT;
383-
analyticalJacobianColumn_func_ptr functionJacFMIDERINIT_column;
383+
jacobianColumn_func_ptr functionJacFMIDERINIT_column;
384384
const int INDEX_JAC_FMIDERINIT;
385385
};
386386

OMCompiler/SimulationRuntime/c/optimization/DataManagement/MoveData.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ void diffSynColoredOptimizerSystem(OptData *optData, modelica_real **J, const in
811811
int i,j,l,ii, ll;
812812

813813
const int h_index = optData->s.indexABCD[index];
814-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[h_index]);
814+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[h_index]);
815815
const long double * scaldt = optData->bounds.scaldt[m];
816816
const unsigned int * const cC = jacobian->sparsePattern->colorCols;
817817
const unsigned int * const lindex = jacobian->sparsePattern->leadindex;
@@ -877,7 +877,7 @@ void diffSynColoredOptimizerSystemF(OptData *optData, modelica_real **J){
877877
int i,j,l,ii, ll;
878878
const int index = 4;
879879
const int h_index = optData->s.indexABCD[index];
880-
ANALYTIC_JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[h_index]);
880+
JACOBIAN* jacobian = &(data->simulationInfo->analyticJacobians[h_index]);
881881
const unsigned int * const cC = jacobian->sparsePattern->colorCols;
882882
const unsigned int * const lindex = jacobian->sparsePattern->leadindex;
883883
const int nx = jacobian->sizeCols;

OMCompiler/SimulationRuntime/c/simulation/jacobian_util.c

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@
4848
* NULL if not available.
4949
* @param sparsePattern Pointer to sparsity pattern of Jacobian.
5050
*/
51-
void initAnalyticJacobian(ANALYTIC_JACOBIAN* jacobian, unsigned int sizeCols, unsigned int sizeRows, unsigned int sizeTmpVars, int (*constantEqns)(void* data, threadData_t *threadData, void* thisJacobian, void* parentJacobian), SPARSE_PATTERN* sparsePattern) {
51+
void initJacobian(JACOBIAN* jacobian, unsigned int sizeCols, unsigned int sizeRows, unsigned int sizeTmpVars, jacobianColumn_func_ptr evalColumn, jacobianColumn_func_ptr constantEqns, SPARSE_PATTERN* sparsePattern)
52+
{
5253
jacobian->sizeCols = sizeCols;
5354
jacobian->sizeRows = sizeRows;
5455
jacobian->sizeTmpVars = sizeTmpVars;
5556
jacobian->seedVars = (modelica_real*) calloc(sizeCols, sizeof(modelica_real));
5657
jacobian->resultVars = (modelica_real*) calloc(sizeRows, sizeof(modelica_real));
5758
jacobian->tmpVars = (modelica_real*) calloc(sizeTmpVars, sizeof(modelica_real));
59+
jacobian->evalColumn = evalColumn;
5860
jacobian->constantEqns = constantEqns;
5961
jacobian->sparsePattern = sparsePattern;
6062
jacobian->availability = JACOBIAN_UNKNOWN;
@@ -67,16 +69,18 @@ void initAnalyticJacobian(ANALYTIC_JACOBIAN* jacobian, unsigned int sizeCols, un
6769
* Sparsity pattern is not copied, only the pointer to it.
6870
*
6971
* @param source Jacobian that should be copied.
70-
* @return ANALYTIC_JACOBIAN* Copy of source.
72+
* @return JACOBIAN* Copy of source.
7173
*/
72-
ANALYTIC_JACOBIAN* copyAnalyticJacobian(ANALYTIC_JACOBIAN* source) {
73-
ANALYTIC_JACOBIAN* jacobian = (ANALYTIC_JACOBIAN*) malloc(sizeof(ANALYTIC_JACOBIAN));
74-
initAnalyticJacobian(jacobian,
75-
source->sizeCols,
76-
source->sizeRows,
77-
source->sizeTmpVars,
78-
source->constantEqns,
79-
source->sparsePattern);
74+
JACOBIAN* copyJacobian(JACOBIAN* source)
75+
{
76+
JACOBIAN* jacobian = (JACOBIAN*) malloc(sizeof(JACOBIAN));
77+
initJacobian(jacobian,
78+
source->sizeCols,
79+
source->sizeRows,
80+
source->sizeTmpVars,
81+
source->evalColumn,
82+
source->constantEqns,
83+
source->sparsePattern);
8084

8185
return jacobian;
8286
}
@@ -88,7 +92,8 @@ ANALYTIC_JACOBIAN* copyAnalyticJacobian(ANALYTIC_JACOBIAN* source) {
8892
*
8993
* @param jac Pointer to Jacobian.
9094
*/
91-
void freeAnalyticJacobian(ANALYTIC_JACOBIAN *jac) {
95+
void freeJacobian(JACOBIAN *jac)
96+
{
9297
if (jac == NULL) {
9398
return;
9499
}
@@ -99,6 +104,53 @@ void freeAnalyticJacobian(ANALYTIC_JACOBIAN *jac) {
99104
free(jac->sparsePattern); jac->sparsePattern = NULL;
100105
}
101106

107+
/*! \fn evalJacobian
108+
*
109+
* compute entries of Jacobian
110+
* uses coloring (from sparsity pattern) if available
111+
*
112+
* \param [ref] [data]
113+
* \param [ref] [threadData]
114+
* \param [ref] [jacobian] Pointer to Jacobian
115+
* \param [out] [jac] Contains jacobian values on exit, column-major
116+
*/
117+
void evalJacobian(DATA* data, threadData_t *threadData, JACOBIAN* jacobian, JACOBIAN* parentJacobian, modelica_real* jac)
118+
{
119+
int i,j,k,l,ii;
120+
const SPARSE_PATTERN* sp = jacobian->sparsePattern;
121+
122+
memset(jac, 0.0, (jacobian->sizeRows) * (jacobian->sizeCols) * sizeof(modelica_real));
123+
124+
/* evaluate constant equations of Jacobian */
125+
if (jacobian->constantEqns != NULL) {
126+
jacobian->constantEqns(data, threadData, jacobian, parentJacobian);
127+
}
128+
129+
/* evaluate Jacobian */
130+
for (i = 0; i < sp->maxColors; i++) {
131+
/* activate seed variable for the corresponding color */
132+
for (j = 0; j < jacobian->sizeCols; j++)
133+
if (sp->colorCols[j]-1 == i)
134+
jacobian->seedVars[j] = 1.0;
135+
136+
/* evaluate Jacobian column */
137+
jacobian->evalColumn(data, threadData, jacobian, parentJacobian);
138+
139+
for (j = 0; j < jacobian->sizeCols; j++) {
140+
if (sp->colorCols[j]-1 == i) {
141+
for (ii = sp->leadindex[j]; ii < sp->leadindex[j+1]; ii++) {
142+
l = sp->index[ii];
143+
k = j*jacobian->sizeRows + l;
144+
jac[k] = jacobian->resultVars[l]; //* solverData->xScaling[j];
145+
}
146+
/* de-activate seed variable for the corresponding color */
147+
jacobian->seedVars[j] = 0.0;
148+
}
149+
}
150+
}
151+
}
152+
153+
102154
/**
103155
* @brief Allocate memory for sparsity pattern.
104156
*
@@ -108,7 +160,8 @@ void freeAnalyticJacobian(ANALYTIC_JACOBIAN *jac) {
108160
* @param maxColors Maximum number of colors of Matrix.
109161
* @return SPARSE_PATTERN* Pointer ot allocated sparsity pattern of Matrix.
110162
*/
111-
SPARSE_PATTERN* allocSparsePattern(unsigned int n_leadIndex, unsigned int numberOfNonZeros, unsigned int maxColors) {
163+
SPARSE_PATTERN* allocSparsePattern(unsigned int n_leadIndex, unsigned int numberOfNonZeros, unsigned int maxColors)
164+
{
112165
SPARSE_PATTERN* sparsePattern = (SPARSE_PATTERN*) malloc(sizeof(SPARSE_PATTERN));
113166
sparsePattern->leadindex = (unsigned int*) malloc((n_leadIndex+1)*sizeof(unsigned int));
114167
sparsePattern->index = (unsigned int*) malloc(numberOfNonZeros*sizeof(unsigned int));
@@ -125,7 +178,8 @@ SPARSE_PATTERN* allocSparsePattern(unsigned int n_leadIndex, unsigned int number
125178
*
126179
* @param spp Pointer to sparsity pattern
127180
*/
128-
void freeSparsePattern(SPARSE_PATTERN *spp) {
181+
void freeSparsePattern(SPARSE_PATTERN *spp)
182+
{
129183
if (spp != NULL) {
130184
free(spp->index); spp->index = NULL;
131185
free(spp->colorCols); spp->colorCols = NULL;
@@ -141,7 +195,8 @@ void freeSparsePattern(SPARSE_PATTERN *spp) {
141195
* @param filename String for the filename.
142196
* @return FILE* Pointer to sparsity pattern stream.
143197
*/
144-
FILE * openSparsePatternFile(DATA* data, threadData_t *threadData, const char* filename) {
198+
FILE * openSparsePatternFile(DATA* data, threadData_t *threadData, const char* filename)
199+
{
145200
FILE* pFile;
146201
const char* fullPath = NULL;
147202

@@ -168,7 +223,8 @@ FILE * openSparsePatternFile(DATA* data, threadData_t *threadData, const char* f
168223
* @param color Current color index.
169224
* @param length Number of columns in color `color`.
170225
*/
171-
void readSparsePatternColor(threadData_t* threadData, FILE * pFile, unsigned int* colorCols, unsigned int color, unsigned int length, unsigned int maxIndex) {
226+
void readSparsePatternColor(threadData_t* threadData, FILE * pFile, unsigned int* colorCols, unsigned int color, unsigned int length, unsigned int maxIndex)
227+
{
172228
unsigned int i, index;
173229
size_t count;
174230

@@ -192,7 +248,8 @@ void readSparsePatternColor(threadData_t* threadData, FILE * pFile, unsigned int
192248
* @param flagValue Flag value of FLAG_JACOBIAN. Can be NULL.
193249
* @return JACOBIAN_METHOD Returns jacobian method that is availble.
194250
*/
195-
JACOBIAN_METHOD setJacobianMethod(threadData_t* threadData, JACOBIAN_AVAILABILITY availability, const char* flagValue){
251+
JACOBIAN_METHOD setJacobianMethod(threadData_t* threadData, JACOBIAN_AVAILABILITY availability, const char* flagValue)
252+
{
196253
JACOBIAN_METHOD jacobianMethod = JAC_UNKNOWN;
197254
assertStreamPrint(threadData, availability != JACOBIAN_UNKNOWN, "Jacobian availablity status is unknown.");
198255

@@ -205,7 +262,7 @@ JACOBIAN_METHOD setJacobianMethod(threadData_t* threadData, JACOBIAN_AVAILABILIT
205262
}
206263
}
207264
// Error case
208-
if(jacobianMethod == JAC_UNKNOWN){
265+
if (jacobianMethod == JAC_UNKNOWN) {
209266
errorStreamPrint(OMC_LOG_STDOUT, 0, "Unknown value `%s` for flag `-jacobian`", flagValue);
210267
infoStreamPrint(OMC_LOG_STDOUT, 1, "Available options are");
211268
for (int method=1; method < JAC_MAX; method++) {
@@ -271,7 +328,8 @@ JACOBIAN_METHOD setJacobianMethod(threadData_t* threadData, JACOBIAN_AVAILABILIT
271328
return jacobianMethod;
272329
}
273330

274-
void freeNonlinearPattern(NONLINEAR_PATTERN *nlp) {
331+
void freeNonlinearPattern(NONLINEAR_PATTERN *nlp)
332+
{
275333
if (nlp != NULL) {
276334
free(nlp->indexVar); nlp->indexVar = NULL;
277335
free(nlp->indexEqn); nlp->indexEqn = NULL;
@@ -280,19 +338,20 @@ void freeNonlinearPattern(NONLINEAR_PATTERN *nlp) {
280338
}
281339
}
282340

283-
unsigned int* getNonlinearPatternCol(NONLINEAR_PATTERN *nlp, int var_idx){
341+
unsigned int* getNonlinearPatternCol(NONLINEAR_PATTERN *nlp, int var_idx)
342+
{
284343
unsigned int idx_start = nlp->indexVar[var_idx];
285344
unsigned int idx_stop;
286-
if (var_idx == nlp->numberOfVars){
345+
if (var_idx == nlp->numberOfVars) {
287346
idx_stop = nlp->numberOfNonlinear;
288-
}else{
347+
} else {
289348
idx_stop = nlp->indexVar[var_idx + 1];
290349
}
291350

292351
unsigned int* col = (unsigned int*) malloc((idx_stop - idx_start + 1)*sizeof(unsigned int));
293352

294353
int index = 0;
295-
for(int i = idx_start; i < idx_stop + 1; i++){
354+
for (int i = idx_start; i < idx_stop + 1; i++) {
296355
col[index] = nlp->columns[i];
297356
index++;
298357
}
@@ -305,12 +364,13 @@ unsigned int* getNonlinearPatternCol(NONLINEAR_PATTERN *nlp, int var_idx){
305364
return col;
306365
}
307366

308-
unsigned int* getNonlinearPatternRow(NONLINEAR_PATTERN *nlp, int eqn_idx){
367+
unsigned int* getNonlinearPatternRow(NONLINEAR_PATTERN *nlp, int eqn_idx)
368+
{
309369
unsigned int idx_start = nlp->indexEqn[eqn_idx];
310370
unsigned int idx_stop;
311-
if (eqn_idx == nlp->numberOfEqns){
371+
if (eqn_idx == nlp->numberOfEqns) {
312372
idx_stop = nlp->numberOfNonlinear;
313-
}else{
373+
} else {
314374
idx_stop = nlp->indexEqn[eqn_idx + 1];
315375
}
316376
//printf(" eqn_idx = %d\n", eqn_idx);
@@ -319,7 +379,7 @@ unsigned int* getNonlinearPatternRow(NONLINEAR_PATTERN *nlp, int eqn_idx){
319379
unsigned int* row = (unsigned int*) malloc((idx_stop - idx_start + 1)*sizeof(unsigned int));
320380

321381
int index = 0;
322-
for(int i = idx_start; i < idx_stop + 1; i++){
382+
for (int i = idx_start; i < idx_stop + 1; i++) {
323383
row[index] = nlp->rows[i];
324384
//printf(" row[index] = row[%d] = %d\n", index, row[index]);
325385
index++;

OMCompiler/SimulationRuntime/c/simulation/jacobian_util.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@
4040
extern "C" {
4141
#endif
4242

43-
void initAnalyticJacobian(ANALYTIC_JACOBIAN* jacobian, unsigned int sizeCols, unsigned int sizeRows, unsigned int sizeTmpVars, int (*constantEqns)(void* data, threadData_t *threadData, void* thisJacobian, void* parentJacobian), SPARSE_PATTERN* sparsePattern);
44-
ANALYTIC_JACOBIAN* copyAnalyticJacobian(ANALYTIC_JACOBIAN* source);
45-
void freeAnalyticJacobian(ANALYTIC_JACOBIAN* jac);
43+
void initJacobian(JACOBIAN* jacobian, unsigned int sizeCols, unsigned int sizeRows, unsigned int sizeTmpVars, jacobianColumn_func_ptr evalColumn, jacobianColumn_func_ptr constantEqns, SPARSE_PATTERN* sparsePattern);
44+
JACOBIAN* copyJacobian(JACOBIAN* source);
45+
void freeJacobian(JACOBIAN* jac);
46+
47+
void evalJacobian(DATA* data, threadData_t *threadData, JACOBIAN* jacobian, JACOBIAN* parentJacobian, modelica_real* jac);
4648

4749
SPARSE_PATTERN* allocSparsePattern(unsigned int n_leadIndex, unsigned int numberOfNonZeros, unsigned int maxColors);
4850
void freeSparsePattern(SPARSE_PATTERN *spp);

OMCompiler/SimulationRuntime/c/simulation/solver/cvode_solver.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ int cvode_solver_initial(DATA *data, threadData_t *threadData, SOLVER_INFO *solv
526526
int flag;
527527
int i;
528528
double *abstol_tmp;
529-
ANALYTIC_JACOBIAN *jacobian;
529+
JACOBIAN *jacobian;
530530

531531
/* Log cvode_initial */
532532
infoStreamPrint(OMC_LOG_SOLVER_V, 0, "### Start initialize of CVODE solver ###");

0 commit comments

Comments
 (0)