Skip to content

Commit

Permalink
Python: include the ability to easily release all values at once.
Browse files Browse the repository at this point in the history
  • Loading branch information
agarny authored Aug 23, 2024
2 parents 08c0c02 + 885f296 commit de000c7
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 81 deletions.
48 changes: 6 additions & 42 deletions src/plugins/dataStore/DataStore/src/datastorepythonwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,6 @@ DataStorePythonWrapper::DataStorePythonWrapper(void *pModule,

//==============================================================================

DataStorePythonWrapper::~DataStorePythonWrapper()
{
// Delete all the values that were requested as NumPy arrays.

for (const auto *numPyArray : mNumPyArrays) {
delete numPyArray;
}
}

//==============================================================================

PyObject * DataStorePythonWrapper::dataStoreValuesDict(const DataStoreValues *pDataStoreValues,
SimulationSupport::SimulationDataUpdatedFunction *pSimulationDataUpdatedFunction)
{
Expand All @@ -392,12 +381,10 @@ PyObject * DataStorePythonWrapper::dataStoreValuesDict(const DataStoreValues *pD

reinterpret_cast<DataStoreValuesDictObject *>(res)->simulationDataUpdatedFunction = pSimulationDataUpdatedFunction;

if (pDataStoreValues != nullptr) {
for (int i = 0, iMax = pDataStoreValues->size(); i < iMax; ++i) {
DataStoreValue *value = pDataStoreValues->at(i);
for (int i = 0, iMax = pDataStoreValues->size(); i < iMax; ++i) {
DataStoreValue *value = pDataStoreValues->at(i);

PythonQtSupport::addObject(res, value->uri(), value);
}
PythonQtSupport::addObject(res, value->uri(), value);
}

return res;
Expand Down Expand Up @@ -445,8 +432,7 @@ double DataStorePythonWrapper::value(DataStoreVariable *pDataStoreVariable,
// Return the value of the given data store variable at the given position
// and for the given run

if ( (pDataStoreVariable != nullptr)
&& (pDataStoreVariable->array() != nullptr)) {
if (pDataStoreVariable->array() != nullptr) {
return pDataStoreVariable->value(pPosition, pRun);
}

Expand All @@ -462,10 +448,10 @@ PyObject * DataStorePythonWrapper::values(DataStoreVariable *pDataStoreVariable,

DataStoreArray *dataStoreArray = pDataStoreVariable->array(pRun);

if ((pDataStoreVariable != nullptr) && (dataStoreArray != nullptr)) {
if (dataStoreArray != nullptr) {
auto numPyArray = new NumPyPythonWrapper(dataStoreArray, pDataStoreVariable->size());

mNumPyArrays << numPyArray;
pDataStoreVariable->mSimulation->mNumPyArrays << numPyArray;

return numPyArray->mNumPyArray;
}
Expand All @@ -477,28 +463,6 @@ PyObject * DataStorePythonWrapper::values(DataStoreVariable *pDataStoreVariable,

//==============================================================================

bool DataStorePythonWrapper::release_values(DataStoreVariable *pDataStoreVariable,
PyObject *pValues)
{
Q_UNUSED(pDataStoreVariable);

// Release the given NumPy array

for (auto it = mNumPyArrays.begin(); it != mNumPyArrays.end(); ++it) {
if ((*it)->mNumPyArray == pValues) {
delete *it;

mNumPyArrays.erase(it);

return true;
}
}

return false;
}

//==============================================================================

NumPyPythonWrapper::NumPyPythonWrapper(DataStoreArray *pDataStoreArray,
quint64 pSize) :
mArray(pDataStoreArray)
Expand Down
16 changes: 10 additions & 6 deletions src/plugins/dataStore/DataStore/src/datastorepythonwrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ along with this program. If not, see <https://gnu.org/licenses>.
//==============================================================================

namespace OpenCOR {

//==============================================================================

namespace SimulationSupport {
class SimulationSupportPythonWrapper;
} // namespace SimulationSupport

//==============================================================================

namespace DataStore {

//==============================================================================
Expand All @@ -56,15 +65,11 @@ class DataStorePythonWrapper : public QObject

public:
explicit DataStorePythonWrapper(void *pModule, QObject *pParent);
~DataStorePythonWrapper() override;

static DATASTORE_EXPORT PyObject * dataStoreValuesDict(const DataStoreValues *pDataStoreValues,
SimulationSupport::SimulationDataUpdatedFunction *pSimulationDataUpdatedFunction);
static DATASTORE_EXPORT PyObject * dataStoreVariablesDict(const DataStoreVariables &pDataStoreVariables);

private:
QList<NumPyPythonWrapper *> mNumPyArrays;

public slots:
PyObject * variables(OpenCOR::DataStore::DataStore *pDataStore);
PyObject * voi_and_variables(OpenCOR::DataStore::DataStore *pDataStore);
Expand All @@ -73,8 +78,6 @@ public slots:
quint64 pPosition, int pRun = -1) const;
PyObject * values(OpenCOR::DataStore::DataStoreVariable *pDataStoreVariable,
int pRun = -1);
bool release_values(OpenCOR::DataStore::DataStoreVariable *pDataStoreVariable,
PyObject *pValues);
};

//==============================================================================
Expand All @@ -84,6 +87,7 @@ class NumPyPythonWrapper : public QObject
Q_OBJECT

friend class DataStorePythonWrapper;
friend class SimulationSupport::SimulationSupportPythonWrapper;

public:
explicit NumPyPythonWrapper(DataStoreArray *pDataStoreArray,
Expand Down
13 changes: 8 additions & 5 deletions src/plugins/datastoreinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ double * DataStoreVariableRun::values() const

//==============================================================================

DataStoreVariable::DataStoreVariable(double *pValue) :
DataStoreVariable::DataStoreVariable(SimulationSupport::Simulation *pSimulation, double *pValue) :
mSimulation(pSimulation),
mValue(pValue)
{
}
Expand Down Expand Up @@ -795,9 +796,11 @@ DataStoreVariables DataStoreExportData::variables() const

//==============================================================================

DataStore::DataStore(const QString &pUri) :
DataStore::DataStore(SimulationSupport::Simulation *pSimulation,
const QString &pUri) :
mSimulation(pSimulation),
mUri(pUri),
mVoi(new DataStoreVariable())
mVoi(new DataStoreVariable(mSimulation))
{
}

Expand Down Expand Up @@ -921,7 +924,7 @@ DataStoreVariables DataStore::addVariables(double *pValues, int pCount)
DataStoreVariables variables;

for (int i = 0; i < pCount; ++i, ++pValues) {
variables << new DataStoreVariable(pValues);
variables << new DataStoreVariable(mSimulation, pValues);
}

mVariables << variables;
Expand All @@ -935,7 +938,7 @@ DataStoreVariable * DataStore::addVariable(double *pValue)
{
// Add a variable to our data store

auto variable = new DataStoreVariable(pValue);
auto variable = new DataStoreVariable(mSimulation, pValue);

mVariables << variable;

Expand Down
20 changes: 18 additions & 2 deletions src/plugins/datastoreinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ along with this program. If not, see <https://gnu.org/licenses>.
//==============================================================================

namespace OpenCOR {

//==============================================================================

namespace SimulationSupport {
class Simulation;
} // namespace SimulationSupport

//==============================================================================

namespace DataStore {

//==============================================================================
Expand Down Expand Up @@ -126,8 +135,10 @@ class DataStoreVariable : public QObject
{
Q_OBJECT

friend class DataStorePythonWrapper;

public:
explicit DataStoreVariable(double *pValue = nullptr);
explicit DataStoreVariable(SimulationSupport::Simulation *pSimulation, double *pValue = nullptr);
~DataStoreVariable() override;

static bool compare(DataStoreVariable *pVariable1,
Expand Down Expand Up @@ -168,6 +179,8 @@ public slots:
void setValue(double pValue);

private:
SimulationSupport::Simulation *mSimulation;

int mType = -1;
QString mUri;
QString mName;
Expand Down Expand Up @@ -287,7 +300,8 @@ class DataStore : public QObject
Q_OBJECT

public:
explicit DataStore(const QString &pUri = {});
explicit DataStore(SimulationSupport::Simulation *pSimulation,
const QString &pUri = {});
~DataStore() override;

bool addRun(quint64 pCapacity);
Expand All @@ -313,6 +327,8 @@ public slots:
OpenCOR::DataStore::DataStoreVariable * voi() const;

private:
SimulationSupport::Simulation *mSimulation;

QString mUri;

DataStoreVariable *mVoi = nullptr;
Expand Down
62 changes: 38 additions & 24 deletions src/plugins/support/PythonSupport/tests/data/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from enum import Enum
import math
import os

import opencor as oc


class Mode(Enum):
RELEASE_NOTHING = 0
RELEASE_VALUES = 1
RELEASE_ALL_VALUES = 2


def header(title, first=True):
if not first:
print()
Expand Down Expand Up @@ -50,7 +57,7 @@ def print_values(data):
str_value(data[data_len - 3]), str_value(data[data_len - 2]), str_value(data[data_len - 1])))


def values(data, data_type, indent=''):
def values(simulation, mode, data, data_type, indent=''):
if data:
print('%s - %s:' % (indent, data_type))

Expand All @@ -62,14 +69,15 @@ def values(data, data_type, indent=''):

print_values(values)

item.release_values(values)
if mode == Mode.RELEASE_VALUES:
simulation.release_values(values)
except Exception:
print(str_value(item.value()))
else:
print('%s - %s: empty' % (indent, data_type))


def run_simulation(simulation, step):
def run_simulation(simulation, mode, step):
# Run the simulation

print(' - Run simulation [%d]:' % step)
Expand All @@ -83,10 +91,10 @@ def run_simulation(simulation, step):
print(' - ODE solver: %s' % data.ode_solver_name())
print(' - Initial values:')

values(data.constants(), 'Constants', ' ')
values(data.states(), 'States', ' ')
values(data.rates(), 'Rates', ' ')
values(data.algebraic(), 'Algebraic', ' ')
values(simulation, mode, data.constants(), 'Constants', ' ')
values(simulation, mode, data.states(), 'States', ' ')
values(simulation, mode, data.rates(), 'Rates', ' ')
values(simulation, mode, data.algebraic(), 'Algebraic', ' ')

simulation.run()

Expand All @@ -99,10 +107,13 @@ def run_simulation(simulation, step):
print(' - Result values:')
print(' - Number of points: %d' % states['main/x'].values_count())

values(results.constants(), 'Constants', ' ')
values(states, 'States', ' ')
values(results.rates(), 'Rates', ' ')
values(results.algebraic(), 'Algebraic', ' ')
values(simulation, mode, results.constants(), 'Constants', ' ')
values(simulation, mode, states, 'States', ' ')
values(simulation, mode, results.rates(), 'Rates', ' ')
values(simulation, mode, results.algebraic(), 'Algebraic', ' ')

if mode == Mode.RELEASE_ALL_VALUES:
simulation.release_all_values()


def test_simulation(title, file_name_or_url, first=True, expected_fail=False):
Expand Down Expand Up @@ -146,7 +157,7 @@ def test_simulation(title, file_name_or_url, first=True, expected_fail=False):
print(' - Ending point: %f' % data.ending_point())
print(' - Point interval: %f' % data.point_interval())

run_simulation(simulation, 1)
run_simulation(simulation, Mode.RELEASE_ALL_VALUES , 1)

# Run #2: change a few settings and rerun the simulation

Expand All @@ -167,18 +178,18 @@ def test_simulation(title, file_name_or_url, first=True, expected_fail=False):
print(' - Point interval: %f' % data.point_interval())
print(' - ODE solver: %s' % data.ode_solver_name())

run_simulation(simulation, 2)
run_simulation(simulation, Mode.RELEASE_VALUES, 2)

# Run #3: carry on from the previous run

run_simulation(simulation, 3)
run_simulation(simulation, Mode.RELEASE_NOTHING, 3)

# Close the simulation

oc.close_simulation(simulation)


def run_solver_simulation(simulation, solver_name):
def run_solver_simulation(simulation, mode, solver_name):
data = simulation.data()

data.set_ode_solver(solver_name)
Expand All @@ -192,21 +203,24 @@ def run_solver_simulation(simulation, solver_name):

print(' - %s:' % solver_name)

values(results.constants(), 'Constants')
values(results.states(), 'States')
values(results.rates(), 'Rates')
values(results.algebraic(), 'Algebraic')
values(simulation, mode, results.constants(), 'Constants')
values(simulation, mode, results.states(), 'States')
values(simulation, mode, results.rates(), 'Rates')
values(simulation, mode, results.algebraic(), 'Algebraic')

if mode == Mode.RELEASE_ALL_VALUES:
simulation.release_all_values()


def run_simulations(model, title):
header(title)

simulation = open_simulation(model)

run_solver_simulation(simulation, 'CVODE')
run_solver_simulation(simulation, 'Euler (forward)')
run_solver_simulation(simulation, 'Heun')
run_solver_simulation(simulation, 'Runge-Kutta (2nd order)')
run_solver_simulation(simulation, 'Runge-Kutta (4th order)')
run_solver_simulation(simulation, Mode.RELEASE_NOTHING, 'CVODE')
run_solver_simulation(simulation, Mode.RELEASE_VALUES, 'Euler (forward)')
run_solver_simulation(simulation, Mode.RELEASE_ALL_VALUES, 'Heun')
run_solver_simulation(simulation, Mode.RELEASE_VALUES, 'Runge-Kutta (2nd order)')
run_solver_simulation(simulation, Mode.RELEASE_NOTHING, 'Runge-Kutta (4th order)')

oc.close_simulation(simulation)
Loading

0 comments on commit de000c7

Please sign in to comment.