diff --git a/src/gui/utils.cpp b/src/gui/utils.cpp index 0b3e2fb2..7003f3bf 100644 --- a/src/gui/utils.cpp +++ b/src/gui/utils.cpp @@ -36,7 +36,7 @@ bool Utils::isSet(AppFlags flag) { QSettings settings(QCoreApplication::applicationDirPath() + "/qss-solver.ini", QSettings::IniFormat); QString val = settings.value(appFlagName(flag), "Value not found in file qss-solver.ini").toString(); - return val.isEmpty(); + return val == "true"; } QString Utils::getDebugValue() diff --git a/src/mmoc/.vscode/launch.json b/src/mmoc/.vscode/launch.json index 51614f5b..8e6e7470 100644 --- a/src/mmoc/.vscode/launch.json +++ b/src/mmoc/.vscode/launch.json @@ -594,6 +594,26 @@ "ignoreFailures": true } ] + }, + + // Use time variable in initialization code + { + "name": "Init Code Time Test model.", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/usr/bin/mmoc", + "args": ["-o /home/joaquin/work/qss-solver/build/init_code_time/init_code_time ", "/home/joaquin/work/qss-solver/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.mo"], + "cwd": "${workspaceFolder}/usr/bin/", + "environment": [], + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] } + ] } \ No newline at end of file diff --git a/src/mmoc/generator/model_instance.cpp b/src/mmoc/generator/model_instance.cpp index 317c0e36..c4f63104 100644 --- a/src/mmoc/generator/model_instance.cpp +++ b/src/mmoc/generator/model_instance.cpp @@ -367,7 +367,7 @@ void ModelInstance::initialCode() { StatementTable stms = _model.initialCode(); StatementTable::iterator it; - stringstream buffer; + bool autonomous = true; ModelConfig::instance().setLocalInitSymbols(); ModelConfig::instance().setInitialCode(true); VarSymbolTable symbols = _model.symbols(); @@ -380,6 +380,12 @@ void ModelInstance::initialCode() } for (Statement stm = stms.begin(it); !stms.end(it); stm = stms.next(it)) { _writer->write(stm, WRITER::Init_Code); + autonomous = autonomous && stm.autonomous(); + } + if (!autonomous) { + stringstream initial_time; + initial_time << "int t = " << _model.annotations().initialTime() << ";"; + ModelConfig::instance().addLocalSymbol(initial_time.str()); } ModelConfig::instance().setInitialCode(false); ModelConfig::instance().unsetLocalInitSymbols(); @@ -670,7 +676,6 @@ void QSSModelInstance::header() _writer->write(buffer, WRITER::Model_Header); for (Variable var = symbols.begin(it); !symbols.end(it); var = symbols.next(it)) { if (var.isState()) { - stringstream buffer; Macros macros(_model, var); buffer << "// Derivative definition for variable: " << var.name() << endl; buffer << "#define _der" << var << macros.parameters() << " dx[coeff+1]"; @@ -792,7 +797,8 @@ void ClassicModelInstance::header() _writer->write(buffer, WRITER::Model_Header); for (Variable var = symbols.begin(it); !symbols.end(it); var = symbols.next(it)) { if (var.isState()) { - stringstream buffer, arguments; + stringstream buffer; + stringstream arguments; Macros macros(_model, var); arguments << macros.engineIndexArguments(); buffer << "// Derivative definition for variable: " << var.name() << endl; diff --git a/src/mmoc/ir/equation.cpp b/src/mmoc/ir/equation.cpp index d6b3e7c6..c78dbd02 100644 --- a/src/mmoc/ir/equation.cpp +++ b/src/mmoc/ir/equation.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -131,8 +130,7 @@ void Equation::initialize(AST_Equation eq) void Equation::setup() { stringstream buffer; - Autonomous autonomous; - _autonomous = autonomous.apply(_rhs.expression()); + _autonomous = _rhs.autonomous(); CalledFunctions cf; _calledFunctions = cf.apply(_rhs.expression()); if (_range) { diff --git a/src/mmoc/ir/expression.cpp b/src/mmoc/ir/expression.cpp index 4f23957e..6b9c20ac 100644 --- a/src/mmoc/ir/expression.cpp +++ b/src/mmoc/ir/expression.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -177,5 +178,11 @@ std::multimap Expression::usedVariables() const return used_variables.apply(_exp); } +bool Expression::autonomous() const +{ + Autonomous autonomous; + return autonomous.apply(expression()); +} + } // namespace IR } // namespace MicroModelica diff --git a/src/mmoc/ir/expression.h b/src/mmoc/ir/expression.h index fb0ae688..c36b7df4 100644 --- a/src/mmoc/ir/expression.h +++ b/src/mmoc/ir/expression.h @@ -48,6 +48,7 @@ class Expression { friend std::ostream& operator<<(std::ostream& out, const Expression& s); std::multimap usedVariables() const; + bool autonomous() const; protected: std::vector usageExps() const; diff --git a/src/mmoc/ir/statement.cpp b/src/mmoc/ir/statement.cpp index 493e7734..f0fe060a 100644 --- a/src/mmoc/ir/statement.cpp +++ b/src/mmoc/ir/statement.cpp @@ -18,14 +18,14 @@ ******************************************************************************/ #include -#include "../ast/ast_builder.h" -#include "../ast/statement.h" -#include "../util/model_config.h" -#include "../util/util.h" -#include "../util/process_statement.h" -#include "../util/visitors/called_functions.h" -#include "helpers.h" -#include "statement.h" +#include +#include +#include +#include +#include +#include +#include +#include namespace MicroModelica { using namespace Util; @@ -268,6 +268,15 @@ ExpressionList Statement::assignments(STATEMENT::AssignTerm asg) const return ExpressionList(); } +bool Statement::autonomous() const +{ + bool autonomous = true; + for (const auto& exp : _rhs_assignments) { + autonomous = autonomous && exp.autonomous(); + } + return autonomous; +} + std::ostream& operator<<(std::ostream& out, const Statement& s) { return out << s.print(); } } // namespace IR } // namespace MicroModelica diff --git a/src/mmoc/ir/statement.h b/src/mmoc/ir/statement.h index def08c55..3319d86c 100644 --- a/src/mmoc/ir/statement.h +++ b/src/mmoc/ir/statement.h @@ -17,12 +17,11 @@ ******************************************************************************/ -#ifndef MMO_STATEMENT_H_ -#define MMO_STATEMENT_H_ +#pragma once -#include "../ast/ast_types.h" -#include "../util/table.h" -#include "index.h" +#include +#include +#include namespace MicroModelica { @@ -38,8 +37,7 @@ typedef enum { LHS, RHS, LHS_DISCRETES, LHS_STATES } AssignTerm; class Statement { public: Statement(AST_Statement stm, bool initial = false, const std::string& block = ""); - Statement(AST_Statement stm, Option range, bool initial = false, - const std::string& block = ""); + Statement(AST_Statement stm, Option range, bool initial = false, const std::string& block = ""); Statement() : _stm(nullptr), _range(), _block(), _lhs_assignments(), _rhs_assignments(), _lhs_discretes(), _lhs_states(){}; ~Statement() = default; @@ -59,6 +57,7 @@ class Statement { bool isAssignment() const; bool isForStatement() const; inline Option range() { return _range; }; + bool autonomous() const; protected: void initialize(); @@ -82,5 +81,3 @@ class Statement { typedef ModelTable StatementTable; } // namespace IR } // namespace MicroModelica - -#endif /* MMO_STATEMENT_H_ */ diff --git a/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.c b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.c new file mode 100644 index 00000000..d86a96ea --- /dev/null +++ b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include + +#include "init_code_time.h" +#include +#include +#include +#include +#include + +void MOD_settings(SD_simulationSettings settings) +{ + settings->debug = 0; + settings->parallel = FALSE; + settings->hybrid = FALSE; + settings->method = 0; +} + +void MOD_definition(int idx, double *x, double *d, double *a, double t, double *dx) +{ + int _d1; + int i; + if (_is_var_u(idx)) { + _get_u_idxs(idx); + _apply_usage_eq_1(_d1); + if ((i >= 1 && i <= 1000)) { + _der_u(i,0) = _time; + + + } + return; + } +} + +void MOD_zeroCrossing(int idx, double *x, double *d, double *a, double t, double *zc) +{ +} + +void MOD_handlerPos(int idx, double *x, double* q, double *d, double *a, double t) +{ +} + +void MOD_handlerNeg(int idx, double *x, double* q, double *d, double *a, double t) +{ +} + +void MOD_output(int idx, double *x, double *d, double *a, double t, double *out) +{ +} + +void MOD_jacobian(double *x, double *d, double *a, double t, SD_jacMatrices dvdx, double *jac) +{ + int row, row_t, eq_var, c_row, c_row_g; + int col, col_g, col_t; + int x_ind; + double aux; + int _d1; + int _rg_d1; + int i; + SD_cleanJacMatrices(dvdx); + for(row = 1; row <= 1000; row++) { + c_row = _c_index(row); + _get_eq_1_var_idxs(row, eq_var); + _get_u_idxs(eq_var); + } + // Assign Jacobian Matrix values for equation: 0 + for (row = 0; row < 1000; row++) { + for (col = 0; col < dvdx->df_dx[0]->size[row]; col++) { + row_t = dvdx->df_dx[0]->index[row][col]; + _assign_jac(row_t, dvdx->df_dx[0]->value[row][col]); + } + } +} + +void MOD_dependencies(int idx, double *x, double *d, double *a, double t, double *dx, int *map) +{ +} + +void MOD_BDF_definition(double *x, double *d, double *a, double t, double *dx, int *BDFMap, int nBDF) +{ + int idx; + int __bdf_it; + for(__bdf_it = 0; __bdf_it < nBDF; __bdf_it++) { + idx = BDFMap[__bdf_it]; + int _d1; + int i; + if (_is_var_u(idx)) { + _get_u_idxs(idx); + _apply_usage_eq_1(_d1); + if ((i >= 1 && i <= 1000)) { + _eval_dep_u(i,1) = _time; + + + } + continue; + } + } +} + +void QSS_initializeDataStructs(QSS_simulator simulator) +{ + simulator->data = QSS_Data(1000,0,0,1000,0,1,0,"init_code_time"); + QSS_data modelData = simulator->data; + MODEL_DATA_ACCESS(modelData) + int* states = (int*) malloc(1000*sizeof(int)); + int row, eq_var, c_row; + int x_ind; + int _d1; + int _rg_d1; + int i; + int t = 0; + for(i = 1; i<=999; i+=1) { + _init_u(i,0) = _time; + } + _init_u(1000,0) = _time; + for(row = 1; row <= 1000; row++) { + c_row = _c_index(row); + _get_eq_1_var_idxs(row, eq_var); + _get_u_idxs(eq_var); + } + QSS_allocDataMatrix(modelData); + cleanVector(states, 0, 1000); + for(row = 1; row <= 1000; row++) { + c_row = _c_index(row); + _get_eq_1_var_idxs(row, eq_var); + _get_u_idxs(eq_var); + } + SD_setupJacMatrices(modelData->jac_matrices); + simulator->time = QSS_Time(1000,0,1000,0,ST_Binary, NULL); + for(i = 1; i<=1000; i+=1) { + modelData->IT[_input_1(i)] = _idx_u(i,0); + } + simulator->output = SD_Output("init_code_time",0,0,1000,NULL,0,0,CI_Step,SD_Memory,NULL); + SD_output modelOutput = simulator->output; + simulator->model = QSS_Model(MOD_definition, MOD_dependencies, MOD_zeroCrossing, MOD_handlerPos, MOD_handlerNeg, MOD_jacobian, MOD_BDF_definition); + free(states); +} + +void CLC_initializeDataStructs(CLC_simulator simulator) +{ +} + diff --git a/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.h b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.h new file mode 100644 index 00000000..737bb91b --- /dev/null +++ b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.h @@ -0,0 +1,51 @@ +// Model data access macro. + +#define MODEL_DATA_ACCESS(m) \ + double* x = m->x; + +// Coeff multipliers definition. + +#define COEFF_MULTIPLIER(c) COEFF_MULTIPLIER_##c +#define COEFF_MULTIPLIER_0 1 +#define COEFF_MULTIPLIER_1 1 + +// Model Variables Macros + +// Macros definition for variable: u +#define _idx_u(d1,coeff) ((d1-1)) +#define _state_idx_u(d1,coeff) ((d1-1))*2 + coeff +#define _u(d1,coeff) x[_state_idx_u(d1,coeff)] * COEFF_MULTIPLIER(coeff) +#define _init_u(d1,coeff) x[_state_idx_u(d1,coeff)] +#define _q_u(d1,coeff) q[_state_idx_u(d1,coeff)] * COEFF_MULTIPLIER(coeff) +#define _eval_u(d1,coeff) ((d1-1)) +#define _is_var_u(idx) idx >= 0 && idx < 1000 +#define _get_u_idxs(idx)\ + _d1 = (idx)+ 1; +#define _eval_dep_u(d1,coeff) dx[_state_idx_u(d1,coeff)] + + +// Derivative Equations Macros + +// Macros for equation: 1 +#define _apply_usage_eq_1(_d1) \ + i = _d1; +#define _get_eq_1_var_idxs(row, var)\ + _rg_d1 = 0 + (row-1)+ 1;\ + var = _idx_u(_rg_d1,0); + +// Input Matrix Macros + +#define _input_1(i) ((i-1)) + +// Jacobian Macros definition. +#define _assign_jac(r, val) \ + col_t = dvdx->df_dx_t->size[r] + dvdx->df_dx_t->index[r][0]; \ + dvdx->df_dx_t->index[r][0]++; \ + jac[col_t] = val; +#define _c_index(i) (i-1) + +#define _time t + +// Derivative Macros definition. +// Derivative definition for variable: u +#define _der_u(d1,coeff) dx[coeff+1] diff --git a/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.ini b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.ini new file mode 100644 index 00000000..191278e7 --- /dev/null +++ b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.ini @@ -0,0 +1,15 @@ +minstep=1.00000e-14; +zchyst=1.00000e-12; +derdelta=1.00000e-08; +symdiff=1; +lps=0; +nodesize=10000; +jacobian=1; +it=0.00000e+00; +ft=1.00000e+01; +sol="QSS"; +dqmin=(1.00000e-03); +dqrel=(1.00000e-03); +bdf=0; +BDFPartitionDepth=1; +BDFMaxStep=0.00000e+00; diff --git a/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.mo b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.mo new file mode 100644 index 00000000..9b7d86ce --- /dev/null +++ b/src/mmoc/tests/system/gt_data/init_code_time/init_code_time.mo @@ -0,0 +1,30 @@ +model init_code_time + constant Integer N=1000; + Real u[N]; + +initial algorithm + for i in 1:N-1 loop + u[i]:=time; + end for; + u[N]:= time; + +equation + for i in 1:N loop + der(u[i])=time; + end for; + annotation( + + experiment( + MMO_Description="Use time variable in initialization code.", + MMO_Solver=QSS, + MMO_PartitionMethod=Metis, + Jacobian=Dense, + MMO_BDF_PDepth=1, + MMO_BDF_Max_Step=0, + MMO_RandomSeed=0, + StartTime=0, + StopTime=10, + Tolerance={1e-3}, + AbsTolerance={1e-3} + )); +end init_code_time; diff --git a/src/mmoc/tests/system/models_test.cpp b/src/mmoc/tests/system/models_test.cpp index d358ba8e..3b589b11 100644 --- a/src/mmoc/tests/system/models_test.cpp +++ b/src/mmoc/tests/system/models_test.cpp @@ -56,13 +56,47 @@ TEST_P(IModelTests, GenerateCode) EXPECT_TRUE(result.good()); } -const char* models[] = {"adr", "adr2D", "advection", "advection2D", "advection2D_LI", "advection_quoted", - "advectionFlux", "airconds", "aircont", "allow_discrete_integer", "bball_downstairs", "boost", "BouncingBall", - "buck", "buckboost", "buck_circuit", "buck_term", "burgers", "cuk", - "cuk2", "interleaved", "inverters", "lc_line", "lotka_volterra", "mliqss_adr", - "mliqss_buck", "mliqss_test", "mliqss_TYSON", "NeuralNetwork1", "par_airconds", "par_airconds_cont", - "rectifier", "rltest", "rltest_LI", "spikings", "testFor", "test_input", - "TYSON", "VIRplanoS", "virus_replication"}; +const char* models[] = {"adr", + "adr2D", + "advection", + "advection2D", + "advection2D_LI", + "advection_quoted", + "advectionFlux", + "airconds", + "aircont", + "allow_discrete_integer", + "bball_downstairs", + "boost", + "BouncingBall", + "buck", + "buckboost", + "buck_circuit", + "buck_term", + "burgers", + "cuk", + "cuk2", + "init_code_time", + "interleaved", + "inverters", + "lc_line", + "lotka_volterra", + "mliqss_adr", + "mliqss_buck", + "mliqss_test", + "mliqss_TYSON", + "NeuralNetwork1", + "par_airconds", + "par_airconds_cont", + "rectifier", + "rltest", + "rltest_LI", + "spikings", + "testFor", + "test_input", + "TYSON", + "VIRplanoS", + "virus_replication"}; INSTANTIATE_TEST_SUITE_P(Models, IModelTests, testing::ValuesIn(models)); /// @}