Skip to content

Commit

Permalink
Generator: take into account tracked/untracked variables when generat…
Browse files Browse the repository at this point in the history
…ing some code.
  • Loading branch information
agarny committed Oct 26, 2024
1 parent 9c34561 commit ba471ff
Show file tree
Hide file tree
Showing 13 changed files with 188 additions and 247 deletions.
30 changes: 14 additions & 16 deletions src/analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2777,7 +2777,7 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model)
return;
}

// Add a dummy equation for each of our true (i.e. non-computed) constants.
// Add a dummy equation for each of our true constants.
// Note: this is so that a constant can be marked as an external variable.

for (const auto &internalVariable : mInternalVariables) {
Expand All @@ -2797,9 +2797,7 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model)
std::map<AnalyserInternalEquationPtr, AnalyserEquationPtr> aie2aeMappings;

for (const auto &internalEquation : mInternalEquations) {
auto equation = AnalyserEquation::AnalyserEquationImpl::create();

aie2aeMappings.emplace(internalEquation, equation);
aie2aeMappings.emplace(internalEquation, AnalyserEquation::AnalyserEquationImpl::create());
}

// Start making our internal equations available through our API.
Expand Down Expand Up @@ -2850,11 +2848,6 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model)

break;
default: // AnalyserEquation::Type::UNKNOWN.
// The equation type is unknown, which means that it is a dummy
// equation for a true (i.e. non-computed) constant (so that it
// could have been marked as an external variable), so we skip
// it since the constant wasn't marked as an external variable.

continue;
}
}
Expand Down Expand Up @@ -3029,6 +3022,13 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model)
if (variable != nullptr) {
for (const auto &equation : variable->equations()) {
if (std::find(equationDependencies.begin(), equationDependencies.end(), equation) == equationDependencies.end()) {
if (variable->type() == AnalyserVariable::Type::CONSTANT) {
// This is a constant, so keep track of it in case it is untracked and in case we need to
// generate some code for it.

equation->mPimpl->mConstant = variable;
}

equationDependencies.push_back(equation);
}
}
Expand Down Expand Up @@ -3080,15 +3080,13 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model)
mModel->mPimpl->mEquations.push_back(equation);
}

// Clean up our equations' dependencies.
// Note: indeed, some equations may have a dependency on the variable of
// integration (for which there is no equation) and/or one or several
// true (i.e. non-computed) constants (for which there are no proper
// equations). So, we need to remove those dependencies, and obviously
// this can only be done once all our equations are ready.
// Remove the dummy equations for our constants.
// Note: indeed, some equations may have a dependency on one or several constants (for which there are no proper
// equations). So, we need to remove those dependencies, and obviously this can only be done once all our
// equations are ready.

for (const auto &equation : mModel->mPimpl->mEquations) {
equation->mPimpl->cleanUpDependencies();
equation->mPimpl->removeDummyDependencies();
}

// Determine whether our equations are state/rate based.
Expand Down
24 changes: 15 additions & 9 deletions src/analyserequation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,26 @@ AnalyserEquationPtr AnalyserEquation::AnalyserEquationImpl::create()
return std::shared_ptr<AnalyserEquation> {new AnalyserEquation {}};
}

bool AnalyserEquation::AnalyserEquationImpl::isEmptyDependency(const AnalyserEquationWeakPtr &dependency)
bool AnalyserEquation::AnalyserEquationImpl::isDummyDependency(const AnalyserEquationWeakPtr &dependency)
{
auto variables = libcellml::variables(dependency.lock());
return libcellml::variables(dependency.lock()).empty();
}

void AnalyserEquation::AnalyserEquationImpl::removeDummyDependencies()
{
// Keep track of our constant dependencies, so that we can generate some code for them, should they be untracked.

if (std::any_of(variables.begin(), variables.end(), [](const auto &v) { return v != nullptr; })) {
return false;
for (const auto &dependency : mDependencies) {
auto constantDependency = dependency.lock()->mPimpl->mConstant;

if (isDummyDependency(dependency)) {
mConstantDependencies.push_back(constantDependency);
}
}

return true;
}
// Effectively remove our dummy dependencies.

void AnalyserEquation::AnalyserEquationImpl::cleanUpDependencies()
{
mDependencies.erase(std::remove_if(mDependencies.begin(), mDependencies.end(), isEmptyDependency), mDependencies.end());
mDependencies.erase(std::remove_if(mDependencies.begin(), mDependencies.end(), isDummyDependency), mDependencies.end());
}

AnalyserEquation::AnalyserEquation()
Expand Down
7 changes: 5 additions & 2 deletions src/analyserequation_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,22 @@ struct AnalyserEquation::AnalyserEquationImpl
size_t mNlaSystemIndex;
bool mIsStateRateBased = false;

AnalyserVariablePtr mConstant;

std::vector<AnalyserVariablePtr> mStates;
std::vector<AnalyserVariablePtr> mComputedConstants;
std::vector<AnalyserVariablePtr> mAlgebraic;
std::vector<AnalyserVariablePtr> mExternals;

std::vector<AnalyserVariablePtr> mConstantDependencies;
std::vector<AnalyserEquationWeakPtr> mDependencies;
std::vector<AnalyserEquationWeakPtr> mNlaSiblings;

static AnalyserEquationPtr create();

static bool isEmptyDependency(const AnalyserEquationWeakPtr &dependency);
static bool isDummyDependency(const AnalyserEquationWeakPtr &dependency);

void cleanUpDependencies();
void removeDummyDependencies();
};

} // namespace libcellml
36 changes: 3 additions & 33 deletions src/analysermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,39 +237,9 @@ AnalyserVariablePtr AnalyserModel::variable(const VariablePtr &variable)
return {};
}

if (mPimpl->mVoi != nullptr) {
if (areEquivalentVariables(mPimpl->mVoi->variable(), variable)) {
return mPimpl->mVoi;
}
}

for (const auto &state : mPimpl->mStates) {
if (areEquivalentVariables(state->variable(), variable)) {
return state;
}
}

for (const auto &constant : mPimpl->mConstants) {
if (areEquivalentVariables(constant->variable(), variable)) {
return constant;
}
}

for (const auto &computedConstant : mPimpl->mComputedConstants) {
if (areEquivalentVariables(computedConstant->variable(), variable)) {
return computedConstant;
}
}

for (const auto &algebraic : mPimpl->mAlgebraic) {
if (areEquivalentVariables(algebraic->variable(), variable)) {
return algebraic;
}
}

for (const auto &external : mPimpl->mExternals) {
if (areEquivalentVariables(external->variable(), variable)) {
return external;
for (const auto &modelVariable : variables(shared_from_this())) {
if (areEquivalentVariables(variable, modelVariable->variable())) {
return modelVariable;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/api/libcellml/analyserequation.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace libcellml {
class LIBCELLML_EXPORT AnalyserEquation
{
friend class Analyser;
friend class Generator;

public:
/**
Expand Down
7 changes: 7 additions & 0 deletions src/api/libcellml/analysermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ limitations under the License.

#include "libcellml/analyser.h"

#ifndef SWIG
template class LIBCELLML_EXPORT std::weak_ptr<libcellml::AnalyserModel>;
#endif

namespace libcellml {

/**
Expand All @@ -27,6 +31,9 @@ namespace libcellml {
* CellML Analyser.
*/
class LIBCELLML_EXPORT AnalyserModel
#ifndef SWIG
: public std::enable_shared_from_this<AnalyserModel>
#endif
{
friend class Analyser;
friend class Generator;
Expand Down
Loading

0 comments on commit ba471ff

Please sign in to comment.