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 / 1378
Functions: 0.0% 0 / 1 / 55
Branches: 0.0% 0 / 0 / 2440

OMCompiler/SimulationRuntime/c/dataReconciliation/dataReconciliation.cpp
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 #include "util/omc_error.h"
29 #include "simulation_data.h"
30 #include "openmodelica_func.h"
31 #include "simulation/solver/external_input.h"
32 #include "simulation/options.h"
33 #include "simulation/solver/model_help.h"
34 #include "simulation/jacobian_util.h"
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 #include <fstream>
39 #include <vector>
40 #include <algorithm>
41 #include <iomanip>
42 #include <stdlib.h>
43 #include <math.h>
44 #include <ctime>
45 #include <regex>
46 #include "omc_config.h"
47 #include "../util/omc_file.h"
48 #include <cmath>
49 #include "dataReconciliation.h"
50 using namespace std;
51
52 extern "C"
53 {
54 int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
55 int dgemm_(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda,
56 double *b, int *ldb, double *beta, double *c, int *ldc);
57 int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
58 int dgetri_(int *n, double *a, int *lda, int *ipiv, double *work, int *lwork, int *info);
59 int dscal_(int *n, double *da, double *dx, int *incx);
60 int dcopy_(int *n, double *dx, int *incx, double *dy, int *incy);
61 }
62
63 // only 200 values of chisquared x^2 values are added with degree of freedom
64 static double chisquaredvalue[200] = {3.84146, 5.99146, 7.81473, 9.48773, 11.0705, 12.5916, 14.0671, 15.5073, 16.919, 18.307, 19.6751, 21.0261, 22.362, 23.6848, 24.9958, 26.2962, 27.5871, 28.8693, 30.1435, 31.4104, 32.6706, 33.9244, 35.1725, 36.415, 37.6525, 38.8851, 40.1133, 41.3371, 42.557, 43.773, 44.9853, 46.1943, 47.3999, 48.6024, 49.8018, 50.9985, 52.1923, 53.3835, 54.5722, 55.7585, 56.9424, 58.124, 59.3035, 60.4809, 61.6562, 62.8296, 64.0011, 65.1708, 66.3386, 67.5048, 68.6693, 69.8322, 70.9935, 72.1532, 73.3115, 74.4683, 75.6237, 76.7778, 77.9305, 79.0819, 80.2321, 81.381, 82.5287, 83.6753, 84.8206, 85.9649, 87.1081, 88.2502, 89.3912, 90.5312, 91.6702, 92.8083, 93.9453, 95.0815, 96.2167, 97.351, 98.4844, 99.6169, 100.749, 101.879, 103.01, 104.139, 105.267, 106.395, 107.522, 108.648, 109.773, 110.898, 112.022, 113.145, 114.268, 115.39, 116.511, 117.632, 118.752, 119.871, 120.99, 122.108, 123.225, 124.342, 125.458, 126.574, 127.689, 128.804, 129.918, 131.031, 132.144, 133.257, 134.369, 135.48, 136.591, 137.701, 138.811, 139.921, 141.03, 142.138, 143.246, 144.354, 145.461, 146.567, 147.674, 148.779, 149.885, 150.989, 152.094, 153.198, 154.302, 155.405, 156.508, 157.61, 158.712, 159.814, 160.915, 162.016, 163.116, 164.216, 165.316, 166.415, 167.514, 168.613, 169.711, 170.809, 171.907, 173.004, 174.101, 175.198, 176.294, 177.39, 178.485, 179.581, 180.676, 181.77, 182.865, 183.959, 185.052, 186.146, 187.239, 188.332, 189.424, 190.516, 191.608, 192.7, 193.791, 194.883, 195.973, 197.064, 198.154, 199.244, 200.334, 201.423, 202.513, 203.602, 204.69, 205.779, 206.867, 207.955, 209.042, 210.13, 211.217, 212.304, 213.391, 214.477, 215.563, 216.649, 217.735, 218.82, 219.906, 220.991, 222.076, 223.16, 224.245, 225.329, 226.413, 227.496, 228.58, 229.663, 230.746, 231.829, 232.912};
65
66 struct csvData
67 {
68 int linecount;
69 int rowcount;
70 int columncount;
71 vector<double> xdata;
72 vector<double> sxdata;
73 vector<string> headers;
74 vector< vector<string> > rx;
75 };
76
77 struct errorData
78 {
79 string name;
80 string x;
81 string sx;
82 };
83
84 struct correlationData
85 {
86 vector<double> data;
87 vector<string> rowHeaders;
88 vector<string> columnHeaders;
89 };
90
91 struct correlationDataWarning
92 {
93 vector<string> diagonalEntry;
94 vector<string> aboveDiagonalEntry;
95 vector<errorData> warningInfo; // to warn user about entries closer to 1
96 };
97
98 struct matrixData
99 {
100 int rows;
101 int column;
102 double * data;
103 };
104
105 ✗ struct inputData
106 {
107 int rows;
108 int column;
109 double * data;
110 vector<int> index;
111 };
112
113 ✗ struct dataReconciliationData
114 {
115 csvData csvinputs;
116 matrixData xdiag;
117 matrixData reconciled_X;
118 matrixData reconciled_SX; // full covariance matrix
119 matrixData copyreconSx_diag; // only diagonal elements
120 double *newX;
121 double eps;
122 int iterationcount;
123 double value;
124 double J;
125 correlationDataWarning warning;
126 };
127
128 ✗ struct boundaryConditionData
129 {
130 std::vector<std::string> boundaryConditionVars;
131 double *boundaryConditionVarsResults;
132 double *reconSt_diag;
133 };
134
135 ✗ void copyReferenceFile(DATA * data, const std::string & filename)
136 {
137 ✗ std::string outputPath = std::string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + std::string(data->modelData->modelFilePrefix) + filename;
138
139 // Read the reference file from -inputPath when it's given -- that's what
140 // OMEdit passes, since the model isn't necessarily run from its build
141 // directory -- falling back to the current directory otherwise.
142 ✗ std::string inputDir = omc_flag[FLAG_INPUT_PATH] ? std::string(omc_flagValue[FLAG_INPUT_PATH]) : std::string(".");
143 ✗ std::string referenceFile = inputDir + "/" + std::string(data->modelData->modelFilePrefix) + filename;
144
145 // If the output directory is the same as the input directory, the file is
146 // already there -- skip the copy. ofstream truncates on open, so opening
147 // the same file for both reading and writing here would wipe it out
148 // instead of copying it.
149 char resolvedOutputDir[PATH_MAX];
150 char resolvedInputDir[PATH_MAX];
151 ✗ if (realpath(omc_flagValue[FLAG_OUTPUT_PATH], resolvedOutputDir) && realpath(inputDir.c_str(), resolvedInputDir)
152 ✗ && std::string(resolvedOutputDir) == std::string(resolvedInputDir))
153 {
154 return;
155 }
156
157 ✗ ifstream ifstreamfile;
158 ✗ ifstreamfile.open(referenceFile);
159
160 ✗ if (ifstreamfile.good())
161 {
162 ✗ ofstream ofstreamfile;
163 ✗ ofstreamfile.open(outputPath);
164 ✗ ofstreamfile << ifstreamfile.rdbuf();
165 ✗ ofstreamfile.close();
166 ✗ ifstreamfile.close();
167 ✗ }
168 ✗ }
169
170 ✗ int getRelatedBoundaryConditions(DATA * data)
171 {
172 // check for _relatedBoundaryConditionsEquations.txt file exists to map the nonReconciled Vars failing with condition-2 of extraction algorithm
173 ✗ std::string relatedBoundaryConditionsFilename = string(data->modelData->modelFilePrefix) + "_relatedBoundaryConditionsEquations.html";
174
175 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
176 {
177 ✗ relatedBoundaryConditionsFilename = string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + relatedBoundaryConditionsFilename;
178 ✗ copyReferenceFile(data, "_relatedBoundaryConditionsEquations.html");
179 }
180
181 ✗ ifstream relatedBoundaryConditionsFilenameip(relatedBoundaryConditionsFilename);
182 string line;
183 int count = 0;
184 ✗ if (relatedBoundaryConditionsFilenameip.good())
185 {
186 ✗ while (relatedBoundaryConditionsFilenameip.good())
187 {
188 ✗ getline(relatedBoundaryConditionsFilenameip, line);
189 ✗ if (!line.empty())
190 {
191 ✗ count = count + 1;
192 }
193 }
194 ✗ relatedBoundaryConditionsFilenameip.close();
195 //omc_unlink(relatedBoundaryConditionsFilename.c_str());
196 }
197 ✗ return count;
198 ✗ }
199
200 /*
201 * create html report with error logs for D.1
202 */
203 ✗ void createErrorHtmlReport(DATA * data, int status = 0)
204 {
205 // create HTML Report with Error Logs
206 ✗ ofstream myfile;
207 ✗ time_t now = time(0);
208 ✗ std::stringstream htmlfile;
209 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
210 {
211 ✗ htmlfile << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << ".html";
212 }
213 else
214 {
215 ✗ htmlfile << data->modelData->modelFilePrefix << ".html";
216 }
217 string html = htmlfile.str();
218 ✗ myfile.open(html.c_str());
219
220 /* Add Overview Data */
221 ✗ myfile << "<!DOCTYPE html><html>\n <head> <h1> Data Reconciliation Report</h1></head> \n <body> \n ";
222 ✗ myfile << "<h2> Overview: </h2>\n";
223 ✗ myfile << "<table> \n";
224 ✗ myfile << "<tr> \n" << "<th align=right> Model file: </th> \n" << "<td>" << data->modelData->modelFileName << "</td> </tr>\n";
225 ✗ myfile << "<tr> \n" << "<th align=right> Model name: </th> \n" << "<td>" << data->modelData->modelName << "</td> </tr>\n";
226 ✗ myfile << "<tr> \n" << "<th align=right> Model directory: </th> \n" << "<td>" << data->modelData->modelDir << "</td> </tr>\n";
227 ✗ if (omc_flagValue[FLAG_DATA_RECONCILE_Sx])
228 {
229 ✗ myfile << "<tr> \n" << "<th align=right> Measurement input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "</td> </tr>\n";
230 }
231 else
232 {
233 ✗ myfile << "<tr> \n" << "<th align=right> Measurement input file: </th> \n" << "<td style=color:red>" << "no file provided" << "</td> </tr>\n";
234 }
235 ✗ myfile << "<tr> \n" << "<th align=right> Correlation matrix input file: </th> \n" << "<td>" << "no file provided" << "</td> </tr>\n";
236 ✗ myfile << "<tr> \n" << "<th align=right> Generated: </th> \n" << "<td>" << ctime(&now) << " by "<< "<b>" << CONFIG_VERSION << "</b>" << "</td> </tr>\n";
237 ✗ myfile << "</table>\n";
238
239 /* add analysis section */
240 ✗ myfile << "<h2> Analysis: </h2>\n";
241 ✗ myfile << "<table> \n";
242 ✗ myfile << "<tr> \n" << "<th align=right> Number of auxiliary conditions: </th> \n" << "<td>" << data->modelData->nSetcVars << "</td> </tr>\n";
243 ✗ myfile << "<tr> \n" << "<th align=right> Number of measured variables: </th> \n" << "<td>" << data->modelData->ndataReconVars << "</td> </tr>\n";
244 ✗ myfile << "<tr> \n" << "<th align=right> Number of unmeasured variables: </th> \n" << "<td>" << data->modelData->nSetbVars << "</td> </tr>\n";
245 ✗ myfile << "<tr> \n" << "<th align=right> Number of related boundary conditions: </th> \n" << "<td>" << data->modelData->nRelatedBoundaryConditions << "</td> </tr>\n";
246 ✗ myfile << "</table> \n";
247
248 // Auxiliary Conditions
249 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_AuxiliaryConditions.html" << " target=_blank> Auxiliary conditions </a> </h3>\n";
250 // Intermediate Conditions
251 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_IntermediateEquations.html" << " target=_blank> Intermediate equations </a> </h3>\n";
252
253 ✗ if (data->modelData->nSetbVars > 0)
254 {
255 // Boundary Conditions
256 //myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionsEquations.html" << " target=_blank> Boundary conditions </a> </h3>\n";
257 // Intermediate Conditions
258 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionIntermediateEquations.html" << " target=_blank> Intermediate equations for unmeasured variables </a> </h3>\n";
259 }
260
261 ✗ if (data->modelData->nRelatedBoundaryConditions > 0)
262 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_relatedBoundaryConditionsEquations.html" << " target=_blank> Related boundary conditions </a> </h3>\n";
263
264 // Error log
265 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << ".log" << " target=_blank> Errors </a> </h2>\n";
266 // copy the error log to output path
267 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
268 {
269 ✗ copyReferenceFile(data, ".log");
270 }
271
272 // iteration vars file
273 ✗ if (status == 0)
274 {
275 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << "_iterationVars.txt" << " target=_blank> Iteration vars </a> </h2>\n";
276 }
277 // debug log
278 ✗ if (status == 0)
279 {
280 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << "_debug.txt" << " target=_blank> Debug log </a> </h2>\n";
281 }
282
283 ✗ myfile << "</table>\n";
284 ✗ myfile << "</body>\n</html>";
285 ✗ myfile.flush();
286 ✗ myfile.close();
287 ✗ }
288
289 /*
290 * create warning report for correlation coefficients data
291 */
292 ✗ void createCorrelationWarningReport(DATA * data, ofstream &myfile, correlationDataWarning &warningCorrelationData)
293 {
294 // create a warning log for correlation input file
295 ✗ if (!warningCorrelationData.aboveDiagonalEntry.empty() || !warningCorrelationData.diagonalEntry.empty() || !warningCorrelationData.warningInfo.empty())
296 {
297 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_warning.txt" << " target=_blank> Warnings </a> </h3>\n";
298 /* create a warning log file */
299 ✗ ofstream warningfile;
300 ✗ std::stringstream warning_file;
301 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
302 {
303 ✗ warning_file << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_warning.txt";
304 }
305 else
306 {
307 ✗ warning_file << data->modelData->modelFilePrefix << "_warning.txt";
308 }
309
310 ✗ warningfile.open(warning_file.str().c_str());
311 // user warning #1 : Diagonal entry for variable of interest <variable name> in correlation input file <input file name> is ignored
312 ✗ for (const auto &index : warningCorrelationData.diagonalEntry)
313 {
314 ✗ warningfile << "| warning | " << "Diagonal entry for variable of interest " << index << " in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " is ignored" << "\n";
315 }
316 // user warning #2 : Above diagonal entry for variable of interest <variable name> in correlation input file <input file name> is ignored
317 ✗ for (const auto &index : warningCorrelationData.aboveDiagonalEntry)
318 {
319 ✗ warningfile << "| warning | " << "Above diagonal entry for variable of interest " << index << " in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " is ignored" << "\n";
320 }
321 // user warning #3 : Entries in correlation matrix closer to 1 for variable of interest <variable name> in correlation input file <input file name>
322 ✗ for (const auto &info : warningCorrelationData.warningInfo)
323 {
324 ✗ warningfile << "| warning | " << "Entry for variable of interest " << info.name << " and variable of interest " << info.x << " in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " is closer to 1: " << "[" << info.sx << "]" <<"\n";
325 }
326 ✗ warningfile.close();
327 ✗ }
328 ✗ }
329
330
331 /*
332 * create html report for data Reconciliation D.1
333 */
334 ✗ void createHtmlReportFordataReconciliation(DATA *data, csvData &csvinputs, matrixData &xdiag, matrixData &reconciled_X, matrixData &copyreconSx_diag, double *newX, double &eps, int &iterationcount, double &value, double &J, correlationDataWarning &warningCorrelationData, boundaryConditionData& boundaryconditiondata)
335 {
336 ✗ ofstream myfile;
337 ✗ time_t now = time(0);
338 ✗ std::stringstream htmlfile;
339 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
340 {
341 ✗ htmlfile << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << ".html";
342 }
343 else
344 {
345 ✗ htmlfile << data->modelData->modelFilePrefix << ".html";
346 }
347 string html = htmlfile.str();
348 ✗ myfile.open(html.c_str());
349
350 /* create a csv file */
351 ✗ ofstream csvfile;
352 ✗ std::stringstream csv_file;
353 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
354 {
355 ✗ csv_file << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_Outputs.csv";
356 }
357 else
358 {
359 ✗ csv_file << data->modelData->modelFilePrefix << "_Outputs.csv";
360 }
361
362 string tmpcsv = csv_file.str();
363 ✗ csvfile.open(tmpcsv.c_str());
364
365 // check for nonReconciledVars.txt file exists to map the nonReconciled Vars failing with condition-2 of extraction algorithm
366 std::string nonReconciledVarsFilename;
367 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
368 {
369 ✗ nonReconciledVarsFilename = std::string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + std::string(data->modelData->modelFilePrefix) + "_NonReconcilcedVars.txt";
370 ✗ copyReferenceFile(data, "_NonReconcilcedVars.txt");
371 }
372 else
373 {
374 ✗ nonReconciledVarsFilename = string(data->modelData->modelFilePrefix) + "_NonReconcilcedVars.txt";
375 }
376 vector<std::string> nonReconciledVars;
377
378 ✗ ifstream nonreconcilevarsip(nonReconciledVarsFilename);
379 string line;
380 ✗ if (nonreconcilevarsip.good())
381 {
382 ✗ while (nonreconcilevarsip.good())
383 {
384 ✗ getline(nonreconcilevarsip, line);
385 ✗ if (!line.empty())
386 {
387 //std::cout << "\n reading nonVariables of interest : " << line;
388 ✗ nonReconciledVars.push_back(line);
389 }
390 }
391 ✗ nonreconcilevarsip.close();
392 //omc_unlink(nonReconciledVarsFilename.c_str());
393 }
394
395 /* Add Overview Data */
396 ✗ myfile << "<!DOCTYPE html><html>\n <head> <h1> Data Reconciliation Report</h1></head> \n <body> \n ";
397 ✗ myfile << "<h2> Overview: </h2>\n";
398 ✗ myfile << "<table> \n";
399 ✗ myfile << "<tr> \n" << "<th align=right> Model file: </th> \n" << "<td>" << data->modelData->modelFileName << "</td> </tr>\n";
400 ✗ myfile << "<tr> \n" << "<th align=right> Model name: </th> \n" << "<td>" << data->modelData->modelName << "</td> </tr>\n";
401 ✗ myfile << "<tr> \n" << "<th align=right> Model directory: </th> \n" << "<td>" << data->modelData->modelDir << "</td> </tr>\n";
402 ✗ myfile << "<tr> \n" << "<th align=right> Measurement input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "</td> </tr>\n";
403 ✗ if (omc_flagValue[FLAG_DATA_RECONCILE_Cx])
404 {
405 ✗ myfile << "<tr> \n" << "<th align=right> Correlation matrix input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << "</td> </tr>\n";
406 }
407 else
408 {
409 ✗ myfile << "<tr> \n" << "<th align=right> Correlation matrix input file: </th> \n" << "<td>" << "no file provided" << "</td> </tr>\n";
410 }
411 ✗ myfile << "<tr> \n" << "<th align=right> Generated: </th> \n" << "<td>" << ctime(&now) << " by "<< "<b>" << CONFIG_VERSION << "</b>" << "</td> </tr>\n";
412 ✗ myfile << "</table>\n";
413
414 /* Add Analysis data */
415 ✗ myfile << "<h2> Analysis: </h2>\n";
416 ✗ myfile << "<table> \n";
417 ✗ myfile << "<tr> \n" << "<th align=right> Number of auxiliary conditions: </th> \n" << "<td>" << data->modelData->nSetcVars << "</td> </tr>\n";
418 ✗ myfile << "<tr> \n" << "<th align=right> Number of measured variables: </th> \n" << "<td>" << data->modelData->ndataReconVars << "</td> </tr>\n";
419 ✗ myfile << "<tr> \n" << "<th align=right> Number of unmeasured variables: </th> \n" << "<td>" << data->modelData->nSetbVars << "</td> </tr>\n";
420 ✗ myfile << "<tr> \n" << "<th align=right> Number of related boundary conditions: </th> \n" << "<td>" << data->modelData->nRelatedBoundaryConditions << "</td> </tr>\n";
421 ✗ myfile << "<tr> \n" << "<th align=right> Number of iterations to convergence: </th> \n" << "<td>" << iterationcount << "</td> </tr>\n";
422 ✗ myfile << "<tr> \n" << "<th align=right> Final value of (J*/r) : </th> \n" << "<td>" << value << "</td> </tr>\n";
423 ✗ myfile << "<tr> \n" << "<th align=right> Epsilon : </th> \n" << "<td>" << eps << "</td> </tr>\n";
424 ✗ myfile << "<tr> \n" << "<th align=right> Final value of the objective function (J) : </th> \n" << "<td>" << J << "</td> </tr>\n";
425 //myfile << "<tr> \n" << "<th align=right> Chi-square value : </th> \n" << "<td>" << quantile(complement(chi_squared(data->modelData->nSetcVars), 0.05)) << "</td> </tr>\n";
426
427 ✗ if (data->modelData->nSetcVars > 200)
428 {
429 ✗ myfile << "<tr> \n" << "<th align=right> Chi-square value : </th> \n" << "<td>" << "NOT Available for equations > 200 in setC" << "</td> </tr>\n";
430 }
431 else
432 {
433 ✗ myfile << "<tr> \n" << "<th align=right> Chi-square value : </th> \n" << "<td>" << chisquaredvalue[data->modelData->nSetcVars - 1] << "</td> </tr>\n";
434 }
435 ✗ if (J <= chisquaredvalue[data->modelData->nSetcVars - 1])
436 {
437 ✗ myfile << "<tr> \n" << "<th align=right> Result of global test : </th> \n" << "<td>" << "TRUE" << "</td> </tr>\n";
438 }
439 else
440 {
441 ✗ myfile << "<tr> \n" << "<th align=right> Result of global test : </th> \n" << "<td>" << "FALSE" << "</td> </tr>\n";
442 }
443 ✗ myfile << "<tr> \n" << "<th align=right> Quality (J/Chi-square) : </th> \n" << "<td>" << J/chisquaredvalue[data->modelData->nSetcVars - 1] << "</td> </tr>\n";
444 ✗ myfile << "</table>\n";
445
446 // Auxiliary Conditions
447 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_AuxiliaryConditions.html" << " target=_blank> Auxiliary conditions </a> </h3>\n";
448
449 // Intermediate Conditions
450 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_IntermediateEquations.html" << " target=_blank> Intermediate equations for measured variables </a> </h3>\n";
451
452 ✗ if (data->modelData->nSetbVars > 0)
453 {
454 // Boundary Conditions
455 //myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionsEquations.html" << " target=_blank> Boundary conditions </a> </h3>\n";
456 // Intermediate Conditions
457 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionIntermediateEquations.html" << " target=_blank> Intermediate equations for unmeasured variables </a> </h3>\n";
458 }
459
460 ✗ if (data->modelData->nRelatedBoundaryConditions > 0)
461 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_relatedBoundaryConditionsEquations.html" << " target=_blank> Related boundary conditions </a> </h3>\n";
462
463 // iteration vars file
464 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_iterationVars.txt" << " target=_blank> Iteration vars </a> </h3>\n";
465
466 // Debug log
467 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_debug.txt" << " target=_blank> Debug log </a> </h3>\n";
468
469 // create a warning log for correlation input file
470 ✗ createCorrelationWarningReport(data, myfile, warningCorrelationData);
471
472
473 /* Add Results data */
474 ✗ myfile << "<h2> Results: </h2>\n";
475 ✗ myfile << "<table border=2>\n";
476 ✗ myfile << "<tr>\n" << "<th> Variable to be Estimated </th>\n" << "<th> Unit </th>\n" << "<th> Description </th>\n" << "<th> Initial Measured Value </th>\n" << "<th> Estimated Value </th>\n" << "<th> Initial Uncertainty </th>\n" <<"<th> Estimated Uncertainty </th>\n";
477 ✗ csvfile << "Variable to be Estimated ," << "Initial Measured Value ," << "Estimated Value ," << "Initial Uncertainty ," << "Estimated Uncertainty,";
478 ✗ myfile << "<th> Result of Local Test </th>\n" << "<th> Local Quality </th>\n" << "<th> Comment </th>\n" << "</tr>\n";
479 ✗ csvfile << "Result of Local Test ," << "Local Quality ," << "\n";
480
481 // collect units and description
482
483 std::vector<std::string> unitString, unitStringUnMeasuredVariables;
484 std::vector<std::string> description, descriptionUnMeasuredVariables;
485 ✗ for (unsigned int r = 0; r < csvinputs.headers.size(); r++)
486 {
487 ✗ for (int i = 0; i < data->modelData->nVariablesReal; i++)
488 {
489 ✗ if (strcmp(data->modelData->realVarsData[i].info.name, csvinputs.headers[r].c_str())==0)
490 {
491 ✗ char *unitStr = omc_string_data(data->modelData->realVarsData[i].attribute.displayUnit);
492 ✗ unitString.push_back(unitStr);
493 ✗ description.push_back(data->modelData->realVarsData[i].info.comment);
494 }
495 else
496 {
497 // check units and description for unmeasured variables of interest
498 ✗ auto it = find(boundaryconditiondata.boundaryConditionVars.begin(), boundaryconditiondata.boundaryConditionVars.end(), data->modelData->realVarsData[i].info.name);
499 ✗ if (it != boundaryconditiondata.boundaryConditionVars.end())
500 {
501 ✗ char *unitStr = omc_string_data(data->modelData->realVarsData[i].attribute.displayUnit);
502 ✗ unitStringUnMeasuredVariables.push_back(unitStr);
503 ✗ descriptionUnMeasuredVariables.push_back(data->modelData->realVarsData[i].info.comment);
504 }
505 }
506 }
507 }
508
509 ✗ for (unsigned int r = 0; r < csvinputs.headers.size(); r++)
510 {
511 bool reconciled = true;
512 ✗ if (!nonReconciledVars.empty())
513 {
514 ✗ auto nonReconciledVar = std::find(nonReconciledVars.begin(), nonReconciledVars.end(), csvinputs.headers[r]);
515 ✗ if (nonReconciledVar != nonReconciledVars.end())
516 {
517 reconciled = false;
518 }
519 }
520
521 ✗ myfile << "<tr>\n";
522 // variables of interest
523 ✗ myfile << "<td>" << csvinputs.headers[r] << "</td>\n";
524 ✗ csvfile << csvinputs.headers[r] << ",";
525
526 // Unit
527 ✗ myfile << "<td>" << unitString[r] << "</td>\n";
528 //csvfile << unitString[r] << ",";
529
530 // description
531 ✗ myfile << "<td>" << description[r] << "</td>\n";
532 //csvfile << description[r] << ",";
533
534 // Initial Measured Values
535 ✗ myfile << "<td>" << xdiag.data[r] << "</td>\n";
536 ✗ csvfile << xdiag.data[r] << ",";
537
538 // Reconciled Values
539 ✗ myfile << "<td>" << reconciled_X.data[r] << "</td>\n";
540 ✗ csvfile << reconciled_X.data[r] << ",";
541
542 // Initial Uncertainty Values
543 ✗ myfile << "<td>" << csvinputs.sxdata[r] << "</td>\n";
544 ✗ csvfile << csvinputs.sxdata[r] << ",";
545
546 // Reconciled Uncertainty Values
547 ✗ myfile << "<td>" << copyreconSx_diag.data[r] << "</td>\n";
548 ✗ csvfile << copyreconSx_diag.data[r] << ",";
549
550 // Results of Local Tests
551 ✗ if (newX[r] < 1.96)
552 {
553 ✗ myfile << "<td>" << "TRUE" << "</td>\n";
554 ✗ csvfile << "TRUE" << ",";
555 }
556 else
557 {
558 ✗ myfile << "<td>" << "FALSE" << "</td>\n";
559 ✗ csvfile << "FALSE" << ",";
560 }
561
562 // Values of Local Tests
563 ✗ myfile << "<td>" << newX[r]/1.96 << "</td>\n";
564 ✗ csvfile << newX[r]/1.96 << ",\n";
565
566 // // Margin to Correctness(distance from 1.96)
567 // myfile << "<td>" << (1.96 - newX[r]) << "</td>\n";
568 // csvfile << (1.96 - newX[r]) << ",";
569
570 // comments
571 ✗ if (reconciled)
572 {
573 ✗ myfile << "<td>" << "" << "</td>\n";
574 //csvfile << "" << ",\n";
575 }
576 else
577 {
578 ✗ myfile << "<td style=color:red>" << "Not reconciled" << "</td>\n";
579 //csvfile << "Not reconciled" << ",\n";
580 }
581 ✗ myfile << "</tr>\n";
582 }
583
584 // check for boundary condition vars and unmeasured vars
585 ✗ if (!boundaryconditiondata.boundaryConditionVars.empty())
586 {
587 ✗ for (int i=0; i<boundaryconditiondata.boundaryConditionVars.size(); i++)
588 {
589 ✗ myfile << "<tr>\n";
590 ✗ myfile << "<td>" << boundaryconditiondata.boundaryConditionVars[i] << "</td>\n";
591 ✗ csvfile << boundaryconditiondata.boundaryConditionVars[i] << ",";
592
593 // unit
594 ✗ myfile << "<td>" << unitStringUnMeasuredVariables[i] << "</td>\n";
595 //csvfile << unitStringUnMeasuredVariables[i] << ",";
596
597 // description
598 ✗ myfile << "<td>"<< descriptionUnMeasuredVariables[i] << "</td>\n";
599 //csvfile << descriptionUnMeasuredVariables[i] << ",";
600
601 ✗ myfile << "<td> </td>\n";
602 ✗ csvfile << "" << ",";
603
604 ✗ myfile << "<td>" << boundaryconditiondata.boundaryConditionVarsResults[i] << "</td>\n";
605 ✗ csvfile << boundaryconditiondata.boundaryConditionVarsResults[i] << ",";
606
607 // Initial Uncertainty Values
608 ✗ myfile << "<td>" << "" << "</td>\n";
609 ✗ csvfile << "" << ",";
610
611 // Reconciled Uncertainty Values
612 ✗ myfile << "<td>" << boundaryconditiondata.reconSt_diag[i] << "</td>\n";
613 ✗ csvfile << boundaryconditiondata.reconSt_diag[i] << ",";
614
615 ✗ myfile << "<td>" << "" << "</td>\n";
616 ✗ csvfile << "" << ",";
617
618 ✗ myfile << "<td>" << "" << "</td>\n";
619 ✗ csvfile << "" << ",\n";
620
621 ✗ myfile << "<td>" << "" << "</td>\n";
622 //csvfile << "" << ",\n";
623 ✗ myfile << "</tr>\n";
624 }
625 }
626 ✗ csvfile.flush();
627 ✗ csvfile.close();
628 ✗ myfile << "</table>\n";
629 ✗ myfile << "</body>\n</html>";
630 ✗ myfile.flush();
631 ✗ myfile.close();
632 ✗ }
633
634 /*
635 * create html report with error logs for Boundary conditions D.2
636 */
637 ✗ void createErrorHtmlReportForBoundaryConditions(DATA * data, int status = 0)
638 {
639 // create HTML Report with Error Logs
640 ✗ ofstream myfile;
641 ✗ time_t now = time(0);
642 ✗ std::stringstream htmlfile;
643 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
644 {
645 ✗ htmlfile << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_BoundaryConditions.html";
646 }
647 else
648 {
649 ✗ htmlfile << data->modelData->modelFilePrefix << "_BoundaryConditions.html";
650 }
651 string html = htmlfile.str();
652 ✗ myfile.open(html.c_str());
653
654 /* Add Overview Data */
655 ✗ myfile << "<!DOCTYPE html><html>\n <head> <h1> Boundary Conditions Report </h1></head> \n <body> \n ";
656 ✗ myfile << "<h2> Overview: </h2>\n";
657 ✗ myfile << "<table> \n";
658 ✗ myfile << "<tr> \n" << "<th align=right> Model file: </th> \n" << "<td>" << data->modelData->modelFileName << "</td> </tr>\n";
659 ✗ myfile << "<tr> \n" << "<th align=right> Model name: </th> \n" << "<td>" << data->modelData->modelName << "</td> </tr>\n";
660 ✗ myfile << "<tr> \n" << "<th align=right> Model directory: </th> \n" << "<td>" << data->modelData->modelDir << "</td> </tr>\n";
661 // Sx input file
662 ✗ if (omc_flagValue[FLAG_DATA_RECONCILE_Sx])
663 {
664 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled values input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "</td> </tr>\n";
665 }
666 else
667 {
668 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled values input file: </th> \n" << "<td style=color:red>" << "no file provided" << "</td> </tr>\n";
669 }
670 // Cx input file
671 ✗ if (omc_flagValue[FLAG_DATA_RECONCILE_Cx])
672 {
673 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled covariance matrix input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << "</td> </tr>\n";
674 }
675 else
676 {
677 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled covariance matrix input file: </th> \n" << "<td style=color:red>" << "no file provided" << "</td> </tr>\n";
678 }
679 ✗ myfile << "<tr> \n" << "<th align=right> Generated: </th> \n" << "<td>" << ctime(&now) << " by "<< "<b>" << CONFIG_VERSION << "</b>" << "</td> </tr>\n";
680 ✗ myfile << "</table>\n";
681
682 /* add analysis section */
683 ✗ myfile << "<h2> Analysis: </h2>\n";
684 ✗ myfile << "<table> \n";
685 ✗ myfile << "<tr> \n" << "<th align=right> Number of boundary conditions: </th> \n" << "<td>" << data->modelData->nSetcVars << "</td> </tr>\n";
686 ✗ myfile << "<tr> \n" << "<th align=right> Number of variables to be reconciled: </th> \n" << "<td>" << data->modelData->ndataReconVars << "</td> </tr>\n";
687 ✗ myfile << "</table> \n";
688
689 // Boundary Conditions
690 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionsEquations.html" << " target=_blank> Boundary conditions </a> </h3>\n";
691 // Intermediate Conditions
692 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionIntermediateEquations.html" << " target=_blank> Intermediate equations </a> </h3>\n";
693
694 // Error log
695 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << ".log" << " target=_blank> Errors </a> </h2>\n";
696 // copy the error log to output path
697 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
698 {
699 ✗ copyReferenceFile(data, ".log");
700 }
701
702 // iteration vars file
703 ✗ if (status == 0)
704 {
705 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << "_iterationVars.txt" << " target=_blank> Iteration vars </a> </h2>\n";
706 }
707 // debug log
708 ✗ if (status == 0)
709 {
710 ✗ myfile << "<h2> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditions_debug.txt" << " target=_blank> Debug log </a> </h2>\n";
711 }
712
713 ✗ myfile << "</table>\n";
714 ✗ myfile << "</body>\n</html>";
715 ✗ myfile.flush();
716 ✗ myfile.close();
717 ✗ }
718
719 /*
720 * create HTML Report for Boundary Conditions D.2
721 */
722 ✗ void createHtmlReportForBoundaryConditions(DATA * data, std::vector<std::string> & boundaryConditionVars, double* values, double* uncertaintyValues, correlationDataWarning &warningCorrelationData)
723 {
724 ✗ ofstream myfile;
725 ✗ time_t now = time(0);
726 ✗ std::stringstream htmlfile;
727 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
728 {
729 ✗ htmlfile << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_BoundaryConditions.html";
730 }
731 else
732 {
733 ✗ htmlfile << data->modelData->modelFilePrefix << "_BoundaryConditions.html";
734 }
735 string html = htmlfile.str();
736 ✗ myfile.open(html.c_str());
737
738 /* create a csv file */
739 ✗ ofstream csvfile;
740 ✗ std::stringstream csv_file;
741 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
742 {
743 ✗ csv_file << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_BoundaryConditions_Outputs.csv";
744 }
745 else
746 {
747 ✗ csv_file << data->modelData->modelFilePrefix << "_BoundaryConditions_Outputs.csv";
748 }
749
750 string tmpcsv = csv_file.str();
751 ✗ csvfile.open(tmpcsv.c_str());
752
753 /* Add Overview Data */
754 ✗ myfile << "<!DOCTYPE html><html>\n <head> <h1> Boundary Conditions Report </h1></head> \n <body> \n ";
755 ✗ myfile << "<h2> Overview: </h2>\n";
756 ✗ myfile << "<table> \n";
757 ✗ myfile << "<tr> \n" << "<th align=right> Model file: </th> \n" << "<td>" << data->modelData->modelFileName << "</td> </tr>\n";
758 ✗ myfile << "<tr> \n" << "<th align=right> Model name: </th> \n" << "<td>" << data->modelData->modelName << "</td> </tr>\n";
759 ✗ myfile << "<tr> \n" << "<th align=right> Model directory: </th> \n" << "<td>" << data->modelData->modelDir << "</td> </tr>\n";
760 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled values input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "</td> </tr>\n";
761 ✗ if (omc_flagValue[FLAG_DATA_RECONCILE_Cx])
762 {
763 ✗ myfile << "<tr> \n" << "<th align=right> Reconciled covariance matrix input file: </th> \n" << "<td>" << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << "</td> </tr>\n";
764 }
765 else
766 {
767 ✗ myfile << "<tr> \n" << "<th align=right> Correlation matrix input file: </th> \n" << "<td>" << "no file provided" << "</td> </tr>\n";
768 }
769 ✗ myfile << "<tr> \n" << "<th align=right> Generated: </th> \n" << "<td>" << ctime(&now) << " by "<< "<b>" << CONFIG_VERSION << "</b>" << "</td> </tr>\n";
770 ✗ myfile << "</table>\n";
771
772 /* Add Analysis data */
773 ✗ myfile << "<h2> Analysis: </h2>\n";
774 ✗ myfile << "<table> \n";
775 ✗ myfile << "<tr> \n" << "<th align=right> Number of boundary conditions: </th> \n" << "<td>" << data->modelData->nSetcVars << "</td> </tr>\n";
776 ✗ myfile << "<tr> \n" << "<th align=right> Number of variables to be reconciled: </th> \n" << "<td>" << data->modelData->ndataReconVars << "</td> </tr>\n";
777 ✗ myfile << "</table>\n";
778
779 // Boundary Conditions
780 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionsEquations.html" << " target=_blank> Boundary conditions </a> </h3>\n";
781
782 // Intermediate Conditions
783 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditionIntermediateEquations.html" << " target=_blank> Intermediate equations </a> </h3>\n";
784
785 // iteration vars file
786 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_iterationVars.txt" << " target=_blank> Iteration vars </a> </h3>\n";
787
788 // Debug log
789 ✗ myfile << "<h3> <a href=" << data->modelData->modelFilePrefix << "_BoundaryConditions_debug.txt" << " target=_blank> Debug log </a> </h3>\n";
790
791 // create a warning log for correlation input file
792 ✗ createCorrelationWarningReport(data, myfile, warningCorrelationData);
793
794 /* Add Results data */
795 ✗ myfile << "<h2> Results: </h2>\n";
796 ✗ myfile << "<table border=2>\n";
797 ✗ myfile << "<tr>\n" << "<th> Boundary conditions </th>\n" << "<th> Values </th>\n" << "<th> Reconciled Half-width Confidence Intervals </th> </tr>\n";
798 ✗ csvfile << "Boundary conditions ," << "Values ," << "Reconciled Half-width Confidence Intervals," << "\n";
799
800 ✗ for (unsigned int r = 0; r < boundaryConditionVars.size(); r++)
801 {
802 ✗ myfile << "<tr>\n";
803 // Boundary Conditions
804 ✗ myfile << "<td>" << boundaryConditionVars[r] << "</td>\n";
805 ✗ csvfile << boundaryConditionVars[r] << ",";
806
807 // simulation Values
808 ✗ myfile << "<td>" << values[r] << "</td>\n";
809 ✗ csvfile << values[r] << ",";
810
811 // uncertainty Values
812 ✗ myfile << "<td>" << uncertaintyValues[r] << "</td>\n";
813 ✗ myfile << "</tr>\n";
814 ✗ csvfile << uncertaintyValues[r] << "," << "\n";
815 }
816
817 ✗ myfile << "</table>\n</html>";
818 ✗ myfile.close();
819 ✗ csvfile.close();
820 ✗ }
821
822 /*
823 * function which returns the index pos
824 * of input variables
825 */
826 ✗ int getVariableIndex(vector<string> headers, string name, ofstream & logfile, DATA * data)
827 {
828 int pos = -1;
829 ✗ for (unsigned int i = 0; i < headers.size(); i++)
830 {
831 //logfile << "founded headers " << headers[i] << i << "\n";
832 ✗ if (strcmp(headers[i].c_str(), name.c_str()) == 0)
833 {
834 ✗ pos = i;
835 ✗ break;
836 }
837 }
838 //logfile << "founded pos " << name << ": " << pos << "\n";
839 ✗ if (pos == -1)
840 {
841 //logfile << "Variable Name not Matched :" << name;
842 ✗ logfile << "| error | " << "CoRelation-Coefficient Variable Name not Matched: " << name << " ,getVariableIndex() failed!" << "\n";
843 ✗ logfile.close();
844 ✗ exit(1);
845 createErrorHtmlReport(data);
846 }
847 ✗ return pos;
848 }
849
850 /*
851 * check string is a valid double
852 */
853 ✗ bool isStringValidDouble(std::string &cref)
854 {
855 ✗ return std::regex_match(cref, std::regex("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"));
856 }
857
858 /*
859 * check string is a empty, (i.e) contains only "," in csv input
860 * also ignore lines starting with c comments //
861 */
862 ✗ bool isLineEmptyData(std::string &cref)
863 {
864 ✗ return std::regex_match(cref, std::regex("^[,|/]+.*"));
865 }
866
867 /*
868 * function which checks whether a variable
869 * is unmeasured (i.e) uncertain=Uncertainty.propagate
870 */
871 ✗ bool isUnmeasuredVariables(DATA* data, const char* name)
872 {
873 ✗ char **unmeasuredvariable = (char**) malloc(data->modelData->nSetbVars * sizeof(char*));
874 ✗ data->callback->dataReconciliationUnmeasuredVariables(data, unmeasuredvariable);
875 bool found = false;
876 // check for unmeasured variables
877 ✗ for (int i = 0; i < data->modelData->nSetbVars; i++)
878 {
879 ✗ if (strcmp(unmeasuredvariable[i], name) == 0)
880 {
881 found = true;
882 break;
883 }
884 }
885 ✗ free(unmeasuredvariable);
886 ✗ return found;
887 }
888
889 //----------------------------------------------
890 // Helper: Update Reconciled.mo with reconciled values
891 //----------------------------------------------
892 ✗ void updateReconciledMo(DATA * data, threadData_t * threadData, vector<string> headers, double * reconciled_X, ofstream & logfile)
893 {
894 ✗ std::string modelPrefix(data->modelData->modelFilePrefix);
895 std::replace(modelPrefix.begin(), modelPrefix.end(), '.', '_');
896
897 // check for reconciled.mo file to update with reconciled values
898 std::string reconciledMoFile, reconciledValuesMoFile;
899 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
900 {
901 ✗ reconciledMoFile = std::string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + data->modelData->modelFilePrefix +"_Reconciled_tmp.mo";
902 ✗ reconciledValuesMoFile = std::string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + "Reconciled_" + modelPrefix + ".mo";
903 ✗ copyReferenceFile(data, "_Reconciled_tmp.mo");
904 }
905 else
906 {
907 ✗ reconciledMoFile = std::string(data->modelData->modelFilePrefix) + "_Reconciled_tmp.mo";
908 ✗ reconciledValuesMoFile = "Reconciled_" + modelPrefix + ".mo";
909 }
910 ✗ std::ifstream infile(reconciledMoFile);
911 ✗ if (!infile.is_open())
912 {
913 // just give a warning, if file not found as this is optional and user may not want to update the file with reconciled values
914 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0, "Reconciled modelica file path not found %s.", reconciledMoFile.c_str());
915 ✗ logfile << "| warning | " << "Measurement input file path not found " << reconciledMoFile << "\n";
916 }
917
918 ✗ std::ofstream outfile(reconciledValuesMoFile);
919 ✗ if (!outfile.is_open())
920 {
921 // just give a warning, if file not found as this is optional and user may not want to update the file with reconciled values
922 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0, "Cannot open reconciled values output file %s.", reconciledValuesMoFile.c_str());
923 ✗ logfile << "| warning | " << "Cannot open reconciled values output file " << reconciledValuesMoFile << "\n";
924 }
925
926 std::string line;
927 int count = 1;
928 int varCount = 1; // counter for variables of interest
929 ✗ while (std::getline(infile, line))
930 {
931 ✗ if (count > 3 && varCount <= data->modelData->ndataReconVars)
932 {
933 ✗ std::string variableName(headers[varCount-1]);
934 std::replace(variableName.begin(), variableName.end(), '.', '_');
935 ✗ outfile << " parameter Real " << variableName << " = " << reconciled_X[varCount-1] << ";\n";
936 ✗ varCount++;
937 ✗ }
938 else
939 {
940 // copy other lines as it is
941 ✗ count++;
942 ✗ outfile << line << "\n";
943 }
944 }
945 ✗ infile.close();
946 ✗ outfile.close();
947 //omc_unlink(reconciledMoFile.c_str());
948 ✗ logfile << "| info | " << "Reconciled modelica file updated successfully " << reconciledValuesMoFile << "\n";
949 ✗ }
950
951 /*
952 * Function which reads the csv file
953 * and stores the initial measured value X and HalfWidth confidence
954 * interval Wx and also the input variable names
955 */
956 ✗ csvData readMeasurementInputFile(ofstream & logfile, DATA * data, threadData_t * threadData, bool boundaryConditions = false)
957 {
958 char * filename = NULL;
959 ✗ filename = (char*) omc_flagValue[FLAG_DATA_RECONCILE_Sx];
960
961 ✗ if (filename == NULL && !boundaryConditions)
962 {
963 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Measurement input file not provided (eg:-sx=filename.csv), DataReconciliation cannot be computed!.");
964 ✗ logfile << "| error | " << "Measurement input file not provided (eg:-sx=filename.csv), DataReconciliation cannot be computed!.\n";
965 ✗ logfile.close();
966 ✗ createErrorHtmlReport(data);
967 ✗ exit(1);
968 }
969
970 ✗ if (filename == NULL && boundaryConditions)
971 {
972 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Reconciled values input file not provided (eg:-sx=filename.csv), Boundary conditions cannot be computed!.");
973 ✗ logfile << "| error | " << "Reconciled values input file not provided (eg:-sx=filename.csv), Boundary conditions cannot be computed!.\n";
974 ✗ logfile.close();
975 ✗ createErrorHtmlReportForBoundaryConditions(data);
976 ✗ exit(1);
977 }
978 /*
979 * fix issue https://github.com/OpenModelica/OpenModelica/issues/13797
980 * check if filepath uses uri format and convert it to absolute path
981 * eg: modelica://Modelica/Resources/Files/filename.csv => /absolute/path/to/filename.csv
982 */
983 ✗ modelica_string uri = OpenModelica_uriToFilename(omc_string_new(filename));
984 ✗ std::string filenameStr = omc_string_data(uri);
985
986 ✗ ifstream ip(filenameStr.c_str());
987 string line;
988 vector<double> xdata;
989 vector<double> sxdata;
990 vector<string> names;
991 //vector<double> rx_ik;
992 vector< vector<string> > rx;
993 int Sxrowcount = 0;
994 ✗ int linecount = 1;
995 int Sxcolscount = 0;
996 bool flag = false;
997 vector<errorData> errorInfo;
998 vector<int> errorInfoHeaders;
999
1000 ✗ if (!ip.good() && !boundaryConditions)
1001 {
1002 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Measurement input file path not found %s.",filename);
1003 ✗ logfile << "| error | " << "Measurement input file path not found " << filename << "\n";
1004 ✗ logfile.close();
1005 ✗ createErrorHtmlReport(data);
1006 ✗ exit(1);
1007 }
1008
1009 ✗ if (!ip.good() && boundaryConditions)
1010 {
1011 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Reconciled values input file path not found %s.", filename);
1012 ✗ logfile << "| error | " << "Reconciled values input file path not found " << filename << "\n";
1013 ✗ logfile.close();
1014 ✗ createErrorHtmlReportForBoundaryConditions(data);
1015 ✗ exit(1);
1016 }
1017
1018 ✗ while (ip.good())
1019 {
1020 ✗ getline(ip, line);
1021 vector<string> t1;
1022
1023 // allow comments on the line#1 until finding the headers
1024 ✗ if (linecount == 1 && isLineEmptyData(line))
1025 {
1026 continue;
1027 }
1028
1029 ✗ if (linecount > 1 && !line.empty() && !isLineEmptyData(line))
1030 {
1031 //std::cout << "\nline info:" << line;
1032 std::replace(line.begin(), line.end(), ';', ',');
1033 // remove whitespace in a string
1034 ✗ line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end());
1035
1036 ✗ stringstream ss(line);
1037 string temp;
1038 int columnCount = 0;
1039 bool col0 = false, col1 = false, col2 = false;
1040 ✗ while (getline(ss, temp, ','))
1041 {
1042 // ignore unmeasured variables of interest
1043 ✗ if (columnCount == 0 && isUnmeasuredVariables(data, temp.c_str()))
1044 {
1045 col0 = true;
1046 col1 = true;
1047 col2 = true;
1048 break;
1049 }
1050
1051 ✗ if (columnCount == 0)
1052 {
1053 // // error : no variable of interest is provided by user at column #1
1054 ✗ if (temp.empty())
1055 {
1056 ✗ errorInfoHeaders.push_back(linecount);
1057 }
1058 col0 = true;
1059 ✗ names.push_back(temp.c_str());
1060 ✗ Sxrowcount++;
1061 ✗ if (!flag)
1062 {
1063 ✗ Sxcolscount++;
1064 }
1065 }
1066 ✗ if (columnCount == 1 && !temp.empty() && isStringValidDouble(temp))
1067 {
1068 //std::cout << "\n x: " << temp << " type : "<< isStringValidDouble(temp);
1069 //logfile << "xdata" << temp << " double" << atof(temp.c_str()) <<"\n";
1070 col1 = true;
1071 ✗ xdata.push_back(atof(temp.c_str()));
1072 ✗ if (!flag)
1073 {
1074 ✗ Sxcolscount++;
1075 }
1076 }
1077 ✗ if (columnCount == 2 && !temp.empty() && isStringValidDouble(temp))
1078 {
1079 //std::cout << "\n sxdata: " << temp << " valid type " << isStringValidDouble(temp);
1080 //logfile << "sxdata" << temp << " double" << atof(temp.c_str()) <<"\n";
1081 col2 = true;
1082 ✗ sxdata.push_back(atof(temp.c_str()));
1083 ✗ if (!flag)
1084 {
1085 ✗ Sxcolscount++;
1086 }
1087 }
1088 // ignore columns greater than 3
1089 ✗ if (columnCount > 2)
1090 {
1091 break;
1092 }
1093 ✗ columnCount++;
1094 }
1095 flag = true;
1096
1097 ✗ if (!col0 || !col1 || !col2)
1098 {
1099 ✗ std::string column1 = "(no-Value/wrong-Type)", column2 = "(no-Value/wrong-Type)", column3 = "(no-Value/wrong-Type)";
1100 ✗ if (col0)
1101 {
1102 column1 = names.back();
1103 }
1104 ✗ if (col1)
1105 {
1106 ✗ column2 = std::to_string(xdata.back());
1107 }
1108 ✗ if (col2)
1109 {
1110 ✗ column3 = std::to_string(sxdata.back());
1111 }
1112 errorData info = {column1, column2, column3};
1113 ✗ errorInfo.push_back(info);
1114 ✗ }
1115 ✗ }
1116 ✗ linecount++;
1117 ✗ }
1118
1119 // user error : variable of interest is missing in column #1
1120 ✗ if (!errorInfoHeaders.empty())
1121 {
1122 ✗ for (const auto &line : errorInfoHeaders)
1123 {
1124 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "the name of the variable of interest in measurement input file %s is missing in line #%d ", filename, line);
1125 ✗ logfile << "| error | " << "the name of the variable of interest in measurement input file " << filename << " is missing in line #" << line << "\n";
1126 }
1127 ✗ logfile.close();
1128 ✗ createErrorHtmlReport(data);
1129 ✗ exit(1);
1130 }
1131
1132 // user error #6: Entry for variable of interest <variable name> in measurement input file <input file name> is incorrect: <reason (no value or incorrect value type)>
1133 ✗ if (!errorInfo.empty())
1134 {
1135 ✗ for (const auto & info : errorInfo)
1136 {
1137 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Entry for variable of interest %s in measurement input file %s is incorrect because of (no-Value/wrong-Type), with following data: [%s, %s, %s] ", info.name.c_str(), filename, info.name.c_str(), info.x.c_str(), info.sx.c_str());
1138 ✗ logfile << "| error | " << "Entry for variable of interest " << info.name << " in measurement input file " << filename << " is incorrect because of (no-Value/wrong-Type), with following data: " << "[" << info.name << ", " << info.x << ", " << info.sx << "]" <<"\n";
1139 }
1140 ✗ logfile.close();
1141 ✗ createErrorHtmlReport(data);
1142 ✗ exit(1);
1143 }
1144
1145 //logfile << "csvdata header:" << "header length: " << names.size() << " " << names[0] << names[1] << names[2] << "" << "\n";
1146 //logfile << "linecount:" << linecount << " " << "rowcount :" << Sxrowcount << " " << "colscount:" << Sxcolscount << "\n";
1147
1148 ✗ csvData csvData = {linecount, Sxrowcount, Sxcolscount, xdata, sxdata, names, rx};
1149 ✗ return csvData;
1150 ✗ }
1151
1152 /*
1153 * Function which arranges the elements in column major
1154 */
1155 ✗ void initColumnMatrix(vector<double> data, int rows, int cols, double * tempSx)
1156 {
1157 ✗ for (int i = 0; i < rows; i++)
1158 {
1159 ✗ for (int j = 0; j < cols; j++)
1160 {
1161 // store the matrix in column order
1162 ✗ tempSx[j + i * rows] = data[i + j * rows];
1163 }
1164 }
1165 ✗ }
1166
1167 /*
1168 * Function to print and debug whether the matrices are stored in column major
1169 */
1170 ✗ void printColumnAlginment(double * matrix, int rows, int cols, string name)
1171 {
1172 ✗ cout << "\n" << "************ " << name << " **********" << "\n";
1173 ✗ for (int i = 0; i < rows * cols; i++)
1174 {
1175 ✗ cout << matrix[i] << " ";
1176 }
1177 ✗ cout << "\n";
1178 ✗ }
1179
1180 /*
1181 * Function to Print the matrix in row based format
1182 */
1183 ✗ void printMatrix(double * matrix, int rows, int cols, string name, ofstream & logfile)
1184 {
1185 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1186 ✗ for (int i = 0; i < rows; i++)
1187 {
1188 ✗ for (int j = 0; j < cols; j++)
1189 {
1190 //cout << setprecision(5);
1191 ✗ logfile << std::right << setw(15) << matrix[i + j * rows];
1192 ✗ logfile.flush();
1193 }
1194 ✗ logfile << "\n";
1195 }
1196 ✗ logfile << "\n";
1197 ✗ }
1198
1199 /*
1200 * Function to Print the matrix in row based format
1201 */
1202 ✗ void printMatrixModelicaFormat(double * matrix, int rows, int cols, string name, ofstream & logfile)
1203 {
1204 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1205 ✗ logfile << "\n[";
1206 ✗ for (int i = 0; i < rows; i++)
1207 {
1208 ✗ for (int j = 0; j < cols; j++)
1209 {
1210 //cout << setprecision(5);
1211 ✗ if (j == cols - 1)
1212 {
1213 ✗ logfile << std::right << setw(15) << matrix[i + j * rows] << ";\n";
1214 }
1215 else
1216 {
1217 ✗ logfile << std::right << setw(15) << matrix[i + j * rows] << ",";
1218 }
1219
1220 ✗ logfile.flush();
1221 }
1222 //logfile << ";\n";
1223 }
1224 ✗ logfile << "\n";
1225 ✗ }
1226
1227 /*
1228 *
1229 Function to Print the matrix in row based format with headers
1230 */
1231 ✗ void printMatrixWithHeaders(double * matrix, int rows, int cols, vector<string> headers, string name, ofstream & logfile)
1232 {
1233 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1234 ✗ for (int i = 0; i < rows; i++)
1235 {
1236 ✗ logfile << std::right << setw(10) << headers[i];
1237 ✗ for (int j = 0; j < cols; j++)
1238 {
1239 //cout << setprecision(5);
1240 ✗ logfile << std::right << setw(15) << matrix[i + j * rows];
1241 ✗ logfile.flush();
1242 //printf("% .5e ", matrix[i+j*rows]);
1243 }
1244 ✗ logfile << "\n";
1245 }
1246 ✗ logfile << "\n";
1247 ✗ }
1248
1249 /*
1250 *
1251 Function to Print the matrix in row based format with headers
1252 */
1253 ✗ void printBoundaryConditionsResults(double * matrixA, double * matrixB, int rows, int cols, vector<string> headers, string name, ofstream & logfile)
1254 {
1255 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1256 ✗ logfile << "\n Boundary conditions" << setw(20) << "Values" << setw(45) << "Half-width Confidence Interval" << "\n";
1257 ✗ for (int i = 0; i < rows; i++)
1258 {
1259 ✗ logfile << std::right << setw(20) << headers[i];
1260 ✗ for (int j = 0; j < cols; j++)
1261 {
1262 //cout << setprecision(5);
1263 ✗ logfile << std::right << setw(20) << matrixA[i + j * rows] << setw(25) << matrixB[i + j * rows];
1264 ✗ logfile.flush();
1265 //printf("% .5e ", matrix[i+j*rows]);
1266 }
1267 ✗ logfile << "\n";
1268 }
1269 ✗ logfile << "\n";
1270 ✗ }
1271
1272 ✗ void dumpReconciledSxToCSV(double * matrix, int rows, int cols, vector<string> headers, DATA * data)
1273 {
1274 /* create a csv file */
1275 ✗ ofstream csvfile;
1276 ✗ std::stringstream csv_file;
1277 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
1278 {
1279 ✗ csv_file << string(omc_flagValue[FLAG_OUTPUT_PATH]) << "/" << data->modelData->modelFilePrefix << "_Reconciled_Sx.csv";
1280 }
1281 else
1282 {
1283 ✗ csv_file << data->modelData->modelFilePrefix << "_Reconciled_Sx.csv";
1284 }
1285
1286 string tmpcsv = csv_file.str();
1287 ✗ csvfile.open(tmpcsv.c_str());
1288
1289 ✗ csvfile << "Sxij" << ",";
1290 ✗ for (auto it : headers)
1291 {
1292 //std::cout << "headers : " << it << "\n";
1293 ✗ csvfile << it << ",";
1294 }
1295 ✗ csvfile << "\n";
1296
1297 ✗ for (int i = 0; i < rows; i++)
1298 {
1299 ✗ csvfile << headers[i] << ",";
1300 ✗ for (int j = 0; j < cols; j++)
1301 {
1302 //cout << setprecision(5);
1303 ✗ csvfile << matrix[i + j * rows] << ",";
1304 //csvfile.flush();
1305 //printf("% .5e ", matrix[i+j*rows]);
1306 }
1307 ✗ csvfile << "\n";
1308 }
1309 //csvfile << "\n";
1310 ✗ csvfile.flush();
1311 ✗ csvfile.close();
1312 ✗ }
1313
1314 /*
1315 *Function to Print the vecomatrix in row based format with headers
1316 *based on vector arrays
1317 */
1318 ✗ void printVectorMatrixWithHeaders(vector<double> matrix, int rows, int cols, vector<string> headers, string name, ofstream & logfile)
1319 {
1320 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1321 ✗ for (int i = 0; i < rows; i++)
1322 {
1323 ✗ logfile << std::right << setw(10) << headers[i];
1324 ✗ for (int j = 0; j < cols; j++)
1325 {
1326 //cout << setprecision(5);
1327 ✗ logfile << std::right << setw(15) << matrix[i + j * rows];
1328 ✗ logfile.flush();
1329 //printf("% .5e ", matrix[i+j*rows]);
1330 }
1331 ✗ logfile << "\n";
1332 }
1333 ✗ logfile << "\n";
1334 ✗ }
1335
1336 /*
1337 Function to Print the corelation matrix in row based format with headers
1338 */
1339 ✗ void printCorelationMatrix(vector<double> cx_data, vector<string> rowHeaders, vector<string> columnHeaders, string name, ofstream & logfile, correlationDataWarning & warningCorrelationData)
1340 {
1341 ✗ if (cx_data.empty())
1342 {
1343 return;
1344 }
1345
1346 ✗ logfile << "\n" << "************ " << name << " **********" << "\n";
1347 ✗ for (int i = 0; i < rowHeaders.size(); i++)
1348 {
1349 logfile << std::right << setw(10) << rowHeaders[i];
1350 ✗ for (int j = 0; j < columnHeaders.size(); j++)
1351 {
1352 ✗ if (i == j && cx_data[columnHeaders.size() * i + j] != 0)
1353 {
1354 ✗ warningCorrelationData.diagonalEntry.push_back(rowHeaders[i]);
1355 }
1356 ✗ else if (j > i && cx_data[columnHeaders.size() * i + j] != 0)
1357 {
1358 ✗ warningCorrelationData.aboveDiagonalEntry.push_back(rowHeaders[i]);
1359 }
1360 ✗ logfile << std::right << setw(15) << cx_data[columnHeaders.size() * i + j];
1361 }
1362 ✗ logfile << "\n";
1363 }
1364 ✗ logfile << "\n";
1365 }
1366
1367 /*
1368 *
1369 Function Which gets the diagonal elements of the matrix
1370 */
1371 ✗ void getDiagonalElements(double * matrix, int rows, int cols, double * result)
1372 {
1373 int k = 0;
1374 ✗ for (int i = 0; i < rows; i++)
1375 {
1376 ✗ for (int j = 0; j < cols; j++)
1377 {
1378 ✗ if (i == j)
1379 {
1380 ✗ result[k++] = matrix[i + j * rows];
1381 }
1382 }
1383 }
1384 ✗ }
1385
1386 /*
1387 * Function to transpose the Matrix
1388 */
1389 ✗ void transposeMatrix(double * jacF, double * jacFT, int rows, int cols)
1390 {
1391 ✗ for (int i = 0; i < rows; i++)
1392 {
1393 ✗ for (int j = 0; j < cols; j++)
1394 {
1395 // Perform matrix transpose store the elements in column major
1396 ✗ jacFT[i * cols + j] = jacF[i + j * rows];
1397 }
1398 }
1399 ✗ }
1400
1401
1402 /*
1403 * Matrix Multiplication using dgemm LaPack routine
1404 */
1405 ✗ void solveMatrixMultiplication(double *matrixA, double *matrixB, int rowsa, int colsa, int rowsb, int colsb, double *matrixC, ofstream &logfile, DATA * data)
1406 {
1407 ✗ char trans = 'N';
1408 ✗ double one = 1.0, zero = 0.0;
1409 ✗ int rowsA = rowsa;
1410 int colsA = colsa;
1411 int rowsB = rowsb;
1412 ✗ int colsB = colsb;
1413 ✗ int common = colsa;
1414
1415 ✗ if (colsA != rowsB)
1416 {
1417 //cout << "\n Error: Column of First Matrix not equal to Rows of Second Matrix \n ";
1418 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "solveMatrixMultiplication() Failed!, Column of First Matrix not equal to Rows of Second Matrix %i != %i.",colsA,rowsB);
1419 ✗ logfile << "| error | " << "solveMatrixMultiplication() Failed!, Column of First Matrix not equal to Rows of Second Matrix " << colsA << " != " << rowsB << "\n";
1420 ✗ logfile.close();
1421 ✗ createErrorHtmlReport(data);
1422 ✗ exit(1);
1423 }
1424 // solve matrix multiplication using dgemm_ LAPACK routine
1425 ✗ dgemm_(&trans, &trans, &rowsA, &colsB, &common, &one, matrixA, &rowsA, matrixB, &common, &zero, matrixC, &rowsA);
1426 ✗ }
1427
1428 /*
1429 * Solve the Linear System A*x=b using LAPACK Solver routine dgesv_
1430 */
1431 ✗ void solveSystemFstar(int n, int nhrs, double *tmpMatrixD, double *tmpMatrixC, ofstream &logfile, DATA * data)
1432 {
1433 ✗ int N = n; // number of rows of Matrix A
1434 ✗ int NRHS = nhrs; // number of columns of Matrix B
1435 ✗ int LDA = N;
1436 ✗ int LDB = N;
1437 ✗ int* ipiv = new int[N];
1438 int info;
1439 // call the external function
1440 ✗ dgesv_(&N, &NRHS, tmpMatrixD, &LDA, ipiv, tmpMatrixC, &LDB, &info);
1441 ✗ delete[] ipiv;
1442
1443 ✗ if (info > 0)
1444 {
1445 //cout << "The solution could not be computed, The info satus is : " << info;
1446 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "solveSystemFstar() Failed !, The solution could not be computed, The info satus is %i", info);
1447 ✗ logfile << "| error | " << "solveSystemFstar() Failed !, The solution could not be computed, The info satus is " << info << "\n";
1448 ✗ logfile.close();
1449 ✗ createErrorHtmlReport(data);
1450 ✗ exit(1);
1451 }
1452 ✗ }
1453
1454 /*
1455 * Solve the matrix Subtraction of two matrices
1456 */
1457 ✗ void solveMatrixSubtraction(matrixData A, matrixData B, double *result, ofstream &logfile, DATA * data)
1458 {
1459 ✗ if (A.rows != B.rows && A.column != B.column)
1460 {
1461 //cout << "The Matrix Dimensions are not equal to Compute ! \n";
1462 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "solveMatrixSubtraction() Failed !, The Matrix Dimensions are not equal to Compute ! %i != %i.", A.rows,B.rows);
1463 ✗ logfile << "| error | " << "solveMatrixSubtraction() Failed !, The Matrix Dimensions are not equal to Compute" << A.rows << " != " << B.rows << "\n";
1464 ✗ logfile.close();
1465 ✗ createErrorHtmlReport(data);
1466 ✗ exit(1);
1467 }
1468
1469 //printColumnAlginment(A.data,A.rows,A.column,"A-Matrix");
1470 //printColumnAlginment(B.data,B.rows,B.column,"B-Matrix");
1471
1472 // subtract elements in cloumn major
1473 ✗ for (int i = 0; i < A.rows * A.column; i++)
1474 {
1475 ✗ result[i] = A.data[i] - B.data[i];
1476 }
1477 ✗ }
1478
1479 /*
1480 * Solve the matrix addition of two matrices
1481 */
1482 ✗ matrixData solveMatrixAddition(matrixData A, matrixData B, ofstream &logfile, DATA * data)
1483 {
1484 ✗ double *result = (double*) calloc(A.rows * A.column, sizeof(double));
1485 ✗ if (A.rows != B.rows && A.column != B.column)
1486 {
1487 //cout << "The Matrix Dimensions are not equal to Compute ! \n";
1488 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "solveMatrixAddition() Failed !, The Matrix Dimensions are not equal to Compute ! %i != %i.", A.rows,B.rows);
1489 ✗ logfile << "| error | " << "solveMatrixAddition() Failed !, The Matrix Dimensions are not equal to Compute" << A.rows << " != " << B.rows << "\n";
1490 ✗ logfile.close();
1491 ✗ createErrorHtmlReport(data);
1492 ✗ exit(1);
1493 }
1494
1495 //printColumnAlginment(A.data,A.rows,A.column,"A-Matrix");
1496 //printColumnAlginment(B.data,B.rows,B.column,"B-Matrix");
1497
1498 // Add the elements in cloumn major
1499 ✗ for (int i = 0; i < A.rows * A.column; i++)
1500 {
1501 ✗ result[i] = A.data[i] + B.data[i];
1502 }
1503 matrixData tmpadd_a_b = {A.rows, A.column, result};
1504 ✗ return tmpadd_a_b;
1505 }
1506
1507 /*
1508 * Function which Calculates the Matrix Multiplication
1509 * of (Sx*Ft)*Fstar
1510 */
1511 ✗ matrixData Calculate_Sx_Ft_Fstar(matrixData Sx, matrixData Ft, matrixData Fstar, ofstream &logfile, DATA * data)
1512 {
1513 // Sx*Ft
1514 ✗ double *tmpMatrixA = (double*) calloc(Sx.rows * Ft.column, sizeof(double));
1515 ✗ solveMatrixMultiplication(Sx.data, Ft.data, Sx.rows, Sx.column, Ft.rows, Ft.column, tmpMatrixA, logfile, data);
1516 //printMatrix1(tmpMatrixA,Sx.rows,Ft.column,"Reconciled-(Sx*Ft)");
1517 //printMatrix1(Fstar.data,Fstar.rows,Fstar.column,"REconciled-FStar");
1518
1519 //(Sx*Ft)*Fstar
1520 ✗ double *tmpMatrixB = (double*) calloc(Sx.rows * Fstar.column, sizeof(double));
1521 ✗ solveMatrixMultiplication(tmpMatrixA, Fstar.data, Sx.rows, Ft.column, Fstar.rows, Fstar.column, tmpMatrixB, logfile, data);
1522 matrixData rhsdata = {Sx.rows, Fstar.column, tmpMatrixB};
1523
1524 ✗ free(tmpMatrixA);
1525 ✗ free(tmpMatrixB);
1526 ✗ return rhsdata;
1527 }
1528
1529 /*
1530 * Solves the system
1531 * recon_x = x - (Sx*Ft*fstar)
1532 */
1533 ✗ matrixData solveReconciledX(matrixData x, matrixData Sx, matrixData Ft, matrixData Fstar, ofstream &logfile, DATA * data)
1534 {
1535 // Sx*Ft
1536 ✗ double *tmpMatrixAf = (double*) calloc(Sx.rows * Ft.column, sizeof(double));
1537 ✗ solveMatrixMultiplication(Sx.data, Ft.data, Sx.rows, Sx.column, Ft.rows, Ft.column, tmpMatrixAf, logfile, data);
1538 //printMatrix(tmpMatrixAf,Sx.rows,Ft.column,"Sx*Ft");
1539
1540 //(Sx*Ft)*fstar
1541 ✗ double *tmpMatrixBf = (double*) calloc(Sx.rows * Fstar.column, sizeof(double));
1542 ✗ solveMatrixMultiplication(tmpMatrixAf, Fstar.data, Sx.rows, Ft.column, Fstar.rows, Fstar.column, tmpMatrixBf, logfile, data);
1543 //printMatrix(tmpMatrixBf,Sx.rows,Fstar.column,"(Sx*Ft*fstar)");
1544
1545 ✗ matrixData rhs = {Sx.rows, Fstar.column, tmpMatrixBf};
1546 //matrixData rhs = Calculate_Sx_Ft_Fstar(Sx, Ft, Fstar, data);
1547
1548 ✗ double *reconciledX = (double*) calloc(x.rows * x.column, sizeof(double));
1549 ✗ solveMatrixSubtraction(x, rhs, reconciledX, logfile, data);
1550 //printMatrix(reconciledX,x.rows,x.column,"reconciled X^cap ===> (x - (Sx*Ft*fstar))");
1551
1552 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
1553 {
1554 ✗ logfile << "Calculations of Reconciled_x ==> (x - (Sx*Ft*f*))" << "\n";
1555 ✗ logfile << "====================================================";
1556 ✗ printMatrix(tmpMatrixAf, Sx.rows, Ft.column, "Sx*Ft", logfile);
1557 ✗ printMatrix(tmpMatrixBf, Sx.rows, Fstar.column, "(Sx*Ft*f*)", logfile);
1558 ✗ printMatrix(reconciledX, x.rows, x.column, "x - (Sx*Ft*f*))", logfile);
1559 ✗ logfile << "***** Completed ****** \n\n";
1560 }
1561 matrixData recon_x = {x.rows, x.column, reconciledX};
1562 //free(reconciledX);
1563 ✗ free(tmpMatrixAf);
1564 ✗ free(tmpMatrixBf);
1565 ✗ return recon_x;
1566 }
1567
1568 /*
1569 * Solves the system
1570 * recon_Sx = Sx - (Sx*Ft*Fstar)
1571 */
1572 ✗ matrixData solveReconciledSx(matrixData Sx, matrixData Ft, matrixData Fstar, ofstream &logfile, DATA * data)
1573 {
1574 // Sx*Ft
1575 ✗ double *tmpMatrixA = (double*) calloc(Sx.rows * Ft.column, sizeof(double));
1576 ✗ solveMatrixMultiplication(Sx.data, Ft.data, Sx.rows, Sx.column, Ft.rows, Ft.column, tmpMatrixA, logfile, data);
1577 //printMatrix(tmpMatrixA,Sx.rows,Ft.column,"Reconciled-(Sx*Ft)");
1578 //printMatrix(Fstar.data,Fstar.rows,Fstar.column,"REconciled-FStar");
1579
1580 //(Sx*Ft)*Fstar
1581 ✗ double *tmpMatrixB = (double*) calloc(Sx.rows * Fstar.column, sizeof(double));
1582 ✗ solveMatrixMultiplication(tmpMatrixA, Fstar.data, Sx.rows, Ft.column, Fstar.rows, Fstar.column, tmpMatrixB, logfile, data);
1583 //printMatrix(tmpMatrixB,Sx.rows,Fstar.column,"Reconciled-(Sx*Ft*Fstar)");
1584
1585 ✗ matrixData rhs = {Sx.rows, Fstar.column, tmpMatrixB};
1586 //matrixData rhs = Calculate_Sx_Ft_Fstar(Sx, Ft, Fstar, data);
1587
1588 ✗ double *reconciledSx = (double*) calloc(Sx.rows * Sx.column, sizeof(double));
1589 ✗ solveMatrixSubtraction(Sx, rhs, reconciledSx, logfile, data);
1590 //printMatrix(reconciledSx,Sx.rows,Sx.column,"reconciled Sx ===> (Sx - (Sx*Ft*Fstar))");
1591
1592 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
1593 {
1594 ✗ logfile << "Calculations of Reconciled_Sx ===> (Sx - (Sx*Ft*F*))" << "\n";
1595 ✗ logfile << "============================================";
1596 ✗ printMatrix(tmpMatrixA, Sx.rows, Ft.column, "(Sx*Ft)", logfile);
1597 ✗ printMatrix(tmpMatrixB, Sx.rows, Fstar.column, "(Sx*Ft*F*)", logfile);
1598 ✗ printMatrix(reconciledSx, Sx.rows, Sx.column, "Sx - (Sx*Ft*F*))", logfile);
1599 ✗ logfile << "***** Completed ****** \n\n";
1600 }
1601 matrixData recon_sx = {Sx.rows, Sx.column, reconciledSx};
1602 //free(reconciledSx);
1603 ✗ free(tmpMatrixA);
1604 ✗ free(tmpMatrixB);
1605 ✗ return recon_sx;
1606 }
1607
1608 /*
1609 * Function Which Computes the
1610 * Jacobian Matrix F
1611 */
1612 ✗ matrixData getJacobianMatrixF(DATA * data, threadData_t * threadData, ofstream & logfile, bool boundaryConditions = false)
1613 {
1614 // initialize the jacobian call
1615 ✗ const int index = data->callback->INDEX_JAC_F;
1616 ✗ JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
1617 ✗ data->callback->initialAnalyticJacobianF(data, threadData, jacobian);
1618 ✗ int cols = jacobian->sizeCols;
1619 ✗ int rows = jacobian->sizeRows;
1620 ✗ if (cols == 0)
1621 {
1622 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Cannot Compute Jacobian Matrix F");
1623 ✗ logfile << "| error | " << "Cannot Compute Jacobian Matrix F" << "\n";
1624 ✗ logfile.close();
1625 ✗ if (!boundaryConditions)
1626 {
1627 ✗ createErrorHtmlReport(data);
1628 }
1629 else
1630 {
1631 ✗ createErrorHtmlReportForBoundaryConditions(data);
1632 }
1633 ✗ exit(1);
1634 }
1635 ✗ double *jacF = (double*) calloc(rows * cols, sizeof(double)); // allocate for Matrix F
1636 int k = 0;
1637 ✗ for (int x = 0; x < cols; x++)
1638 {
1639 ✗ jacobian->seedVars[x] = 1.0;
1640 ✗ data->callback->functionJacF_column(data, threadData, jacobian, NULL);
1641 //cout << "Calculate one column\n:";
1642 ✗ for (int y = 0; y < rows; y++)
1643 {
1644 ✗ jacF[k++] = jacobian->resultVars[y];
1645 }
1646 ✗ jacobian->seedVars[x] = 0.0;
1647 }
1648 matrixData Fdata = {rows, cols, jacF};
1649 // free the allocated seed and result variables in jacobian struct after computing the jacobian matrix F to avoid memory leak
1650 ✗ freeJacobian(jacobian);
1651 ✗ return Fdata;
1652 }
1653
1654 /*
1655 * Function Which Computes the
1656 * Jacobian Matrix H
1657 */
1658 ✗ matrixData getJacobianMatrixH(DATA * data, threadData_t * threadData, ofstream & logfile, bool boundaryConditions = false)
1659 {
1660 // initialize the jacobian call
1661 ✗ const int index = data->callback->INDEX_JAC_H;
1662 ✗ JACOBIAN *jacobian = &(data->simulationInfo->analyticJacobians[index]);
1663 ✗ data->callback->initialAnalyticJacobianH(data, threadData, jacobian);
1664 ✗ int cols = jacobian->sizeCols;
1665 ✗ int rows = jacobian->sizeRows;
1666 //std::cout << "\n check jacobian H :" << rows << "==>" << cols;
1667 ✗ if (cols == 0)
1668 {
1669 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Cannot Compute Jacobian Matrix H");
1670 ✗ logfile << "| error | " << "Cannot Compute Jacobian Matrix H" << "\n";
1671 ✗ logfile.close();
1672 ✗ if (!boundaryConditions)
1673 {
1674 ✗ createErrorHtmlReport(data);
1675 }
1676 else
1677 {
1678 ✗ createErrorHtmlReportForBoundaryConditions(data);
1679 }
1680 ✗ exit(1);
1681 }
1682 ✗ double *jacF = (double*) calloc(rows * cols, sizeof(double)); // allocate for Matrix F
1683 int k = 0;
1684 ✗ for (int x = 0; x < cols; x++)
1685 {
1686 ✗ jacobian->seedVars[x] = 1.0;
1687 ✗ data->callback->functionJacH_column(data, threadData, jacobian, NULL);
1688 //cout << "Calculate one column\n:";
1689 ✗ for (int y = 0; y < rows; y++)
1690 {
1691 ✗ jacF[k++] = jacobian->resultVars[y];
1692 }
1693 ✗ jacobian->seedVars[x] = 0.0;
1694 }
1695 matrixData Fdata = {rows, cols, jacF};
1696 // free the allocated seed and result variables in jacobian struct after computing the jacobian matrix F to avoid memory leak
1697 ✗ freeJacobian(jacobian);
1698 ✗ return Fdata;
1699 }
1700
1701 /*
1702 * Function Which Computes the
1703 * Transpose of Jacobian Matrix FT
1704 */
1705 ✗ matrixData getTransposeMatrix(matrixData jacF)
1706 {
1707 int rows = jacF.column;
1708 int cols = jacF.rows;
1709 ✗ double *jacFT = (double*) calloc(rows * cols, sizeof(double)); // allocate for Matrix F-transpose
1710 int k = 0;
1711 ✗ for (int i = 0; i < jacF.rows; i++)
1712 {
1713 ✗ for (int j = 0; j < jacF.column; j++)
1714 {
1715 // Perform matrix transpose store the elements in column major
1716 //cout << (i1*jacF.rows+j1) << " index :" << (i1+j1*jacF.rows) << " value is: " << jacF.data[i1+j1*jacF.rows] << "\n";
1717 ✗ jacFT[k++] = jacF.data[i + j * jacF.rows];
1718
1719 }
1720 }
1721 matrixData Ft_data = {rows, cols, jacFT};
1722 ✗ return Ft_data;
1723 }
1724
1725 /*
1726 * Function which reads the vector
1727 * and assign to c pointer arrays
1728 */
1729 ✗ matrixData getCovarianceMatrixSx(csvData Sx_result, DATA *data, threadData_t *threadData)
1730 {
1731 ✗ double *tempSx = (double*) calloc(Sx_result.rowcount * Sx_result.columncount, sizeof(double));
1732 ✗ initColumnMatrix(Sx_result.sxdata, Sx_result.rowcount, Sx_result.columncount, tempSx);
1733 ✗ matrixData Sx_data = {Sx_result.rowcount, Sx_result.columncount, tempSx};
1734 ✗ return Sx_data;
1735 }
1736
1737 /*
1738 * function which validates corelation inputs
1739 * and displays error messages for
1740 * user error #7: variable of interest has multiple entry in measurement input file
1741 * user error #8: variable of interest in correlation input file does not correspond to variable of interest
1742 */
1743 ✗ void validateCorelationInputs(csvData Sx_result, DATA * data, ofstream &logfile, vector<string> headers, string comments, bool boundaryConditions = false)
1744 {
1745 vector<string> noEntry, multipleEntry, entry;
1746 ✗ for (int i = 0; i < headers.size(); i++)
1747 {
1748 bool flag = false;
1749 ✗ for (int j = 0; j < Sx_result.headers.size(); j++)
1750 {
1751 ✗ if (strcmp(headers[i].c_str(), Sx_result.headers[j].c_str()) == 0)
1752 {
1753 //std::cout << "\n matched variables of interest: "<< headers[i] << " => " << Sx_result.headers[j] << " pos: " << j << "\n";
1754 flag = true;
1755 ✗ auto it = find(entry.begin(), entry.end(), headers[i]);
1756 ✗ if (it != entry.end())
1757 {
1758 //std::cout << "Element found in myvector: " << headers[i] << "\n";
1759 ✗ multipleEntry.push_back(headers[i]);
1760 }
1761 else
1762 {
1763 ✗ entry.push_back(headers[i]);
1764 }
1765 }
1766 }
1767
1768 // user error variable of interest in correlation input file does not correspond to variable of interest
1769 ✗ if (!flag)
1770 {
1771 ✗ noEntry.push_back(headers[i]);
1772 }
1773 }
1774
1775 // dump user error #7: variable of interest , has multiple entry in measurement input file
1776 ✗ for (int i = 0; i < multipleEntry.size(); i++)
1777 {
1778 ✗ if (!boundaryConditions)
1779 {
1780 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, at %s has multiple entries in correlation input file %s ", multipleEntry[i].c_str(), comments.c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1781 ✗ logfile << "| error | " << "variable of interest " << multipleEntry[i] << " at " << comments << " has multiple entries in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << "\n";
1782 }
1783 else
1784 {
1785 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, at %s has multiple entries in reconciled covariance matrix input file %s ", multipleEntry[i].c_str(), comments.c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1786 ✗ logfile << "| error | " << "variable of interest " << multipleEntry[i] << " at " << comments << " has multiple entries in reconciled covariance matrix input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << "\n";
1787 }
1788 }
1789
1790 // dump user error #8: variable of interest in correlation input file does not correspond to variable of interest
1791 ✗ for (int i = 0; i < noEntry.size(); i++)
1792 {
1793 ✗ if (!boundaryConditions)
1794 {
1795 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, at %s entry in correlation input file %s does not correspond to a variable of interest ", noEntry[i].c_str(), comments.c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1796 ✗ logfile << "| error | " << "variable of interest " << noEntry[i] << ", at " << comments << " entry in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " does not correspond to a variable of interest" << "\n";
1797 }
1798 else
1799 {
1800 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, at %s entry in reconciled covariance matrix input file %s does not correspond to a variable of interest ", noEntry[i].c_str(), comments.c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1801 ✗ logfile << "| error | " << "variable of interest " << noEntry[i] << ", at " << comments << " entry in reconciled covariance matrix input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " does not correspond to a variable of interest" << "\n";
1802 }
1803 }
1804
1805 ✗ if (!noEntry.empty() || !multipleEntry.empty())
1806 {
1807 ✗ logfile.close();
1808 ✗ if (!boundaryConditions)
1809 {
1810 ✗ createErrorHtmlReport(data);
1811 }
1812 else
1813 {
1814 ✗ createErrorHtmlReportForBoundaryConditions(data);
1815 }
1816 ✗ exit(1);
1817 }
1818 ✗ }
1819
1820 /*
1821 * function which validates corelation inputs is
1822 * square matrix or not and displays error messages for
1823 * user error #10: Lines and columns are in different orders
1824 */
1825 ✗ void validateCorelationInputsSquareMatrix(DATA * data, ofstream &logfile, vector<string> rowHeaders, vector<string> columnHeaders, bool boundaryConditions = false)
1826 {
1827 ✗ if (rowHeaders != columnHeaders)
1828 {
1829 ✗ if (!boundaryConditions)
1830 {
1831 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Lines and columns of correlation matrix in correlation input file %s, do not have identical names in the same order.", omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1832 ✗ logfile << "| error | " << "Lines and columns of correlation matrix in correlation input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " do not have identical names in the same order." << "\n";
1833 }
1834 else
1835 {
1836 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Lines and columns of covariance matrix in reconciled covariance matrix input file %s, do not have identical names in the same order.", omc_flagValue[FLAG_DATA_RECONCILE_Cx]);
1837 ✗ logfile << "| error | " << "Lines and columns of covariance matrix in reconciled covariance matrix input file " << omc_flagValue[FLAG_DATA_RECONCILE_Cx] << " do not have identical names in the same order." << "\n";
1838 }
1839
1840 // user error #10: missing line headers
1841 ✗ for (const auto & index : columnHeaders)
1842 {
1843 ✗ auto it = std::find(rowHeaders.begin(), rowHeaders.end(), index);
1844 ✗ if (it == rowHeaders.end())
1845 {
1846 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Line %s is missing", index.c_str());
1847 ✗ logfile << "| error | " << "Line " << index << " is missing " << "\n";
1848 }
1849 }
1850
1851 // user error #10 : missing column headers
1852 ✗ for (const auto & index : rowHeaders)
1853 {
1854 ✗ auto it = find(columnHeaders.begin(), columnHeaders.end(), index);
1855 ✗ if (it == columnHeaders.end())
1856 {
1857 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Column %s is missing", index.c_str());
1858 ✗ logfile << "| error | " << "Column " << index << " is missing " << "\n";
1859 }
1860 }
1861
1862 // user error #10 : missing line Vs column
1863 ✗ for (int i = 0; i < rowHeaders.size(); i++)
1864 {
1865 //std::cout << "\n " << i << rowHeaders[i] << " Vs " << columnHeaders[i];
1866 ✗ if (rowHeaders[i] != columnHeaders[i])
1867 {
1868 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Lines and columns are in different orders %s Vs %s", rowHeaders[i].c_str(), columnHeaders[i].c_str());
1869 ✗ logfile << "| error | " << "Lines and columns are in different orders " << rowHeaders[i] << " Vs " << columnHeaders[i] << "\n";
1870 }
1871 }
1872
1873 ✗ logfile.close();
1874 ✗ if (!boundaryConditions)
1875 {
1876 ✗ createErrorHtmlReport(data);
1877 }
1878 else
1879 {
1880 ✗ createErrorHtmlReportForBoundaryConditions(data);
1881 }
1882 ✗ exit(1);
1883 }
1884 ✗ }
1885
1886 /*
1887 * Function which reads the correlation coefficient input file
1888 * and stores the correlation coefficient matrix Cx for DataReconciliation
1889 */
1890 ✗ correlationData readCorrelationCoefficientFile(csvData Sx_result, ofstream & logfile, DATA * data, threadData_t * threadData, correlationDataWarning & warningCorrelationData, bool boundaryConditions = false)
1891 {
1892 char * filename = NULL;
1893 ✗ filename = (char*) omc_flagValue[FLAG_DATA_RECONCILE_Cx];
1894
1895 vector<string> columnHeaders, rowHeaders;
1896 vector<double> cx_data;
1897 vector<errorData> errorInfo;
1898 correlationData Cx;
1899 vector<int> errorInfoHeaders;
1900
1901 ✗ if (filename == NULL && !boundaryConditions)
1902 {
1903 ✗ Cx = {cx_data, rowHeaders, columnHeaders};
1904 ✗ return Cx;
1905 }
1906
1907 ✗ if (filename == NULL && boundaryConditions)
1908 {
1909 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Reconciled covariance matrix input file not provided (eg:-cx=filename.csv), Boundary conditions cannot be computed!.");
1910 ✗ logfile << "| error | " << "Reconciled covariance matrix input file not provided (eg:-cx=filename.csv), Boundary conditions cannot be computed!.\n";
1911 ✗ logfile.close();
1912 ✗ createErrorHtmlReportForBoundaryConditions(data);
1913 ✗ exit(1);
1914 }
1915
1916 /*
1917 * fix issue https://github.com/OpenModelica/OpenModelica/issues/13797
1918 * check if filepath uses uri format and convert it to absolute path
1919 * eg: modelica://Modelica/Resources/Files/filename.csv => /absolute/path/to/filename.csv
1920 */
1921 ✗ modelica_string uri = OpenModelica_uriToFilename(omc_string_new(filename));
1922 ✗ std::string filenameStr = omc_string_data(uri);
1923
1924 // read the file
1925 ✗ ifstream ip(filenameStr.c_str());
1926 string line;
1927 ✗ if (!ip.good() && !boundaryConditions)
1928 {
1929 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "correlation coefficient input file path not found %s.", filename);
1930 ✗ logfile << "| error | " << "correlation coefficient input file path not found " << filename << "\n";
1931 ✗ logfile.close();
1932 ✗ createErrorHtmlReport(data);
1933 ✗ exit(1);
1934 }
1935
1936 ✗ if (!ip.good() && boundaryConditions)
1937 {
1938 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Reconciled covariance matrix input file path not found %s.", filename);
1939 ✗ logfile << "| error | " << "Reconciled covariance matrix input file path not found " << filename << "\n";
1940 ✗ logfile.close();
1941 ✗ createErrorHtmlReportForBoundaryConditions(data);
1942 ✗ exit(1);
1943 }
1944
1945 ✗ int linecount = 1;
1946 ✗ while (ip.good())
1947 {
1948 ✗ getline(ip, line);
1949 vector<string> t1;
1950 std::replace(line.begin(), line.end(), ';', ',');
1951 // remove whitespace in a string
1952 ✗ line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end());
1953 ✗ stringstream ss(line);
1954 string temp;
1955
1956 // allow comments on the line#1 until finding the headers
1957 ✗ if (linecount == 1 && isLineEmptyData(line))
1958 {
1959 continue;
1960 }
1961
1962 ✗ if (linecount == 1 && !line.empty())
1963 {
1964 int columnCount = 1;
1965 ✗ while (getline(ss, temp, ','))
1966 {
1967 ✗ if (columnCount > 1)
1968 {
1969 //std::cout << "\nreading Column headers : " << temp;
1970 ✗ columnHeaders.push_back(temp);
1971 }
1972 ✗ columnCount++;
1973 }
1974 }
1975 ✗ else if (linecount > 1 && !line.empty() && !isLineEmptyData(line))
1976 {
1977 //std::cout << "\nreading covariance matrix : " << line << " size : " << columnHeaders.size();
1978 int columnCount = 1;
1979 ✗ while (getline(ss, temp, ','))
1980 {
1981 ✗ if (columnCount == 1)
1982 {
1983 // error : no variable of interest is provided by user at column #1
1984 ✗ if (temp.empty())
1985 {
1986 ✗ errorInfoHeaders.push_back(linecount);
1987 }
1988 ✗ rowHeaders.push_back(temp);
1989 }
1990 else
1991 {
1992 //std::cout << "\nreading Column values : " << temp << " : " << columnCount << " value= " << atof(temp.c_str());
1993 ✗ if (temp.empty())
1994 {
1995 ✗ cx_data.push_back(0);
1996 }
1997 ✗ else if (!isStringValidDouble(temp))
1998 {
1999 //std::cout << "\n check wrong type : " << columnCount << " = " << columnHeaders[columnCount-2];
2000 ✗ errorData info = {rowHeaders.back(), columnHeaders[columnCount-2], temp};
2001 ✗ errorInfo.push_back(info);
2002 ✗ }
2003 // warn users if value is closer to 1
2004 ✗ else if (atof(temp.c_str()) > 0.99 && atof(temp.c_str()) < 1.01)
2005 {
2006 ✗ errorData info = {rowHeaders.back(), columnHeaders[columnCount-2], temp};
2007 ✗ warningCorrelationData.warningInfo.push_back(info);
2008 ✗ cx_data.push_back(atof(temp.c_str()));
2009 ✗ }
2010 else
2011 {
2012 ✗ cx_data.push_back(atof(temp.c_str()));
2013 }
2014 }
2015 ✗ columnCount++;
2016 }
2017 ✗ if (columnCount - 2 == columnHeaders.size())
2018 {
2019 // rows and columns have values correctly entered
2020 }
2021 else
2022 {
2023 // just in case, fill the empty rows with zeros
2024 ✗ int count = columnHeaders.size() - (columnCount -2);
2025 ✗ for (int i = 0; i < count; ++i)
2026 {
2027 ✗ cx_data.push_back(0);
2028 }
2029 }
2030 }
2031 ✗ linecount++;
2032 ✗ }
2033
2034 // user error : variable of interest is missing in column #1
2035 ✗ if (!errorInfoHeaders.empty())
2036 {
2037 ✗ for (const auto &line : errorInfoHeaders)
2038 {
2039 ✗ if (!boundaryConditions)
2040 {
2041 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "the name of the variable of interest in correlation input file %s is missing in line #%d ", filename, line);
2042 ✗ logfile << "| error | " << "the name of the variable of interest in correlation input file " << filename << " is missing in line #" << line << "\n";
2043 }
2044 else
2045 {
2046 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "the name of the variable of interest in reconciled covariance matrix input file %s is missing in line #%d ", filename, line);
2047 ✗ logfile << "| error | " << "the name of the variable of interest in reconciled covariance matrix input file " << filename << " is missing in line #" << line << "\n";
2048 }
2049 }
2050 ✗ logfile.close();
2051 ✗ if (!boundaryConditions)
2052 {
2053 ✗ createErrorHtmlReport(data);
2054 }
2055 else
2056 {
2057 ✗ createErrorHtmlReportForBoundaryConditions(data);
2058 }
2059 ✗ exit(1);
2060 }
2061
2062 // user error #9: Entry for variable of interest <variable name> and variable of interest <variable name> in correlation input file <input file name> is incorrect: incorrect value type.
2063 ✗ if (!errorInfo.empty())
2064 {
2065 ✗ for (const auto & info : errorInfo)
2066 {
2067 ✗ if (!boundaryConditions)
2068 {
2069 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Entry for variable of interest %s and variable of interest %s in correlation input file %s is incorrect because of wrong-Type: [%s] ", info.name.c_str(), info.x.c_str(), filename, info.sx.c_str());
2070 ✗ logfile << "| error | " << "Entry for variable of interest " << info.name << " and variable of interest " << info.x << " in correlation input file " << filename << " is incorrect because of wrong-Type: " << "[" << info.sx << "]" <<"\n";
2071 }
2072 else
2073 {
2074 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Entry for variable of interest %s and variable of interest %s in reconciled covariance matrix input file %s is incorrect because of wrong-Type: [%s] ", info.name.c_str(), info.x.c_str(), filename, info.sx.c_str());
2075 ✗ logfile << "| error | " << "Entry for variable of interest " << info.name << " and variable of interest " << info.x << " in reconciled covariance matrix input file " << filename << " is incorrect because of wrong-Type: " << "[" << info.sx << "]" <<"\n";
2076 }
2077 }
2078 ✗ logfile.close();
2079 ✗ if (!boundaryConditions)
2080 {
2081 ✗ createErrorHtmlReport(data);
2082 }
2083 else
2084 {
2085 ✗ createErrorHtmlReportForBoundaryConditions(data);
2086 }
2087 ✗ exit(1);
2088 }
2089
2090 // user warning : Entry for variable of interest <variable name> and variable of interest <variable name> in correlation input file <input file name> is closer to 1.
2091 ✗ if (!warningCorrelationData.warningInfo.empty())
2092 {
2093 ✗ for (const auto & info : warningCorrelationData.warningInfo)
2094 {
2095 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0, "Entry for variable of interest %s and variable of interest %s in correlation input file %s is closer to 1: [%s] ", info.name.c_str(), info.x.c_str(), filename, info.sx.c_str());
2096 }
2097 }
2098
2099 // validate correlation input column headers
2100 ✗ validateCorelationInputs(Sx_result, data, logfile, columnHeaders, "column headers", boundaryConditions);
2101
2102 // validate correlation input column headers
2103 ✗ validateCorelationInputs(Sx_result, data, logfile, rowHeaders, "row headers", boundaryConditions);
2104
2105 // check for square matrix
2106 ✗ validateCorelationInputsSquareMatrix(data, logfile, rowHeaders, columnHeaders, boundaryConditions);
2107
2108 ✗ Cx = {cx_data, rowHeaders, columnHeaders};
2109
2110 return Cx;
2111 ✗ }
2112
2113
2114 /*
2115 * Function which Computes
2116 * covariance matrix Sx based on
2117 * Half width confidence interval provided by user (i.e) csvData.sxdata
2118 * Sx=(Wxi/1.96)^2
2119 */
2120 ✗ matrixData computeCovarianceMatrixSx(csvData Sx_result, correlationData Cx_data, ofstream &logfile, DATA * data)
2121 {
2122 ✗ double *tempSx = (double*) calloc(Sx_result.sxdata.size() * Sx_result.sxdata.size(), sizeof(double));
2123 vector<double> tmpdata;
2124 int k = 0;
2125
2126 ✗ for (unsigned int i = 0; i < Sx_result.sxdata.size(); i++)
2127 {
2128 ✗ double data = pow(Sx_result.sxdata[k] / 1.96, 2);
2129 ✗ for (unsigned int j = 0; j < Sx_result.sxdata.size(); j++)
2130 {
2131 ✗ if (i == j)
2132 {
2133 //tmpdata.push_back(pow(Sx_result.sxdata[k]/1.96,2));
2134 //k++;
2135 ✗ tmpdata.push_back(data);
2136 }
2137 else
2138 {
2139 ✗ tmpdata.push_back(0);
2140 }
2141 // logfile << " data " << count << "=="<< tmpdata[count++] << "\n";
2142 }
2143 ✗ k++;
2144 }
2145
2146 // check for correlation coefficient Cx_data is not empty and recompute the covariance matrix
2147 ✗ if (! Cx_data.data.empty())
2148 {
2149 ✗ for (int i = 0; i < Cx_data.rowHeaders.size(); i++)
2150 {
2151 ✗ for (int j = 0; j < Cx_data.columnHeaders.size(); j++)
2152 {
2153 // consider the values which are strictly below the diagonal entry
2154 ✗ if (j < i && Cx_data.data[Cx_data.columnHeaders.size() * i + j] != 0)
2155 {
2156 //std::cout << "\n value : " << Cx_data.rowHeaders[i] << "=" << Cx_data.data[columnHeaders.size() * i + j];
2157 ✗ int rowpos = getVariableIndex(Sx_result.headers, Cx_data.rowHeaders[i], logfile, data);
2158 ✗ int colpos = getVariableIndex(Sx_result.headers, Cx_data.columnHeaders[j], logfile, data);
2159
2160 ✗ double xi = tmpdata[(Sx_result.rowcount * rowpos) + rowpos];
2161 ✗ double xk = tmpdata[(Sx_result.rowcount * colpos) + colpos];
2162
2163 //std::cout << "\n row pos : " << rowpos << " col pos: " << colpos << " xi " << xi;
2164 ✗ double tmprx = Cx_data.data[Cx_data.columnHeaders.size() * i + j] * sqrt(xi) * sqrt(xk);
2165
2166 // find the symmetric position and insert the elements
2167 ✗ tmpdata[(Sx_result.rowcount * rowpos) + colpos] = tmprx;
2168 ✗ tmpdata[(Sx_result.rowcount * colpos) + rowpos] = tmprx;
2169 }
2170 }
2171 }
2172 }
2173
2174 ✗ initColumnMatrix(tmpdata, Sx_result.rowcount, Sx_result.rowcount, tempSx);
2175 ✗ matrixData Sx_data = {Sx_result.rowcount, Sx_result.rowcount, tempSx};
2176 ✗ return Sx_data;
2177 }
2178
2179 /*
2180 * function which validates the inputs read from measurement input file
2181 * and validates (i.e) all the variables of interest in input file = all variables of interest in model
2182 * and displays error message if the above condition fails.
2183 * Also it perform internal mapping to sort the variable of interest in input file to match with variables of interest in model
2184 * which is very important for jacobians and also to get correct numerical results
2185 */
2186
2187 ✗ csvData validateMeasurementInputs(csvData Sx_result, DATA * data, ofstream &logfile, bool boundaryConditions = false)
2188 {
2189 ✗ if (data->modelData->ndataReconVars != Sx_result.headers.size())
2190 {
2191 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "invalid input file %s, number of variable of interest(%li) != (%zu)number of variables in measurement input file", omc_flagValue[FLAG_DATA_RECONCILE_Sx], data->modelData->ndataReconVars, Sx_result.headers.size());
2192 ✗ logfile << "| error | " << "invalid input file "<< omc_flagValue[FLAG_DATA_RECONCILE_Sx] << ", number of variable of interest(" << data->modelData->ndataReconVars << ")" << " != " << "(" << Sx_result.headers.size() << ")" << "number of variables in measurement input file";
2193 ✗ logfile.close();
2194 ✗ if (!boundaryConditions)
2195 {
2196 ✗ createErrorHtmlReport(data);
2197 }
2198 else
2199 {
2200 ✗ createErrorHtmlReportForBoundaryConditions(data);
2201 }
2202 ✗ exit(1);
2203 }
2204
2205 ✗ char **knowns = (char**) malloc(data->modelData->ndataReconVars * sizeof(char*));
2206 ✗ data->callback->dataReconciliationInputNames(data, knowns);
2207
2208 vector<string> noEntry, multipleEntry;
2209 vector<int> mapindex;
2210 ✗ for (int i = 0; i < data->modelData->ndataReconVars; i++)
2211 {
2212 bool flag = false;
2213 int count = 0;
2214 ✗ for (int j = 0; j < Sx_result.headers.size(); j++)
2215 {
2216 ✗ if (strcmp(knowns[i], Sx_result.headers[j].c_str()) == 0)
2217 {
2218 //std::cout << "\n matched variables of interest: "<< knowns[i] << " => " << Sx_result.headers[j] << " pos: " << j << " size : " << Sx_result.headers.size() << "\n";
2219 ✗ mapindex.push_back(j);
2220 flag = true;
2221 ✗ count ++;
2222 }
2223 }
2224
2225 // user error variable of interest , has no entry in measurement input file
2226 ✗ if (!flag)
2227 {
2228 ✗ noEntry.push_back(knowns[i]);
2229 }
2230 // user error variable of interest , has multiple entry in measurement input file
2231 ✗ if (count > 1)
2232 {
2233 ✗ multipleEntry.push_back(knowns[i]);
2234 }
2235 }
2236
2237 // dump user error #3: variable of interest, has no entry in measurement input file
2238 ✗ for (int i = 0; i < noEntry.size(); i++)
2239 {
2240 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, has no entry in measurement input file %s ", noEntry[i].c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Sx]);
2241 ✗ logfile << "| error | " << "variable of interest " << noEntry[i] << ", has no entry in measurement input file" << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "\n";
2242 }
2243
2244 // dump user error #4: variable of interest , has multiple entry in measurement input file
2245 ✗ for (int i = 0; i < multipleEntry.size(); i++)
2246 {
2247 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, has multiple entries in measurement input file %s ", multipleEntry[i].c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Sx]);
2248 ✗ logfile << "| error | " << "variable of interest " << multipleEntry[i] << ", has multiple entries in measurement input file " << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << "\n";
2249 }
2250
2251 // dump user error #5 entry in measurement input file does not correspond to a variable of interest
2252 bool userError5 = false;
2253 ✗ for (int i = 0; i < data->modelData->ndataReconVars; i++)
2254 {
2255 ✗ auto it = find(mapindex.begin(), mapindex.end(), i);
2256 ✗ if (it == mapindex.end())
2257 {
2258 //std::cout << "\n not found" << i;
2259 userError5 = true;
2260 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "variable of interest %s, entry in measurement input file %s does not correspond to a variable of interest ", Sx_result.headers[i].c_str(), omc_flagValue[FLAG_DATA_RECONCILE_Sx]);
2261 ✗ logfile << "| error | " << "variable of interest " << Sx_result.headers[i] << ", entry in measurement input file " << omc_flagValue[FLAG_DATA_RECONCILE_Sx] << " does not correspond to a variable of interest" << "\n";
2262 }
2263 }
2264
2265 ✗ if (!noEntry.empty() || !multipleEntry.empty() || userError5)
2266 {
2267 ✗ logfile.close();
2268 ✗ free(knowns);
2269 ✗ if (!boundaryConditions)
2270 {
2271 ✗ createErrorHtmlReport(data);
2272 }
2273 else
2274 {
2275 ✗ createErrorHtmlReportForBoundaryConditions(data);
2276 }
2277 ✗ exit(1);
2278 }
2279
2280 // map csv inputs with order of variable of interest in the model
2281 vector<double> mapped_xdata, mapped_Sxdata;
2282 vector<string> mappedHeader;
2283 ✗ for (const auto & index : mapindex)
2284 {
2285 ✗ mapped_xdata.push_back(Sx_result.xdata[index]);
2286 ✗ mapped_Sxdata.push_back(Sx_result.sxdata[index]);
2287 ✗ mappedHeader.push_back(Sx_result.headers[index]);
2288 }
2289
2290 // assign the mapped order
2291 ✗ Sx_result.xdata = mapped_xdata;
2292 ✗ Sx_result.sxdata = mapped_Sxdata;
2293 ✗ Sx_result.headers = mappedHeader;
2294
2295 ✗ free(knowns);
2296 ✗ return Sx_result;
2297 ✗ }
2298
2299
2300 /*
2301 * Function which reads the input data from csvData.xdata
2302 * and stores the input values in double array
2303 */
2304 ✗ inputData getInputData(csvData Sx_result, ofstream & logfile)
2305 {
2306 ✗ double * tempx = (double*) calloc(Sx_result.rowcount, sizeof(double));
2307 vector<int> index;
2308
2309 ✗ for (int i = 0; i < Sx_result.headers.size(); i++)
2310 {
2311 ✗ tempx[i] = Sx_result.xdata[i];
2312 }
2313
2314 ✗ inputData x_data = {Sx_result.rowcount, 1, tempx, index};
2315 ✗ return x_data;
2316 }
2317
2318 /*
2319 * Function which reads the input data from csvData.xdata
2320 * and stores the input values in double array
2321 * Note: this function takes the output.csv file from data reconciliation
2322 * as input and get the reconciled_X values from third column
2323 */
2324 ✗ inputData getReconciledX(csvData Sx_result, ofstream & logfile)
2325 {
2326 ✗ double * tempx = (double*) calloc(Sx_result.rowcount, sizeof(double));
2327 vector<int> index;
2328
2329 ✗ for (int i = 0; i < Sx_result.headers.size(); i++)
2330 {
2331 ✗ tempx[i] = Sx_result.sxdata[i];
2332 }
2333
2334 ✗ inputData x_data = {Sx_result.rowcount, 1, tempx, index};
2335 ✗ return x_data;
2336 }
2337
2338 /*
2339 * Function which Copy Matrix
2340 * using dcopy_ LAPACK routine
2341 * this is mostly used when LAPACK routines override arrays
2342 */
2343 ✗ matrixData copyMatrix(matrixData matdata)
2344 {
2345 ✗ double *tmpcopymatrix = (double*) calloc(matdata.rows * matdata.column, sizeof(double));
2346 ✗ int n = matdata.rows * matdata.column;
2347 ✗ int inc = 1;
2348 ✗ dcopy_(&n, matdata.data, &inc, tmpcopymatrix, &inc);
2349
2350 // for (int i=0; i < matdata.rows*matdata.column; i++)
2351 // {
2352 // tmpcopymatrix[i]=matdata.data[i];
2353 // }
2354 matrixData tmpcopymatrixdata = {matdata.rows, matdata.column, tmpcopymatrix};
2355 ✗ return tmpcopymatrixdata;
2356 }
2357
2358 /*
2359 * Function which scales the MAtrix with constant
2360 * dscal_ LAPACK_routine and result is updated in data
2361 * eg: alpha = 2, data=[2,4,5]
2362 * result = [4,8,10]
2363 */
2364 ✗ void scaleVector(int rows, int cols, double alpha, double *data)
2365 {
2366 ✗ int n = rows * cols;
2367 ✗ int inc = 1;
2368 ✗ dscal_(&n, &alpha, data, &inc);
2369 ✗ }
2370
2371 /*
2372 * Function which calculates the square root of elements
2373 * eg : a=[1,2,3,4]
2374 * result a = [srt(1),sqrt(2).......]
2375 */
2376 ✗ void calculateSquareRoot(double *data, int length)
2377 {
2378 ✗ for (int i = 0; i < length; i++)
2379 {
2380 ✗ data[i] = sqrt(data[i]);
2381 }
2382 ✗ }
2383
2384 /*
2385 * Function which calculates
2386 * J*=(recon_x-x)T*(Sx^-1)*(recon_x-x)+2.[f+F*(recon_x-x)]T*fstar
2387 * where T= transpose of matrix
2388 * and returns the converged value
2389 */
2390 ✗ double solveConvergence(DATA *data, matrixData conv_recon_x, matrixData conv_recon_sx, inputData conv_x, matrixData conv_sx, matrixData conv_jacF, matrixData conv_vector_c, matrixData conv_fstar, ofstream &logfile)
2391 {
2392
2393 //printMatrix(conv_vector_c.data,conv_vector_c.rows,conv_vector_c.column,"Convergence_C(x,y)");
2394 //printMatrix(conv_fstar.data,conv_fstar.rows,conv_fstar.column,"Convergence_f*");
2395 //printMatrix(conv_recon_x.data,conv_recon_x.rows,conv_recon_x.column,"check_recon_x*");
2396
2397 // calculate(recon_x-x)
2398 ✗ double *conv_data1 = (double*) calloc(conv_x.rows * conv_x.column, sizeof(double));
2399 ✗ matrixData conv_inputs = {conv_x.rows, conv_x.column, conv_x.data};
2400 ✗ solveMatrixSubtraction(conv_recon_x, conv_inputs, conv_data1, logfile, data);
2401 ✗ matrixData conv_data1result = {conv_x.rows, conv_x.column, conv_data1};
2402 ✗ matrixData copy_reconx_x = copyMatrix(conv_data1result);
2403
2404 //printMatrix(conv_inputs.data,conv_inputs.rows,conv_inputs.column,"check_inputs");
2405 //printMatrix(conv_data1result.data,conv_data1result.rows,conv_data1result.column,"(recon_X - X)");
2406
2407 // calculate Transpose_(recon_x-x)
2408 ✗ matrixData conv_data1Transpose = getTransposeMatrix(conv_data1result);
2409 //printMatrix(conv_data1Transpose.data,conv_data1Transpose.rows,conv_data1Transpose.column,"Transpose(recon_X - X)");
2410
2411 /* solves (Sx^-1)*(recon_x-x)
2412 * Solve the inverse of matrix Sx using linear form
2413 * Ax=b
2414 * where A=Sx and b= (recon_x-x) to avoid inversion of Sx which is
2415 * expensive
2416 */
2417 ✗ solveSystemFstar(conv_sx.rows, 1, conv_sx.data, conv_data1result.data, logfile, data);
2418 //printMatrix(conv_data1result.data,conv_sx.rows,conv_data1result.column,"inverse multiplication_without inverse");
2419
2420 ✗ double *conv_tmpmatrixlhs = (double*) calloc(conv_data1Transpose.rows * conv_data1result.column, sizeof(double));
2421 /*
2422 * Solve (recon_x-x)T*(Sx^-1)*(recon_x-x)
2423 */
2424 ✗ solveMatrixMultiplication(conv_data1Transpose.data, conv_data1result.data, conv_data1Transpose.rows, conv_data1Transpose.column, conv_data1result.rows, conv_data1result.column, conv_tmpmatrixlhs, logfile, data);
2425 //printMatrix(conv_tmpmatrixlhs,conv_data1Transpose.rows,conv_data1result.column,"(recon_x-x)T*(Sx^-1)*(recon_x-x)");
2426 ✗ matrixData struct_conv_tmpmatrixlhs = {conv_data1Transpose.rows, conv_data1result.column, conv_tmpmatrixlhs};
2427
2428 /*
2429 * Solve rhs = 2.[f+F*(recon_x-x)]T*fstar
2430 *
2431 */
2432 // Calculate F*(recon_x-x)
2433 ✗ double *tmp_F_recon_x_x = (double*) calloc(conv_jacF.rows * copy_reconx_x.column, sizeof(double));
2434 ✗ solveMatrixMultiplication(conv_jacF.data, copy_reconx_x.data, conv_jacF.rows, conv_jacF.column, copy_reconx_x.rows, copy_reconx_x.column, tmp_F_recon_x_x, logfile, data);
2435 //printMatrix(tmp_F_recon_x_x,conv_jacF.rows,copy_reconx_x.column,"F*(recon_x-x)");
2436 ✗ matrixData mult_F_recon_x_x = {conv_jacF.rows, copy_reconx_x.column, tmp_F_recon_x_x};
2437
2438 // Calculate f + F*(recon_x-x)
2439 ✗ matrixData add_f_F_recon_x_x = solveMatrixAddition(conv_vector_c, mult_F_recon_x_x, logfile, data);
2440 //printMatrix(add_f_F_recon_x_x.data,add_f_F_recon_x_x.rows,add_f_F_recon_x_x.column,"f + F*(recon_x-x)");
2441
2442 ✗ matrixData transpose_add_f_F_recon_x_x = getTransposeMatrix(add_f_F_recon_x_x);
2443 //printMatrix(transpose_add_f_F_recon_x_x.data,transpose_add_f_F_recon_x_x.rows,transpose_add_f_F_recon_x_x.column,"transpose-[f + F*(recon_x-x)]");
2444
2445 // calculate [f + F*(recon_x-x)]T*fstar
2446 ✗ double *conv_tmpmatrixrhs = (double*) calloc(transpose_add_f_F_recon_x_x.rows * conv_fstar.column, sizeof(double));
2447 ✗ solveMatrixMultiplication(transpose_add_f_F_recon_x_x.data, conv_fstar.data, transpose_add_f_F_recon_x_x.rows, transpose_add_f_F_recon_x_x.column, conv_fstar.rows, conv_fstar.column, conv_tmpmatrixrhs, logfile, data);
2448 //printMatrix(conv_tmpmatrixrhs, transpose_add_f_F_recon_x_x.rows, conv_fstar.column,"[f + F*(recon_x-x)]*fstar");
2449
2450 // scale the matrix with 2*[f + F*(recon_x-x)]T*fstar
2451 ✗ scaleVector(transpose_add_f_F_recon_x_x.rows, conv_fstar.column, 2.0, conv_tmpmatrixrhs);
2452 //printMatrix(conv_tmpmatrixrhs, transpose_add_f_F_recon_x_x.rows, conv_fstar.column,"2*[f + F*(recon_x-x)]*fstar");
2453 ✗ matrixData struct_conv_tmpmatrixrhs = {transpose_add_f_F_recon_x_x.rows, conv_fstar.column, conv_tmpmatrixrhs};
2454
2455 /*
2456 * solve the final J*=J*=(recon_x-x)T*(Sx^-1)*(recon_x-x)+2.[f+F*(recon_x-x)]T*fstar
2457 * J*=_struct_conv_tmpmatrixlhs + struct_conv_tmpmatrixrhs
2458 */
2459 ✗ matrixData struct_Jstar = solveMatrixAddition(struct_conv_tmpmatrixlhs, struct_conv_tmpmatrixrhs, logfile, data);
2460 //printMatrix(struct_Jstar.data,struct_Jstar.rows,struct_Jstar.column,"J*",logfile);
2461
2462 ✗ int r = data->modelData->nSetcVars; // number of setc equations
2463 ✗ double val = 1.0 / r;
2464
2465 /*
2466 * calculate J/r < epselon
2467 */
2468 ✗ scaleVector(struct_Jstar.rows, struct_Jstar.column, val, struct_Jstar.data);
2469 //printMatrix(struct_Jstar.data,struct_Jstar.rows,struct_Jstar.column,"J*/r ");
2470 ✗ double convergedvalue = struct_Jstar.data[0];
2471
2472 // free the tmp matrices
2473 ✗ free(conv_data1);
2474 ✗ free(conv_tmpmatrixlhs);
2475 ✗ free(tmp_F_recon_x_x);
2476 ✗ free(conv_tmpmatrixrhs);
2477 ✗ free(add_f_F_recon_x_x.data);
2478 ✗ free(struct_Jstar.data);
2479 ✗ free(conv_data1Transpose.data);
2480 ✗ free(transpose_add_f_F_recon_x_x.data);
2481 //free(conv_recon_x.data);
2482 ✗ free(copy_reconx_x.data);
2483
2484 ✗ return convergedvalue;
2485 }
2486
2487 /*
2488 * function which calculates qualityValue J = transpose (x_reconciled – x_measured)*Sx^-1*(x_reconciled – x_measured)
2489 */
2490 ✗ double calculateQualityValue(matrixData reconciledX, matrixData Sx, csvData measuredX, ofstream & logfile, DATA* data)
2491 {
2492 ✗ logfile << "Calculations of Quality Value (J) " << "\n";
2493 ✗ logfile << "=================================\n";
2494
2495 ✗ printMatrix(reconciledX.data, reconciledX.rows, reconciledX.column, "reconciled_x", logfile);
2496 ✗ inputData measured_x = getInputData(measuredX, logfile);
2497 ✗ printMatrix(measured_x.data, measured_x.rows, measured_x.column, "measured_X", logfile);
2498 ✗ printMatrix(Sx.data, Sx.rows, Sx.column, "Sx", logfile);
2499 ✗ matrixData measured_xCopy = {measured_x.rows, measured_x.column, measured_x.data};
2500 ✗ double *newX = (double*) calloc (measured_x.rows * 1, sizeof(double));
2501 ✗ solveMatrixSubtraction(reconciledX, measured_xCopy, newX, logfile, data);
2502 ✗ printMatrix(newX, measured_x.rows, measured_x.column, "x_reconciled - measured_X", logfile);
2503
2504 /* solves (Sx^-1)*(x_reconciled – x_measured)
2505 * Solve the inverse of matrix Sx using linear form
2506 * Ax=b
2507 * where A=Sx and b= (recon_x-x_measured) to avoid inversion of Sx which is
2508 * expensive
2509 */
2510 //solveSystemFstar(conv_sx.rows, 1, conv_sx.data, conv_data1result.data, logfile, data);
2511 ✗ matrixData sub = {measured_x.rows, measured_x.column, newX};
2512 ✗ matrixData subCopy = copyMatrix(sub);
2513 ✗ solveSystemFstar(Sx.rows, 1, Sx.data, newX, logfile, data);
2514 ✗ printMatrix(newX, measured_x.rows, measured_x.column, "Sx-inverse", logfile);
2515
2516 ✗ matrixData subCopyTranspose = getTransposeMatrix(subCopy);
2517
2518 ✗ double *J = (double*) calloc(subCopyTranspose.rows * measured_x.column, sizeof(double));
2519 /*
2520 * Solve transpose (x_reconciled – x_measured)*Sx^-1*(x_reconciled – x_measured)
2521 */
2522 ✗ solveMatrixMultiplication(subCopyTranspose.data, newX, subCopyTranspose.rows, subCopyTranspose.column, measured_x.rows, measured_x.column, J, logfile, data);
2523 ✗ printMatrix(J, subCopyTranspose.rows, measured_x.column, "J", logfile);
2524
2525 ✗ double J_value = J[0];
2526
2527 // --- Free all temporary allocations ---
2528 ✗ free(newX);
2529 ✗ free(subCopy.data);
2530 ✗ free(subCopyTranspose.data);
2531 ✗ free(measured_x.data);
2532 ✗ free(J);
2533
2534 ✗ return J_value;
2535 }
2536
2537 /*
2538 * Example Function which performs matrix inverse
2539 * using dgetri_ and dgetrf_ LAPACK routine
2540 * which is expensive one and not recommended
2541 * use it when no other way to compute it
2542 */
2543 ✗ void checkExpensiveMatrixInverse()
2544 {
2545 ✗ double newval[3*3]={3,2,0,
2546 0,0,1,
2547 2,-2,1};
2548
2549 ✗ int N = 3;
2550 int LDA = N;
2551 int LDB = N;
2552 int ipiv[3];
2553 ✗ int info = 1;
2554 ✗ int LWORK = N;
2555 ✗ double *WORK = (double*) calloc(LWORK, sizeof(double));
2556
2557 ✗ dgetrf_(&N, &N, newval, &N, ipiv, &info);
2558 ✗ dgetri_(&N, newval, &N, ipiv, WORK, &LWORK, &info);
2559 //printMatrix(newval,3,3,"Expensive_Matrix_Inverse");
2560 ✗ }
2561
2562 /*
2563 * Function which performs matrix inverse without performing
2564 * actual matrix inverse, Instead use the dgesv to get result
2565 * Ax=b where matrix mutiplication of x=bA gives the inversed
2566 * mutiplication result b with A inverse
2567 */
2568 ✗ void checkInExpensiveMatrixInverse(ofstream & logfile, DATA * data)
2569 {
2570 ✗ double newchecksx[3*3]={1,1,1,
2571 0,0.95,0,
2572 0,0,0.95};
2573 ✗ double checksx[3 * 1] = {-0.028, 0.026, -0.004};
2574 ✗ solveSystemFstar(3, 1, newchecksx, checksx, logfile, data);
2575 //printMatrix(checksx,3,1,"InExpensive_Matrix_Inverse");
2576 ✗ }
2577
2578 ✗ int RunReconciliation(DATA *data, threadData_t *threadData, inputData x, matrixData Sx, matrixData tmpjacF, matrixData tmpjacFt, double eps, int iterationcount, csvData csvinputs, matrixData xdiag, matrixData sxdiag, ofstream &logfile, correlationDataWarning & warningCorrelationData, dataReconciliationData& datareconciliationdata)
2579 {
2580 // set the inputs from csv file to simulationInfo datainputVars
2581 ✗ for (int i = 0; i < x.rows * x.column; i++)
2582 {
2583 ✗ data->simulationInfo->datainputVars[i] = x.data[i];
2584 //logfile << "input data:" << x.data[i]<<"\n";
2585 }
2586
2587 /* set the inputs via this special function generated for dataReconciliation
2588 * which also sets inputs for models not involving top level inputs
2589 */
2590 ✗ data->callback->data_function(data, threadData);
2591 //data->callback->input_function(data, threadData);
2592 ✗ data->callback->functionDAE(data, threadData);
2593 //data->callback->functionODE(data,threadData);
2594 ✗ data->callback->setc_function(data, threadData);
2595
2596 //data->callback->setb_function(data, threadData);
2597
2598 ✗ matrixData jacF = getJacobianMatrixF(data, threadData, logfile);
2599 ✗ matrixData jacFt = getTransposeMatrix(jacF);
2600
2601 ✗ printMatrix(jacF.data, jacF.rows, jacF.column, "F", logfile);
2602 ✗ printMatrix(jacFt.data, jacFt.rows, jacFt.column, "Ft", logfile);
2603
2604 // allocate data for setc array
2605 ✗ double *setc = (double*) calloc (data->modelData->nSetcVars, sizeof(double));
2606
2607 // store the setc data to compute for convergence as setc will be overriddeen with new values
2608 ✗ double *tmpsetc = (double*) calloc (data->modelData->nSetcVars, sizeof(double));
2609
2610 /* loop to store the data C(x,y) rhs side, get the elements in reverse order */
2611 int t = 0;
2612 ✗ for (int i = data->modelData->nSetcVars; i > 0; i--)
2613 {
2614 ✗ setc[t] = data->simulationInfo->setcVars[i-1];
2615 ✗ tmpsetc[t] = data->simulationInfo->setcVars[i-1];
2616 ✗ t++;
2617 //cout << "array_setc_vars:=>" << t << ":" << data->simulationInfo->setcVars[i-1] << "\n";
2618 }
2619
2620 int nsetcvars = data->modelData->nSetcVars;
2621 ✗ matrixData vector_c = {nsetcvars, 1, tmpsetc};
2622
2623 //allocate data for matrix multiplication F*Sx
2624 ✗ double *tmpmatrixC = (double*) calloc (jacF.rows * Sx.column, sizeof(double));
2625 ✗ solveMatrixMultiplication (jacF.data, Sx.data, jacF.rows, jacF.column,Sx.rows, Sx.column, tmpmatrixC, logfile, data);
2626 //printMatrix(tmpmatrixC,jacF.rows,Sx.column,"F*Sx");
2627
2628 //allocate data for matrix multiplication (F*Sx)*Ftranspose
2629 ✗ double *tmpmatrixD = (double*) calloc (jacF.rows * jacFt.column, sizeof(double));
2630 ✗ solveMatrixMultiplication (tmpmatrixC, jacFt.data, jacF.rows, Sx.column, jacFt.rows, jacFt.column, tmpmatrixD, logfile, data);
2631
2632 //printMatrix(tmpmatrixD,jacF.rows,jacFt.column,"F*Sx*Ft");
2633 //printMatrix(setc,nsetcvars,1,"c(x,y)");
2634
2635 /*
2636 * Copy tmpmatrixC and tmpmatrixD to avoid loss of data
2637 * when calculating F*
2638 */
2639 ✗ matrixData cpytmpmatrixC = {jacF.rows, Sx.column, tmpmatrixC};
2640 ✗ matrixData cpytmpmatrixD = {jacF.rows, jacFt.column, tmpmatrixD};
2641 ✗ matrixData tmpmatrixC1 = copyMatrix(cpytmpmatrixC);
2642 ✗ matrixData tmpmatrixD1 = copyMatrix(cpytmpmatrixD);
2643
2644 ✗ if(OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2645 {
2646 ✗ logfile << "Calculations of Matrix (F*Sx*Ft) f* = c(x,y) " << "\n";
2647 ✗ logfile << "============================================\n";
2648 ✗ printMatrix(tmpmatrixC, jacF.rows, Sx.column, "F*Sx", logfile);
2649 ✗ printMatrix(tmpmatrixD, jacF.rows, jacFt.column, "F*Sx*Ft", logfile);
2650 ✗ printMatrix(setc, nsetcvars, 1, "c(x,y)", logfile);
2651 }
2652
2653 /*
2654 * calculate f* for covariance matrix (F*Sx*Ftranspose).F*= c(x,y)
2655 * matrix setc will be overridden with new values which is the output
2656 * for the calculation A *x =B
2657 * A = tmpmatrixD
2658 * B = setc
2659 */
2660 ✗ solveSystemFstar(jacF.rows, 1, tmpmatrixD, setc, logfile, data);
2661
2662 ✗ if(OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2663 {
2664 ✗ printMatrix(setc, jacF.rows, 1, "f*", logfile);
2665 ✗ logfile << "***** Completed ****** \n\n";
2666 }
2667
2668 ✗ matrixData tmpxcap = {x.rows, 1, x.data};
2669 ✗ matrixData tmpfstar = {jacF.rows, 1, setc};
2670 ✗ matrixData reconciled_X = solveReconciledX(tmpxcap, Sx, jacFt, tmpfstar, logfile, data);
2671 //printMatrix(reconciled_X.data,reconciled_X.rows,reconciled_X.column,"reconciled_X ===> (x - (Sx*Ft*fstar))");
2672
2673 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2674 {
2675 ✗ logfile << "Calculations of Matrix (F*Sx*Ft) F* = F*Sx " << "\n";
2676 ✗ logfile << "===============================================\n";
2677 //printMatrix(tmpmatrixC,jacF.rows,Sx.column,"F*Sx");
2678 //printMatrix(tmpmatrixD,jacF.rows,jacFt.column,"F*Sx*Ft");
2679 ✗ printMatrix(tmpmatrixC1.data, tmpmatrixC1.rows, tmpmatrixC1.column, "F*Sx", logfile);
2680 ✗ printMatrix(tmpmatrixD1.data, tmpmatrixD1.rows, tmpmatrixD1.column, "F*Sx*Ft", logfile);
2681 }
2682
2683 /*
2684 * calculate F* for covariance matrix (F*Sx*Ftranspose).F*= (F*Sx)
2685 * tmpmatrixC1 will be overridden with new values which is the output
2686 * for the calculation A *x =B
2687 * A = tmpmatrixD
2688 * B = tmpmatrixC
2689 */
2690 ✗ solveSystemFstar(jacF.rows, Sx.column, tmpmatrixD1.data, tmpmatrixC1.data, logfile, data);
2691
2692 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2693 {
2694 ✗ printMatrix(tmpmatrixC1.data, jacF.rows, Sx.column, "F*", logfile);
2695 ✗ logfile << "***** Completed ****** \n\n";
2696 }
2697
2698 ✗ matrixData tmpFstar = {jacF.rows, Sx.column, tmpmatrixC1.data};
2699 ✗ matrixData reconciled_Sx = solveReconciledSx(Sx, jacFt, tmpFstar, logfile, data);
2700 //printMatrix(reconciled_Sx.data,reconciled_Sx.rows,reconciled_Sx.column,"reconciled Sx ===> (Sx - (Sx*Ft*Fstar))");
2701
2702 ✗ matrixData copySx = copyMatrix(Sx);
2703 ✗ double value = solveConvergence(data, reconciled_X, reconciled_Sx, x, copySx, jacF, vector_c, tmpfstar, logfile);
2704 ✗ if (value > eps)
2705 {
2706 ✗ logfile << "J*/r" << "(" << value << ")" << " > " << eps << ", Value not Converged \n";
2707 ✗ logfile << "==========================================\n\n";
2708 }
2709 ✗ if (value > eps)
2710 {
2711 ✗ logfile << "Running Convergence iteration: " << iterationcount << " with the following reconciled values:" << "\n";
2712 ✗ logfile << "========================================================================" << "\n";
2713 //cout << "J*/r :=" << value << "\n";
2714 //printMatrix(jacF.data,jacF.rows,jacF.column,"F");
2715 //printMatrix(jacFt.data,jacFt.rows,jacFt.column,"Ft");
2716 //printMatrix(setc,jacF.rows,1,"f*");
2717 //printMatrix(tmpmatrixC,jacF.rows,Sx.column,"F*");
2718 ✗ printMatrixWithHeaders(reconciled_X.data, reconciled_X.rows, reconciled_X.column, csvinputs.headers, "reconciled_X ===> (x - (Sx*Ft*fstar))", logfile);
2719 ✗ printMatrixWithHeaders(reconciled_Sx.data, reconciled_Sx.rows, reconciled_Sx.column, csvinputs.headers, "reconciled_Sx ===> (Sx - (Sx*Ft*Fstar))", logfile);
2720 //free(x.data);
2721 //free(Sx.data);
2722 //x.data = reconciled_X.data;
2723 ✗ for (int i = 0; i < reconciled_X.rows * reconciled_X.column; i++)
2724 {
2725 ✗ x.data[i] = reconciled_X.data[i];
2726 }
2727
2728 ✗ free(reconciled_X.data);
2729 ✗ free(jacF.data);
2730 ✗ free(jacFt.data);
2731 ✗ free(tmpmatrixC);
2732 ✗ free(tmpmatrixD);
2733 ✗ free(tmpmatrixC1.data);
2734 ✗ free(tmpmatrixD1.data);
2735 ✗ free(setc);
2736 ✗ free(tmpsetc);
2737 ✗ free(copySx.data);
2738 ✗ free(reconciled_Sx.data);
2739 ✗ iterationcount++;
2740 ✗ return RunReconciliation(data, threadData, x, Sx, jacF, jacFt, eps, iterationcount, csvinputs, xdiag, sxdiag, logfile, warningCorrelationData, datareconciliationdata);
2741 }
2742
2743 ✗ if (value < eps && iterationcount == 1)
2744 {
2745 ✗ logfile << "J*/r" << "(" << value << ")" << " > " << eps << ", Convergence iteration not required \n\n";
2746 }
2747 else
2748 {
2749 ✗ logfile << "***** Value Converged, Convergence Completed******* \n\n";
2750 }
2751
2752 ✗ double J = calculateQualityValue(reconciled_X, Sx, csvinputs, logfile, data);
2753
2754 ✗ logfile << "Final Results:\n";
2755 ✗ logfile << "=============\n";
2756 ✗ logfile << "Total Iteration to Converge : " << iterationcount << "\n";
2757 ✗ logfile << "Final Converged Value(J*/r) : " << value << "\n";
2758 ✗ logfile << "Final value of the objective function (J) : " << J << "\n";
2759 ✗ logfile << "Epsilon : " << eps << "\n";
2760 ✗ printMatrixWithHeaders(reconciled_X.data, reconciled_X.rows, reconciled_X.column, csvinputs.headers, "reconciled_X ===> (x - (Sx*Ft*fstar))", logfile);
2761 ✗ printMatrixWithHeaders(reconciled_Sx.data, reconciled_Sx.rows, reconciled_Sx.column, csvinputs.headers, "reconciled_Sx ===> (Sx - (Sx*Ft*Fstar))", logfile);
2762
2763 ✗ dumpReconciledSxToCSV(reconciled_Sx.data, reconciled_Sx.rows, reconciled_Sx.column, csvinputs.headers, data);
2764
2765 // copy the reconciledSx matrix for state Estimation
2766 ✗ matrixData copyReconciledSx = copyMatrix(reconciled_Sx);
2767
2768 /*
2769 * Calculate half width Confidence interval
2770 * W=lambda*sqrt(Sx)
2771 * where lamba = 1.96 and
2772 * Sx - diagonal elements of reconciled_Sx
2773 */
2774 ✗ double *reconSx_diag = (double*) calloc (reconciled_Sx.rows * 1, sizeof(double));
2775 ✗ getDiagonalElements(reconciled_Sx.data, reconciled_Sx.rows, reconciled_Sx.column, reconSx_diag);
2776
2777 ✗ matrixData copyreconSx_diag = {reconciled_Sx.rows, 1, reconSx_diag};
2778 ✗ matrixData tmpcopyreconSx_diag = copyMatrix(copyreconSx_diag);
2779
2780 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2781 {
2782 ✗ logfile << "Calculations of HalfWidth Confidence Interval " << "\n";
2783 ✗ logfile << "===============================================\n";
2784 ✗ printMatrix(copyreconSx_diag.data, reconciled_Sx.rows, 1, "reconciled-Sx_Diagonal", logfile);
2785 }
2786
2787 ✗ calculateSquareRoot(copyreconSx_diag.data, reconciled_Sx.rows);
2788
2789 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2790 {
2791 ✗ printMatrix(copyreconSx_diag.data, reconciled_Sx.rows, 1, "reconciled-Sx_SquareRoot", logfile);
2792 ✗ logfile << "*****Completed***********\n";
2793 }
2794
2795 ✗ scaleVector(reconciled_Sx.rows, 1, 1.96, copyreconSx_diag.data);
2796 ✗ printMatrixWithHeaders(copyreconSx_diag.data, reconciled_Sx.rows, 1, csvinputs.headers, "Wx-HalfWidth-Interval-(1.96)*sqrt(Sx_diagonal)", logfile);
2797
2798 /*
2799 * Calculate individual tests
2800 * (recon_x - x)/sqrt(Sx-recon_Sx)
2801 */
2802 ✗ double *newSx_diag = (double*) calloc (reconciled_Sx.rows * 1, sizeof(double));
2803 ✗ solveMatrixSubtraction(sxdiag, tmpcopyreconSx_diag, newSx_diag, logfile, data);
2804
2805 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2806 {
2807 ✗ logfile << "Calculations of Individual Tests " << "\n";
2808 ✗ logfile << "===============================================\n";
2809 ✗ printMatrix(newSx_diag, sxdiag.rows, sxdiag.column, "Sx-recon_Sx", logfile);
2810 }
2811
2812 ✗ calculateSquareRoot(newSx_diag, reconciled_Sx.rows);
2813
2814 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2815 {
2816 ✗ printMatrix (newSx_diag, sxdiag.rows, sxdiag.column, "squareroot-newSx", logfile);
2817 }
2818
2819 ✗ double *newX = (double*) calloc (xdiag.rows * 1, sizeof(double));
2820 ✗ solveMatrixSubtraction(reconciled_X, xdiag, newX, logfile, data);
2821
2822 // calculate absolute value for this numeric analysis
2823 ✗ for (int a = 0; a < xdiag.rows; a++)
2824 {
2825 ✗ newX[a] = fabs (newX[a]);
2826 }
2827
2828 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2829 {
2830 ✗ printMatrix(newX, xdiag.rows, xdiag.column, "recon_X - X", logfile);
2831 ✗ logfile << "*********Completed***********\n";
2832 }
2833
2834 ✗ for (int val = 0; val < xdiag.rows; val++)
2835 {
2836 ✗ newX[val] = newX[val] / max(newSx_diag[val], sqrt(sxdiag.data[val] / 10));
2837 }
2838
2839 ✗ printMatrixWithHeaders(newX, xdiag.rows, xdiag.column, csvinputs.headers, "IndividualTests_Value- (recon_x-x)/sqrt(Sx_diag)", logfile);
2840
2841 // copy the outputs for state Estimation
2842 ✗ if (omc_flag[FLAG_DATA_RECONCILE_STATE])
2843 ✗ datareconciliationdata = {csvinputs, xdiag, reconciled_X, copyReconciledSx, copyreconSx_diag, newX, eps, iterationcount, value, J, warningCorrelationData};
2844
2845 // read and update reconciled mo file with new values
2846
2847 ✗ updateReconciledMo(data, threadData, csvinputs.headers, reconciled_X.data, logfile);
2848
2849 boundaryConditionData boundaryconditiondata;
2850 // create HTML Report for D.1
2851 ✗ if (omc_flag[FLAG_DATA_RECONCILE])
2852 {
2853 ✗ createHtmlReportFordataReconciliation(data, csvinputs, xdiag, reconciled_X, copyreconSx_diag, newX, eps, iterationcount, value, J, warningCorrelationData, boundaryconditiondata);
2854 // free the memory for data Reconciliation
2855 ✗ free(jacF.data);
2856 ✗ free(jacFt.data);
2857 ✗ free(tmpmatrixC);
2858 ✗ free(tmpmatrixD);
2859 ✗ free(tmpmatrixC1.data);
2860 ✗ free(tmpmatrixD1.data);
2861 ✗ free(setc);
2862 ✗ free(tmpsetc);
2863 ✗ free(copySx.data);
2864 ✗ free(copyReconciledSx.data);
2865 ✗ free(reconciled_X.data);
2866 ✗ free(reconciled_Sx.data);
2867 ✗ free(newX);
2868 ✗ free(newSx_diag);
2869 ✗ free(copyreconSx_diag.data);
2870 ✗ free(tmpcopyreconSx_diag.data);
2871 }
2872 else
2873 {
2874 // state estimation, do not free the commented data as it is used in state estimation report
2875 ✗ free(jacF.data);
2876 ✗ free(jacFt.data);
2877 ✗ free(tmpmatrixC);
2878 ✗ free(tmpmatrixD);
2879 ✗ free(tmpmatrixC1.data);
2880 ✗ free(tmpmatrixD1.data);
2881 ✗ free(setc);
2882 ✗ free(tmpsetc);
2883 ✗ free(copySx.data);
2884 //free(copyReconciledSx.data);
2885 //free(reconciled_X.data);
2886 ✗ free(reconciled_Sx.data);
2887 //free(newX);
2888 ✗ free(newSx_diag);
2889 //free(copyreconSx_diag.data);
2890 ✗ free(tmpcopyreconSx_diag.data);
2891 }
2892
2893 return 0;
2894 }
2895
2896 /*
2897 * Runs the numerical procedure to compute Boundary conditions (D.2)
2898 */
2899 ✗ int reconcileBoundaryConditions(DATA * data, threadData_t * threadData, inputData reconciled_x, matrixData reconciled_Sx, boundaryConditionData& boundaryconditiondata, correlationDataWarning& warningCorrelationData, ofstream& logfile)
2900 {
2901 // set the inputs from csv file to simulationInfo datainputVars
2902 ✗ for (int i = 0; i < reconciled_x.rows * reconciled_x.column; i++)
2903 {
2904 ✗ data->simulationInfo->datainputVars[i] = reconciled_x.data[i];
2905 }
2906
2907 /* set the inputs via this special function generated for dataReconciliation
2908 * which also sets inputs for models not involving top level inputs
2909 */
2910 ✗ data->callback->data_function(data, threadData);
2911 // solve the system with reconciled input values got from D.1
2912 ✗ data->callback->functionDAE(data, threadData);
2913 // call the setc function which stores the results of boundary conditions variable
2914 ✗ if (omc_flag[FLAG_DATA_RECONCILE_BOUNDARY])
2915 ✗ data->callback->setc_function(data, threadData);
2916 // call the setb function for state estimation
2917 ✗ if (omc_flag[FLAG_DATA_RECONCILE_STATE])
2918 ✗ data->callback->setb_function(data, threadData);
2919
2920 // Compute the Jacobian Matrix F or H
2921 matrixData jacF;
2922 ✗ if (omc_flag[FLAG_DATA_RECONCILE_BOUNDARY])
2923 {
2924 ✗ jacF = getJacobianMatrixF(data, threadData, logfile, true);
2925 }
2926 else
2927 {
2928 ✗ jacF = getJacobianMatrixH(data, threadData, logfile, true);
2929 }
2930
2931 ✗ printMatrix(jacF.data, jacF.rows, jacF.column, "F", logfile);
2932
2933 // Compute the Transpose of jacobian Matrix F
2934 ✗ matrixData jacFt = getTransposeMatrix(jacF);
2935 ✗ printMatrix(jacFt.data, jacFt.rows, jacFt.column, "Ft", logfile);
2936
2937 /*
2938 * Compute St = jacF*reconciles_Sx*jacFt
2939 */
2940 // F*reconciledSx
2941 ✗ double *tmpMatrixAf = (double *)calloc(jacF.rows * reconciled_Sx.column, sizeof(double));
2942 ✗ solveMatrixMultiplication(jacF.data, reconciled_Sx.data, jacF.rows, jacF.column, reconciled_Sx.rows, reconciled_Sx.column, tmpMatrixAf, logfile, data);
2943 ✗ printMatrix(tmpMatrixAf, jacF.rows, reconciled_Sx.column, "F*reconciled_Sx", logfile);
2944
2945 //(F*reconciledSx)*ftranspose
2946 ✗ double *S_t = (double*) calloc(jacF.rows * jacFt.column, sizeof(double));
2947 ✗ solveMatrixMultiplication(tmpMatrixAf, jacFt.data, jacF.rows, jacF.column, jacFt.rows, jacFt.column, S_t, logfile, data);
2948 ✗ printMatrix(S_t, jacF.rows, jacFt.column, "(s_t = F*reconciled_Sx*Ft)", logfile);
2949
2950 /*
2951 * Calculate half width Confidence interval
2952 * W=lambda*sqrt(S_t)
2953 * where lamba = 1.96 and
2954 * S_t - diagonal elements of S_t
2955 */
2956 ✗ double *reconSt_diag = (double*) calloc (jacF.rows * 1, sizeof(double));
2957 ✗ getDiagonalElements(S_t, jacF.rows, jacFt.column, reconSt_diag);
2958
2959 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2960 {
2961 ✗ logfile << "Calculations of half-width confidence interval" << "\n";
2962 ✗ logfile << "===============================================\n";
2963 ✗ printMatrix(reconSt_diag, jacF.rows, 1, "S_t_Diagonal", logfile);
2964 }
2965
2966 ✗ calculateSquareRoot(reconSt_diag, jacF.rows);
2967
2968 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_JAC))
2969 {
2970 ✗ printMatrix(reconSt_diag, jacF.rows, 1, "S_t_SquareRoot", logfile);
2971 }
2972
2973 ✗ scaleVector(jacF.rows, 1, 1.96, reconSt_diag);
2974
2975 // check for BoundaryConditionVars.txt file exists to generate the html report
2976 std::string boundaryConditionsVarsFilename;
2977 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
2978 {
2979 ✗ boundaryConditionsVarsFilename = std::string(omc_flagValue[FLAG_OUTPUT_PATH]) + "/" + std::string(data->modelData->modelFilePrefix) + "_BoundaryConditionVars.txt";
2980 ✗ copyReferenceFile(data, "_BoundaryConditionVars.txt");
2981 }
2982 else
2983 {
2984 ✗ boundaryConditionsVarsFilename = std::string(data->modelData->modelFilePrefix) + "_BoundaryConditionVars.txt";
2985 }
2986
2987 vector<std::string> boundaryConditionVars;
2988
2989 ✗ ifstream boundaryConditionVarsip(boundaryConditionsVarsFilename);
2990 std::string line;
2991 ✗ if (boundaryConditionVarsip.good())
2992 {
2993 ✗ while (boundaryConditionVarsip.good())
2994 {
2995 ✗ getline(boundaryConditionVarsip, line);
2996 ✗ if (!line.empty())
2997 {
2998 //std::cout << "\n reading nonVariables of interest : " << line;
2999 ✗ boundaryConditionVars.push_back(line);
3000 }
3001 }
3002 ✗ boundaryConditionVarsip.close();
3003 //omc_unlink(boundaryConditionsVarsFilename.c_str());
3004 }
3005 else
3006 {
3007 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Boundary conditions vars filename not found: %s.", boundaryConditionsVarsFilename.c_str());
3008 ✗ logfile << "| error | " << "Boundary conditions vars filename not found: " << boundaryConditionsVarsFilename << "\n";
3009 ✗ logfile.close();
3010 ✗ createErrorHtmlReportForBoundaryConditions(data);
3011 ✗ exit(1);
3012 }
3013
3014 ✗ printMatrixWithHeaders(reconSt_diag, jacF.rows, 1, boundaryConditionVars, "Half-width Confidence Interval(1.96*S_t_SquareRoot)", logfile);
3015
3016 // allocate data for boundaryconditions vars simulation results
3017 double *boundaryConditionVarsResults;
3018 ✗ if (omc_flag[FLAG_DATA_RECONCILE_BOUNDARY])
3019 {
3020 ✗ boundaryConditionVarsResults = (double *)calloc(data->modelData->nSetcVars, sizeof(double));
3021 int t = 0;
3022 ✗ for (int i = data->modelData->nSetcVars; i > 0; i--)
3023 {
3024 ✗ boundaryConditionVarsResults[t] = data->simulationInfo->setcVars[i - 1];
3025 ✗ t++;
3026 }
3027 }
3028 else
3029 {
3030 ✗ boundaryConditionVarsResults = (double *)calloc(data->modelData->nSetbVars, sizeof(double));
3031 int t = 0;
3032 ✗ for (int i = data->modelData->nSetbVars; i > 0; i--)
3033 {
3034 ✗ boundaryConditionVarsResults[t] = data->simulationInfo->setbVars[i - 1];
3035 ✗ t++;
3036 }
3037 }
3038
3039 ✗ printBoundaryConditionsResults(boundaryConditionVarsResults, reconSt_diag, jacF.rows, 1, boundaryConditionVars, "Final Results", logfile);
3040
3041 // create html report for boundary conditions
3042 ✗ if (omc_flag[FLAG_DATA_RECONCILE_BOUNDARY])
3043 ✗ createHtmlReportForBoundaryConditions(data, boundaryConditionVars, boundaryConditionVarsResults, reconSt_diag, warningCorrelationData);
3044
3045 // copy the results for state estimation
3046 ✗ if (omc_flag[FLAG_DATA_RECONCILE_STATE])
3047 ✗ boundaryconditiondata = {boundaryConditionVars, boundaryConditionVarsResults, reconSt_diag};
3048
3049 // free the memory
3050 ✗ if (omc_flag[FLAG_DATA_RECONCILE_BOUNDARY])
3051 {
3052 ✗ free(reconciled_Sx.data);
3053 ✗ free(reconciled_x.data);
3054 ✗ free(tmpMatrixAf);
3055 ✗ free(S_t);
3056 ✗ free(jacF.data);
3057 ✗ free(jacFt.data);
3058 ✗ free(reconSt_diag);
3059 ✗ free(boundaryConditionVarsResults);
3060 }
3061 else
3062 {
3063 // state Estimation
3064 ✗ free(tmpMatrixAf);
3065 ✗ free(S_t);
3066 ✗ free(jacF.data);
3067 ✗ free(jacFt.data);
3068 }
3069
3070 ✗ return 0;
3071 ✗ }
3072
3073 /*
3074 * State Estimation numerical computation is a combination of
3075 * Data Reconciliation and boundary condition computation
3076 */
3077
3078 ✗ int stateEstimation(DATA *data, threadData_t *threadData, inputData x, matrixData Sx, matrixData tmpjacF, matrixData tmpjacFt, double eps, int iterationcount, csvData csvinputs, matrixData xdiag, matrixData sxdiag, ofstream &logfile, correlationDataWarning & warningCorrelationData)
3079 {
3080 // run the data Reconciliation
3081 dataReconciliationData datareconciliationdata;
3082 ✗ RunReconciliation(data, threadData, x, Sx, tmpjacF, tmpjacFt, eps, 1, csvinputs, xdiag, sxdiag, logfile, warningCorrelationData, datareconciliationdata);
3083
3084 //printMatrixWithHeaders(datareconciliationdata.reconciled_X.data, datareconciliationdata.reconciled_X.rows, datareconciliationdata.reconciled_X.column, csvinputs.headers, "ARRRRRreconciled_X ===> (x - (Sx*Ft*fstar))", logfile);
3085 //printMatrixWithHeaders(datareconciliationdata.copyreconSx_diag.data, datareconciliationdata.copyreconSx_diag.rows, datareconciliationdata.copyreconSx_diag.column, csvinputs.headers, "ARRRRRRreconciled_Sx ===> (Sx - (Sx*Ft*Fstar))", logfile);
3086 //printMatrixWithHeaders(datareconciliationdata.reconciled_SX.data, datareconciliationdata.reconciled_SX.rows, datareconciliationdata.reconciled_SX.column, csvinputs.headers, "NovakreconciledS_X ===> (x - (Sx*Ft*fstar))", logfile);
3087
3088 // Compute Boundary conditions only if unmeasured variables exist
3089 boundaryConditionData boundaryconditiondata;
3090 ✗ if (data->modelData->nSetbVars > 0)
3091 {
3092 // copy the reference files "BoundaryConditionsEquations.html and _BoundaryConditionIntermediateEquations.html to output path"
3093 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
3094 {
3095 ✗ copyReferenceFile(data, "_BoundaryConditionIntermediateEquations.html");
3096 }
3097 // pepare data to compute boundary condition
3098 ✗ inputData reconciled_x = {datareconciliationdata.reconciled_X.rows, datareconciliationdata.reconciled_X.column, datareconciliationdata.reconciled_X.data, {}};
3099 ✗ matrixData reconciled_Sx = {datareconciliationdata.reconciled_SX.rows, datareconciliationdata.reconciled_SX.column, datareconciliationdata.reconciled_SX.data};
3100
3101 ✗ logfile << "\n\nCalculation of Boundary condition \n" << "====================================\n";
3102 ✗ reconcileBoundaryConditions(data, threadData, reconciled_x, reconciled_Sx, boundaryconditiondata, warningCorrelationData, logfile);
3103 // printBoundaryConditionsResults(boundaryconditiondata.boundaryConditionVarsResults, boundaryconditiondata.reconSt_diag, boundaryconditiondata.boundaryConditionVars.size(), 1, boundaryconditiondata.boundaryConditionVars, "Final Results Copied", logfile);
3104 }
3105
3106 ✗ createHtmlReportFordataReconciliation(data, datareconciliationdata.csvinputs, datareconciliationdata.xdiag, datareconciliationdata.reconciled_X, datareconciliationdata.copyreconSx_diag, datareconciliationdata.newX, eps, datareconciliationdata.iterationcount, datareconciliationdata.value, datareconciliationdata.J, warningCorrelationData, boundaryconditiondata);
3107
3108 // free data Reconciliation data
3109 ✗ free(datareconciliationdata.reconciled_SX.data);
3110 ✗ free(datareconciliationdata.reconciled_X.data);
3111 ✗ free(datareconciliationdata.copyreconSx_diag.data);
3112 ✗ free(datareconciliationdata.newX);
3113
3114 // free boundaryCondition data
3115 ✗ if (data->modelData->nSetbVars > 0)
3116 {
3117 ✗ free(boundaryconditiondata.boundaryConditionVarsResults);
3118 ✗ free(boundaryconditiondata.reconSt_diag);
3119 }
3120 ✗ return 0;
3121 }
3122
3123 /*
3124 * Runs the numerical procedure to compute constraint equation (D.1)
3125 */
3126 ✗ int dataReconciliation(DATA * data, threadData_t * threadData, int status)
3127 {
3128 // copy the reference files "AuxiliaryConditions and IntermediateEquations.html to output path"
3129 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
3130 {
3131 ✗ copyReferenceFile(data, "_AuxiliaryConditions.html");
3132 ✗ copyReferenceFile(data, "_IntermediateEquations.html");
3133 ✗ copyReferenceFile(data, "_relatedBoundaryConditionsEquations.html");
3134 ✗ copyReferenceFile(data, "_iterationVars.txt");
3135 }
3136
3137 // report run time initialization and non linear convergence error to html
3138 ✗ if (status != 0)
3139 {
3140 ✗ createErrorHtmlReport(data, status);
3141 ✗ exit(1);
3142 }
3143
3144 const char * epselon = NULL;
3145 ✗ epselon = (char*) omc_flagValue[FLAG_DATA_RECONCILE_Eps];
3146
3147 // create a debug log file
3148 ✗ ofstream logfile;
3149 ✗ std::stringstream logfilename;
3150 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
3151 {
3152 ✗ logfilename << omc_flagValue[FLAG_OUTPUT_PATH] << "/" << data->modelData->modelFilePrefix << "_debug.txt";
3153 }
3154 else
3155 {
3156 ✗ logfilename << data->modelData->modelFilePrefix << "_debug.txt";
3157 }
3158
3159 string tmplogfilename = logfilename.str();
3160 ✗ logfile.open(tmplogfilename.c_str());
3161
3162 ✗ if (omc_flag[FLAG_DATA_RECONCILE])
3163 {
3164 ✗ logfile << "| info | " << "DataReconciliation Starting!\n";
3165 ✗ logfile << "| info | " << data->modelData->modelName << "\n";
3166 }
3167 ✗ if (omc_flag[FLAG_DATA_RECONCILE_STATE])
3168 {
3169 ✗ logfile << "| info | " << "State Estimation Starting!\n";
3170 ✗ logfile << "| info | " << data->modelData->modelName << "\n";
3171 }
3172
3173 // set default value (epselon = 1.e-10), if no value provided by user
3174 ✗ if (epselon == NULL)
3175 {
3176 epselon = "0.0000000001";
3177 }
3178
3179 // read the measurement input data provide by user
3180 ✗ csvData csvdata = readMeasurementInputFile(logfile, data, threadData);
3181
3182 // validate the input data read from measurement input file
3183 ✗ csvData Sx_data = validateMeasurementInputs(csvdata, data, logfile);
3184
3185 // extracts the input data (x) from csvData
3186 ✗ inputData x = getInputData(Sx_data, logfile);
3187
3188 // read the correlation coefficient input data provide by user
3189 correlationDataWarning warningCorrelationData;
3190
3191 ✗ correlationData Cx_data = readCorrelationCoefficientFile(Sx_data, logfile, data, threadData, warningCorrelationData);
3192
3193 // Compute the covariance matrix (Sx) from csvData
3194 ✗ matrixData Sx = computeCovarianceMatrixSx(Sx_data, Cx_data, logfile, data);
3195
3196 // Compute the Jacobian Matrix F
3197 ✗ matrixData jacF = getJacobianMatrixF(data, threadData, logfile);
3198
3199 // Compute the Transpose of jacobian Matrix F
3200 ✗ matrixData jacFt = getTransposeMatrix(jacF);
3201
3202 ✗ double * Sx_diag = (double*) calloc(Sx.rows * 1, sizeof(double));
3203 ✗ getDiagonalElements(Sx.data, Sx.rows, Sx.column, Sx_diag);
3204 ✗ matrixData tmpSx_diag = {Sx.rows, 1, Sx_diag};
3205
3206 ✗ matrixData tmp_x = {x.rows, x.column, x.data};
3207 ✗ matrixData x_diag = copyMatrix(tmp_x);
3208
3209 // Print the initial information
3210 ✗ logfile << "\n\nInitial Data \n" << "=============\n";
3211 ✗ printMatrixWithHeaders(x.data, x.rows, x.column, Sx_data.headers, "X", logfile);
3212 ✗ printVectorMatrixWithHeaders(Sx_data.sxdata, Sx_data.rowcount, 1, Sx_data.headers, "Half-WidthConfidenceInterval", logfile);
3213 ✗ printCorelationMatrix(Cx_data.data, Cx_data.rowHeaders, Cx_data.columnHeaders, "Co-Relation_Coefficient", logfile, warningCorrelationData);
3214 ✗ printMatrixWithHeaders(Sx.data, Sx.rows, Sx.column, Sx_data.headers, "Sx", logfile);
3215
3216 // Start the Algorithm
3217 ✗ if (omc_flag[FLAG_DATA_RECONCILE])
3218 {
3219 dataReconciliationData datareconciliationdata;
3220 ✗ RunReconciliation(data, threadData, x, Sx, jacF, jacFt, atof(epselon), 1, Sx_data, x_diag, tmpSx_diag, logfile, warningCorrelationData, datareconciliationdata);
3221 ✗ logfile << "| info | " << "DataReconciliation Completed! \n";
3222 }
3223 ✗ if (omc_flag[FLAG_DATA_RECONCILE_STATE])
3224 {
3225 ✗ stateEstimation(data, threadData, x, Sx, jacF, jacFt, atof(epselon), 1, Sx_data, x_diag, tmpSx_diag, logfile, warningCorrelationData);
3226 ✗ logfile << "| info | " << "state estimation Completed! \n";
3227 }
3228 ✗ logfile.flush();
3229 ✗ logfile.close();
3230 ✗ free(Sx.data);
3231 ✗ free(x.data);
3232 ✗ free(jacF.data);
3233 ✗ free(jacFt.data);
3234 ✗ free(tmpSx_diag.data);
3235 ✗ free(x_diag.data);
3236 ✗ return 0;
3237 ✗ }
3238
3239 ✗ int boundaryConditions(DATA * data, threadData_t * threadData, int status)
3240 {
3241 // copy the reference files "BoundaryConditionsEquations.html and _BoundaryConditionIntermediateEquations.html to output path"
3242 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
3243 {
3244 ✗ copyReferenceFile(data, "_BoundaryConditionsEquations.html");
3245 ✗ copyReferenceFile(data, "_BoundaryConditionIntermediateEquations.html");
3246 ✗ copyReferenceFile(data, "_iterationVars.txt");
3247 }
3248
3249 // report run time initialization and non linear convergence error to html
3250 ✗ if (status != 0)
3251 {
3252 ✗ createErrorHtmlReportForBoundaryConditions(data, status);
3253 ✗ exit(1);
3254 }
3255
3256 // create a debug log file
3257 ✗ ofstream logfile;
3258 ✗ std::stringstream logfilename;
3259 ✗ if (omc_flag[FLAG_OUTPUT_PATH])
3260 {
3261 ✗ logfilename << omc_flagValue[FLAG_OUTPUT_PATH] << "/" << data->modelData->modelFilePrefix << "_BoundaryConditions_debug.txt";
3262 }
3263 else
3264 {
3265 ✗ logfilename << data->modelData->modelFilePrefix << "_BoundaryConditions_debug.txt";
3266 }
3267
3268 string tmplogfilename = logfilename.str();
3269 ✗ logfile.open(tmplogfilename.c_str());
3270 ✗ logfile << "| info | " << "Reconcile Boundary Conditions Starting!\n";
3271 ✗ logfile << "| info | " << data->modelData->modelName << "\n";
3272
3273 // read the measurement input data provide by user
3274 ✗ csvData csvdata = readMeasurementInputFile(logfile, data, threadData, true);
3275
3276 // validate the input data read from measurement input file
3277 ✗ csvData Sx_data = validateMeasurementInputs(csvdata, data, logfile, true);
3278
3279 // extracts the input data (x) from csvData
3280 ✗ inputData reconciled_x = getReconciledX(Sx_data, logfile);
3281
3282 // read the reconciled covariance matrix input file provided by user
3283 correlationDataWarning warningCorrelationData;
3284 ✗ correlationData cx_data = readCorrelationCoefficientFile(Sx_data, logfile, data, threadData, warningCorrelationData, true);
3285
3286 // create the column matrix from the covariance matrix
3287 ✗ int rowsize = cx_data.rowHeaders.size();
3288 ✗ int colsize = cx_data.columnHeaders.size();
3289 ✗ double *tempSx = (double*) calloc(rowsize * colsize, sizeof(double));
3290 ✗ initColumnMatrix(cx_data.data, rowsize, colsize, tempSx);
3291 matrixData reconciled_Sx = {rowsize, colsize, tempSx};
3292
3293
3294 ✗ logfile << "\n\nInitial Data \n" << "=============\n";
3295 ✗ printMatrixWithHeaders(reconciled_x.data, reconciled_x.rows, reconciled_x.column, Sx_data.headers, "Reconciled_X", logfile);
3296 //printCorelationMatrix(reconciled_Sx.data, reconciled_Sx.rowHeaders, reconciled_Sx.columnHeaders, "Reconciled_Sx", logfile, warningCorrelationData);
3297 ✗ printMatrixWithHeaders(reconciled_Sx.data, reconciled_Sx.rows, reconciled_Sx.column, Sx_data.headers, "Reconciled_Sx", logfile);
3298 boundaryConditionData boundaryconditiondata;
3299 ✗ reconcileBoundaryConditions(data, threadData, reconciled_x, reconciled_Sx, boundaryconditiondata, warningCorrelationData, logfile);
3300 ✗ updateReconciledMo(data, threadData, Sx_data.headers, reconciled_x.data, logfile);
3301
3302 ✗ logfile << "*****Completed***********\n";
3303 ✗ logfile << "| info | " << "Reconcile Boundary Conditions Completed! \n";
3304 ✗ logfile.flush();
3305 ✗ logfile.close();
3306
3307 //free(reconciled_Sx.data);
3308 //free(reconciled_x.data);
3309 ✗ return 0;
3310 ✗ }
3311