Page MenuHomec4science

component_libmultiscale.cc
No OneTemporary

File Metadata

Created
Thu, Aug 1, 10:04

component_libmultiscale.cc

/* -------------------------------------------------------------------------- */
#include "component_libmultiscale.hh"
#include "comm_group.hh"
#include "container_array.hh"
#include "lm_communicator.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
void Component::compute() {
bool need_recompute = this->evalDependencies();
bool amIinGroup = comm_group == nullptr || comm_group->amIinGroup();
if (not amIinGroup) {
throw NotInCommGroup{"For component '" + this->getID() +
" I am not in the right group"};
}
if (!need_recompute && calculated_once)
return;
// evaluate all the inputs
this->evalInputs();
// get the context (comm_group, release) from inputs
this->acquireInputsContext();
// call the chain of compute
this->compute_make_call();
// get context again to acknowledge changes in inputs
this->acquireInputsContext();
// sets the context to outputs
this->propagateContextToOutputs();
calculated_once = true;
}
/* -------------------------------------------------------------------------- */
void Component::evalInputs() {
for (auto &&[name, inp] : this->inputs) {
if (not inp.has_value())
LM_FATAL("Component(" << this->getID() << "): input(" << name
<< ") was not created/computed/connected");
inp.eval();
}
}
/* -------------------------------------------------------------------------- */
void Component::acquireInputsContext() {
if (this->inputs.size() == 0) {
this->incRelease();
}
for (auto &&[name, inp] : this->inputs) {
if (not inp.has_value())
LM_FATAL(name << ": input was not created/computed/connected");
auto &connected_output = inp.get();
if (connected_output.has_argument())
this->acquireContext(connected_output.get());
}
}
/* -------------------------------------------------------------------------- */
bool Component::evalDependencies() {
for (auto &&[name, inp] : this->inputs) {
if (not inp.has_value())
return true;
try {
UInt obj_release;
try {
obj_release = inp.evalRelease();
} catch (AutoDispatch::no_argument &e) {
return true;
}
if (obj_release == UInt(-1))
return true;
if (this->getRelease() < obj_release)
return true;
} catch (...) {
return true;
}
}
return false;
}
/* -------------------------------------------------------------------------- */
void Component::propagateContextToOutputs() {
for (auto &&[name, out] : this->outputs) {
if (not out.has_value())
LM_FATAL(name << ": output was not created/computed/connected");
try {
out.get().acquireContext(*this);
} catch (...) {
DUMP(name << ": output could not receive release", DBG_WARNING);
}
}
}
/* -------------------------------------------------------------------------- */
UInt Component::evalRelease() {
UInt release = this->getRelease();
for (auto &&[k, v] : this->inputs) {
release = std::max(release, v.evalRelease());
}
return release;
}
/* -------------------------------------------------------------------------- */
UInt OutputContainer::evalRelease() const {
UInt release = -1;
try {
release = this->get().getRelease();
if (component)
release = std::max(release, component->evalRelease());
} catch (AutoDispatch::no_argument &e) {
throw e;
} catch (...) {
if (component)
release = component->evalRelease();
}
return release;
}
/* ---------------------------------------------------------------------- */
UInt OutputContainer::getRelease() const {
UInt release = -1;
try {
release = this->get().getRelease();
} catch (...) {
if (component)
release = component->getRelease();
}
return release;
}
/* ---------------------------------------------------------------------- */
void OutputContainer::setRelease(UInt release) {
if (this->has_argument())
this->get().setRelease(release);
}
/* ---------------------------------------------------------------------- */
__END_LIBMULTISCALE__
/* ---------------------------------------------------------------------- */

Event Timeline