Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 21
Functions: 0.0% 0 / 0 / 3
Branches: 0.0% 0 / 0 / 16

OMCompiler/SimulationRuntime/c/moo/info.h
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28 #ifndef MOO_OM_INFO_GDOP_H
29 #define MOO_OM_INFO_GDOP_H
30
31 #include "simulation_data.h"
32 #include "simulation/solver/gbode_main.h"
33 #include "simulation/solver/external_input.h"
34
35 #include <base/nlp_structs.h>
36 #include <base/fixed_vector.h>
37 #include <nlp/solvers/nlp_solver_settings.h>
38
39 #include "hessian_finite_diff.h"
40
41 #include <memory>
42
43 namespace OpenModelica {
44
45 /* foward decl */
46 struct ExchangeJacobians;
47 struct ExchangeHessians;
48
49 struct InfoGDOP {
50 DATA* data; // pointer to OM data object
51 threadData_t* threadData; // pointer to OM threadData object
52 int argc; // command-line arg count OM
53 char** argv; // command-line args OM
54
55 /* problem sizes */
56 int x_size;
57 int u_size;
58 int p_size;
59 int xu_size;
60 int f_size;
61 int g_size;
62 int r_size;
63
64 /* objective structure */
65 bool mayer_exists;
66 bool lagrange_exists;
67
68 /* addresses in realVars */
69 modelica_real* address_mayer_real_vars;
70 modelica_real* address_lagrange_real_vars;
71
72 /* realVars variables indices */
73 const int index_x_real_vars = 0;
74 int index_der_x_real_vars;
75 int index_mayer_real_vars = -1;
76 int index_lagrange_real_vars = -1;
77 FixedVector<int> u_indices_real_vars;
78 int index_g_real_vars;
79 int index_r_real_vars;
80
81 /* exchange format for Jacobians OM <-> MOO */
82 std::unique_ptr<ExchangeJacobians> exc_jac;
83
84 /* numerical Hessians */
85 std::unique_ptr<ExchangeHessians> exc_hes;
86
87 /* time horizon */
88 f64 t0; // model start_time
89 f64 tf; // model stop_time
90 int intervals; // model interval count
91 int stages; // stage count
92
93 /* L2BN mesh settings -> move to YAML */
94 int l2bn_phase_one_iterations = 0;
95 int l2bn_phase_two_iterations = 0;
96 f64 l2bn_phase_two_level = 0.0;
97
98 SOLVER_METHOD user_ode_solver = S_GBODE;
99
100 InfoGDOP(DATA* data, threadData_t* threadData, int argc, char** argv);
101
102 void set_user_solver();
103 void set_l2bn_options();
104 void set_omc_flags(NLP::NLPSolverSettings& nlp_solver_settings);
105 void set_time_horizon(int steps);
106 };
107
108 /**
109 * @brief Constructs and initializes OpenModelica Jacobians and their COO mappings for optimization.
110 *
111 * This constructor sets up the Jacobian matrices (A, B, C, D) using OpenModelica's internal
112 * CSC (Compressed Sparse Column) structures and transforms them into COO (Coordinate) format
113 * as required by the optimization backend.
114 *
115 * OpenModelica provides the following Jacobians in CSC format:
116 * - A = (f_{xu})^T
117 * - B = (f_{xu}, L_{xu}, g_{xu})^T
118 * - C = (f_{xu}, L_{xu}, M_{xu}, g_{xu})^T
119 * - D = (r_{xu})^T
120 *
121 * ### LFG Block (B matrix)
122 * - The B matrix includes rows for f, L, and g in that order (`fLg`).
123 * - It is converted directly from CSC to COO without reordering.
124 * - Although the sparsity structure is stored in COO format, the numerical values remain in CSC order.
125 * - This allows the original CSC evaluation buffer to be passed directly to the optimizer callbacks,
126 * since the buffer indices (`buf_index`) in the sparsity structure correctly point to CSC entries.
127 *
128 * ### MR Block (C and D matrices)
129 * - **Mayer term (M)** is embedded in the C matrix:
130 * - C has row order: f, L, M, g.
131 * - It is converted to COO format, and the M row is moved to the top to match the optimizer's expected order.
132 * - During evaluation, the full C matrix is evaluated in CSC format into a temporary buffer.
133 * - Using the `coo_to_csc` mapping, only the entries of the M row (now first in COO) are extracted
134 * into the final buffer passed to the optimizer.
135 *
136 * - **Boundary constraints (r)** are represented in the D matrix:
137 * - D contains only `r_{xu}` and is converted directly to COO.
138 * - Since the optimizer expects `[M, r]` ordering in the MR block, a row offset is applied
139 * during evaluation to place `r` entries after the Mayer entries in the final buffer.
140 *
141 * Throughout this process, the `csc_to_coo` and `coo_to_csc` permutation arrays maintain consistent
142 * mapping between OpenModelica’s CSC structures and the COO format expected by the optimization routines.
143 */
144
145 struct ExchangeJacobian {
146 JACOBIAN* jacobian;
147 bool exists;
148 CscToCoo sparsity;
149 FixedVector<modelica_real> buffer;
150
151 ✗ ExchangeJacobian(InfoGDOP& info,
152 int index,
153 initialAnalyticalJacobian_func_ptr initial_jacobian,
154 int move_to_first_row = -1,
155 ✗ int nnz_offset = 0) :
156 ✗ jacobian(&(info.data->simulationInfo->analyticJacobians[index])),
157 ✗ exists(static_cast<bool>(initial_jacobian(info.data, info.threadData, jacobian) == 0)),
158 ✗ sparsity(exists ? CscToCoo::from_csc(reinterpret_cast<int*>(jacobian->sparsePattern->leadindex),
159 ✗ reinterpret_cast<int*>(jacobian->sparsePattern->index),
160 ✗ static_cast<int>(jacobian->sizeCols),
161 ✗ static_cast<int>(jacobian->sparsePattern->nnz),
162 move_to_first_row,
163 nnz_offset)
164 : CscToCoo()),
165 ✗ buffer(FixedVector<modelica_real>(sparsity.nnz)) {}
166 };
167
168 struct ExchangeJacobians {
169 ExchangeJacobian A;
170 ExchangeJacobian B;
171 ExchangeJacobian C;
172 ExchangeJacobian D;
173
174 ExchangeJacobians(InfoGDOP& info);
175 };
176
177 struct ExchangeHessian {
178 HESSIAN_PATTERN* hessian;
179 bool exists;
180 ExtrapolationData* extr;
181
182 /* some workspace memory for output of Hessian, use if needed */
183 FixedVector<modelica_real> buffer;
184
185 /* some workspace memory for dual multiplicators, use if needed */
186 FixedVector<modelica_real> lambda;
187
188 /* wrapper args for Richardson extrapolation */
189 HessianFiniteDiffArgs args;
190
191 ✗ ExchangeHessian(InfoGDOP& info,
192 ✗ ExchangeJacobian& inducing_jacobian) :
193 ✗ hessian(generate_hessian_pattern(inducing_jacobian.jacobian)),
194 ✗ exists(inducing_jacobian.exists),
195 ✗ extr(!exists ? nullptr : init_extrapolation_data(hessian->lnnz, 5)),
196 ✗ buffer(FixedVector<modelica_real>(!exists ? 0 : hessian->lnnz)),
197 ✗ lambda(FixedVector<modelica_real>(!exists ? 0 : hessian->numFuncs)),
198 ✗ args(HessianFiniteDiffArgs{info.data, info.threadData, hessian, info.u_indices_real_vars.raw(), lambda.raw(), nullptr}) {}
199
200 ✗ ~ExchangeHessian() {
201 // delete c mallocs
202 ✗ if (extr) free_extrapolation_data(extr);
203 ✗ if (hessian) free_hessian_pattern(hessian);
204 ✗ }
205
206 // copy = delete
207 ExchangeHessian(const ExchangeHessian&) = delete;
208 ExchangeHessian& operator=(const ExchangeHessian&) = delete;
209 };
210
211 struct ExchangeHessians {
212 ExchangeHessian A;
213 ExchangeHessian B;
214 ExchangeHessian C;
215 ExchangeHessian D;
216
217 /* mapping of OM C and D HESSIAN_PATTERN indices -> Mr buffer indices, will be set in 'init_hes_mr()' */
218 FixedVector<std::pair<int, int>> C_to_Mr_buffer;
219 FixedVector<std::pair<int, int>> D_to_Mr_buffer;
220
221 ExchangeHessians(InfoGDOP& info);
222 };
223
224 } // namespace OpenModelica
225
226 #endif // MOO_OM_INFO_GDOP_H
227