Skip to content

Commit

Permalink
[clib] Disambiguate objects in Cabinet<T>::index
Browse files Browse the repository at this point in the history
Add object parents to Cabinet, which are used to disambiguate objects
that are created automatically, for example ThermoPhase / Kinetics /
Transport that are instantiated together with new Solution objects.
  • Loading branch information
ischoegl committed Aug 4, 2024
1 parent 99262fa commit 2f87d63
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 43 deletions.
4 changes: 4 additions & 0 deletions include/cantera/clib/ct.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ extern "C" {
CANTERA_CAPI int soln_adjacentName(int n, int a, int lennm, char* nm);

CANTERA_CAPI int thermo_newFromFile(const char* filename, const char* phasename); //!< @todo remove from .NET and Fortran interfaces
CANTERA_CAPI int thermo_parent(int n);
CANTERA_CAPI int thermo_size();
CANTERA_CAPI int thermo_del(int n);
CANTERA_CAPI size_t thermo_nElements(int n);
CANTERA_CAPI size_t thermo_nSpecies(int n);
Expand Down Expand Up @@ -125,6 +127,7 @@ extern "C" {
CANTERA_CAPI int kin_newFromFile(const char* filename, const char* phasename,
int reactingPhase, int neighbor1, int neighbor2,
int neighbor3, int neighbor4); //!< @todo remove from .NET and Fortran interfaces
CANTERA_CAPI int kin_parent(int n);
CANTERA_CAPI int kin_del(int n);
CANTERA_CAPI size_t kin_nSpecies(int n);
CANTERA_CAPI size_t kin_nReactions(int n);
Expand Down Expand Up @@ -159,6 +162,7 @@ extern "C" {

CANTERA_CAPI int trans_newDefault(int th, int loglevel); //!< @todo remove from .NET and Fortran interfaces
CANTERA_CAPI int trans_new(const char* model, int th, int loglevel); //!< @todo remove from .NET and Fortran interfaces
CANTERA_CAPI int trans_parent(int n);
CANTERA_CAPI int trans_del(int n);
CANTERA_CAPI int trans_transportModel(int n, int lennm, char* nm);
CANTERA_CAPI double trans_viscosity(int n);
Expand Down
51 changes: 45 additions & 6 deletions src/clib/Cabinet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "cantera/base/ctexceptions.h"
#include "cantera/base/utilities.h"
#include <unordered_map>
#include <boost/range/adaptor/reversed.hpp>

namespace Cantera {

Expand Down Expand Up @@ -51,6 +52,7 @@ class SharedCabinet
{
public:
typedef vector<shared_ptr<M>>& dataRef;
typedef vector<int>& parentRef;
typedef std::unordered_map<const M*, set<int>>& lookupRef;

/**
Expand All @@ -61,12 +63,14 @@ class SharedCabinet
/**
* Add a new object. The index of the object is returned.
*/
static int add(shared_ptr<M> obj) {
static int add(shared_ptr<M> obj, int parent=-1) {
dataRef data = getData();
data.push_back(obj);
parentRef parents = getParents();
parents.push_back(parent);
int idx = static_cast<int>(data.size()) - 1;
lookupRef lookup = getLookup();
if (index(*obj) >= 0) {
if (lookup.count(obj.get())) {
lookup[obj.get()].insert(idx);
} else {
lookup[obj.get()] = {idx};
Expand Down Expand Up @@ -97,6 +101,7 @@ class SharedCabinet
*/
static int reset() {
getData().clear();
getParents().clear();
getLookup().clear();
return 0;
}
Expand All @@ -107,7 +112,7 @@ class SharedCabinet
static int copy(int n) {
dataRef data = getData();
try {
return add(*data[n]);
return add(*data[n]); // do not copy parent to avoid ambiguous data
} catch (std::exception& err) {
throw CanteraError("SharedCabinet::newCopy", err.what());
}
Expand Down Expand Up @@ -138,6 +143,17 @@ class SharedCabinet
}
}

/**
* Return handle of parent to object n.
*/
static int parent(int n) {
parentRef parents = getParents();
if (n < 0 || n >= len(parents)) {
throw CanteraError("SharedCabinet::parent", "Index {} out of range.", n);
}
return parents[n];
}

/**
* Return a shared pointer to object n.
*/
Expand Down Expand Up @@ -189,13 +205,19 @@ class SharedCabinet
* object is not in the SharedCabinet. If multiple indices reference the same
* object, the index of the last one added is returned.
*/
static int index(const M& obj) {
static int index(const M& obj, int parent=-1) {
lookupRef lookup = getLookup();
if (!lookup.count(&obj)) {
return -1;
}
set<int>& entry = lookup.at(&obj);
return *entry.rbegin();
parentRef parents = getParents();
for (const auto e : boost::adaptors::reverse(entry)) {
if (parents[e] == parent) {
return e;
}
}
return -2; // not found
}

private:
Expand All @@ -211,6 +233,18 @@ class SharedCabinet
return s_storage->m_table;
}

/**
* Static function that returns a pointer to the list of parent object handles of
* the singleton SharedCabinet<M> instance. All member functions should
* access the data through this function.
*/
static parentRef getParents() {
if (s_storage == nullptr) {
s_storage = new SharedCabinet<M>();
}
return s_storage->m_parents;
}

/**
* Static function that returns a pointer to the reverse lookup table of
* the singleton SharedCabinet<M> instance. All member functions should
Expand All @@ -234,7 +268,12 @@ class SharedCabinet
std::unordered_map<const M*, set<int>> m_lookup;

/**
* list to hold pointers to objects.
* List to hold handles of parent objects.
*/
vector<int> m_parents;

/**
* List to hold pointers to objects.
*/
vector<shared_ptr<M>> m_table;
};
Expand Down
79 changes: 59 additions & 20 deletions src/clib/ct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ extern "C" {
{
try {
auto soln = newSolution(infile, name, transport);
int id = SolutionCabinet::add(soln);
// add associated objects
ThermoCabinet::add(soln->thermo());
ThermoCabinet::add(soln->thermo(), id);
if (soln->kinetics()) {
KineticsCabinet::add(soln->kinetics());
KineticsCabinet::add(soln->kinetics(), id);
}
if (soln->transport()) {
TransportCabinet::add(soln->transport());
TransportCabinet::add(soln->transport(), id);
}
return SolutionCabinet::add(soln);
return id;
} catch (...) {
return handleAllExceptions(-1, ERR);
}
Expand All @@ -93,14 +94,15 @@ extern "C" {
// adjacent phases can be retrieved via soln_adjacent
}
// add associated objects
ThermoCabinet::add(soln->thermo());
int id = SolutionCabinet::add(soln);
ThermoCabinet::add(soln->thermo(), id);
if (soln->kinetics()) {
KineticsCabinet::add(soln->kinetics());
KineticsCabinet::add(soln->kinetics(), id);
}
if (soln->transport()) {
TransportCabinet::add(soln->transport());
TransportCabinet::add(soln->transport(), id);
}
return SolutionCabinet::add(soln);
return id;
} catch (...) {
return handleAllExceptions(-1, ERR);
}
Expand All @@ -112,18 +114,18 @@ extern "C" {
if (n >= 0 && n < SolutionCabinet::size()) {
// remove all associated objects
auto soln = SolutionCabinet::at(n);
int index = ThermoCabinet::index(*(soln->thermo()));
int index = ThermoCabinet::index(*(soln->thermo()), n);
if (index >= 0) {
ThermoCabinet::del(index);
}
if (soln->kinetics()) {
index = KineticsCabinet::index(*(soln->kinetics()));
index = KineticsCabinet::index(*(soln->kinetics()), n);
if (index >= 0) {
KineticsCabinet::del(index);
}
}
if (soln->transport()) {
index = TransportCabinet::index(*(soln->transport()));
index = TransportCabinet::index(*(soln->transport()), n);
if (index >= 0) {
TransportCabinet::del(index);
}
Expand Down Expand Up @@ -151,7 +153,7 @@ extern "C" {
{
try {
auto soln = SolutionCabinet::at(n);
return ThermoCabinet::index(*soln->thermo());
return ThermoCabinet::index(*soln->thermo(), n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
Expand All @@ -164,7 +166,7 @@ extern "C" {
if (!soln->kinetics()) {
return -1;
}
return KineticsCabinet::index(*(soln->kinetics()));
return KineticsCabinet::index(*(soln->kinetics()), n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
Expand All @@ -177,7 +179,7 @@ extern "C" {
if (!soln->transport()) {
return -1;
}
return TransportCabinet::index(*(soln->transport()));
return TransportCabinet::index(*(soln->transport()), n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
Expand All @@ -188,9 +190,9 @@ extern "C" {
try {
auto soln = SolutionCabinet::at(n);
TransportCabinet::del(
TransportCabinet::index(*(soln->transport())));
TransportCabinet::index(*(soln->transport()), n));
soln->setTransportModel(model);
return TransportCabinet::add(soln->transport());
return TransportCabinet::add(soln->transport(), n);
} catch (...) {
return handleAllExceptions(-1, ERR);
}
Expand All @@ -214,14 +216,15 @@ extern "C" {
}
auto adj = soln->adjacent(a);
// add associated objects
ThermoCabinet::add(adj->thermo());
int id = SolutionCabinet::add(adj);
ThermoCabinet::add(adj->thermo(), id);
if (adj->kinetics()) {
KineticsCabinet::add(adj->kinetics());
KineticsCabinet::add(adj->kinetics(), id);
}
if (adj->transport()) {
TransportCabinet::add(adj->transport());
TransportCabinet::add(adj->transport(), id);
}
return SolutionCabinet::add(adj);
return id;
} catch (...) {
return handleAllExceptions(-2, ERR);
}
Expand Down Expand Up @@ -1726,6 +1729,42 @@ extern "C" {
}
}

int thermo_parent(int n)
{
try {
return ThermoCabinet::parent(n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
}

int thermo_size()
{
try {
return ThermoCabinet::size();
} catch (...) {
return handleAllExceptions(-1, ERR);
}
}

int kin_parent(int n)
{
try {
return KineticsCabinet::parent(n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
}

int trans_parent(int n)
{
try {
return TransportCabinet::parent(n);
} catch (...) {
return handleAllExceptions(-2, ERR);
}
}

int thermo_del(int n)
{
try {
Expand Down
Loading

0 comments on commit 2f87d63

Please sign in to comment.