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 |