mirror of
https://github.com/nasa/trick.git
synced 2025-02-06 19:09:20 +00:00
703 lines
22 KiB
C++
703 lines
22 KiB
C++
|
|
|
|
// Local includes
|
|
#include "trick/IntegLoopScheduler.hh"
|
|
|
|
#include "trick/IntegLoopManager.hh"
|
|
#include "trick/IntegJobClassId.hh"
|
|
|
|
// Trick includes
|
|
#include "trick/exec_proto.h"
|
|
#include "trick/message_proto.h"
|
|
#include "trick/message_type.h"
|
|
#include "trick/JobData.hh"
|
|
|
|
// System includes
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <cstdarg>
|
|
#include <math.h>
|
|
|
|
|
|
// Anonymous namespace for local functions
|
|
namespace {
|
|
/**
|
|
* Process the enabled job in the provided job queue.
|
|
* @param job_queue Job queue to be processed.
|
|
*/
|
|
inline void call_jobs (
|
|
Trick::ScheduledJobQueue & job_queue)
|
|
{
|
|
Trick::JobData * curr_job;
|
|
job_queue.reset_curr_index();
|
|
while ((curr_job = job_queue.get_next_job()) != NULL) {
|
|
curr_job->call();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
The singleton IntegrationManager object.
|
|
It is a protected static member of the IntegLoopScheduler class.
|
|
*/
|
|
Trick::IntegrationManager Trick::IntegLoopScheduler::manager;
|
|
|
|
/**
|
|
The Integrator currently being processed.
|
|
*/
|
|
Trick::Integrator* trick_curr_integ = NULL;
|
|
|
|
/**
|
|
Non-default constructor.
|
|
@param in_cycle The time interval at which the loop's integrate function is called
|
|
@param in_parent_so Pointer to the parent sim object.
|
|
*/
|
|
Trick::IntegLoopScheduler::IntegLoopScheduler(
|
|
double in_cycle, Trick::SimObject * in_parent_so)
|
|
:
|
|
Scheduler (),
|
|
|
|
verbosity (0),
|
|
last_step_deriv (false),
|
|
first_step_deriv (false),
|
|
integ_ptr (NULL),
|
|
sim_objects (),
|
|
|
|
nominal_cycle (in_cycle),
|
|
next_cycle (in_cycle),
|
|
parent_sim_object (in_parent_so),
|
|
pre_integ_jobs (),
|
|
deriv_jobs (),
|
|
integ_jobs (),
|
|
dynamic_event_jobs (),
|
|
post_integ_jobs ()
|
|
{
|
|
complete_construction();
|
|
}
|
|
|
|
/**
|
|
Default constructor
|
|
*/
|
|
Trick::IntegLoopScheduler::IntegLoopScheduler()
|
|
:
|
|
Scheduler (),
|
|
|
|
verbosity (0),
|
|
last_step_deriv (false),
|
|
first_step_deriv (false),
|
|
integ_ptr (NULL),
|
|
sim_objects (),
|
|
|
|
nominal_cycle (),
|
|
next_cycle (),
|
|
parent_sim_object (NULL),
|
|
pre_integ_jobs (),
|
|
deriv_jobs (),
|
|
integ_jobs (),
|
|
dynamic_event_jobs (),
|
|
post_integ_jobs ()
|
|
{
|
|
complete_construction();
|
|
}
|
|
|
|
/**
|
|
Complete the construction of an integration loop.
|
|
All constructors but the copy constructor call this method.
|
|
*/
|
|
void Trick::IntegLoopScheduler::complete_construction()
|
|
{
|
|
|
|
// Create the class_name to class_id mapping.
|
|
class_map["derivative"] = Trick::DerivativeJobClassId;
|
|
class_to_queue[Trick::DerivativeJobClassId] = &deriv_jobs;
|
|
|
|
class_map["integration"] = Trick::IntegrationJobClassId;
|
|
class_to_queue[Trick::IntegrationJobClassId] = &integ_jobs;
|
|
|
|
class_map["dynamic_event"] = Trick::DynamicEventJobClassId;
|
|
class_to_queue[Trick::DynamicEventJobClassId] = &dynamic_event_jobs;
|
|
|
|
class_map["post_integration"] = Trick::PostIntegrationJobClassId;
|
|
class_to_queue[Trick::PostIntegrationJobClassId] = &post_integ_jobs;
|
|
|
|
class_map["pre_integration"] = Trick::PreIntegrationJobClassId;
|
|
class_to_queue[Trick::PreIntegrationJobClassId] = &pre_integ_jobs;
|
|
}
|
|
|
|
/**
|
|
Find the specified sim object in the set of objects managed by this loop.
|
|
@return Iterator pointing to the object, or to sim_objects.end() if not found.
|
|
@param sim_obj Object to be found.
|
|
*/
|
|
Trick::IntegLoopScheduler::SimObjectVector::iterator
|
|
Trick::IntegLoopScheduler::find_sim_object(Trick::SimObject & sim_obj)
|
|
{
|
|
return std::find (sim_objects.begin(), sim_objects.end(), &sim_obj);
|
|
}
|
|
|
|
/**
|
|
Add jobs from specified object.
|
|
@param in_obj Pointer to the sim object from which the integration jobs
|
|
should be added.
|
|
Deprecated!
|
|
*/
|
|
int Trick::IntegLoopScheduler::add_integ_jobs_from_sim_object (
|
|
Trick::SimObject * in_obj)
|
|
{
|
|
|
|
unsigned int ii ;
|
|
std::map<std::string, int>::iterator class_id_it ;
|
|
std::map<int, Trick::ScheduledJobQueue *>::iterator queue_it ;
|
|
Trick::ScheduledJobQueue * curr_queue ;
|
|
JobData * job ;
|
|
|
|
// TODO: add check to make sure the integ job is not set to another object before adding job to queue
|
|
// TODO: Check other simobjects for jobs that are to be added to this integration
|
|
// TODO: check all integration schemes for integrate structures are the same
|
|
|
|
// For each of the jobs in the SimObject
|
|
for ( ii = 0 ; ii < in_obj->jobs.size() ; ii++ ) {
|
|
job = in_obj->jobs[ii] ;
|
|
|
|
// if the job's job_class_name is in the class map then set its job_class to the corresponding class_id
|
|
if ( (class_id_it = class_map.find(job->job_class_name)) != class_map.end() ) {
|
|
|
|
// set this integration loop frequency to all its individual jobs
|
|
job->cycle = nominal_cycle;
|
|
|
|
job->job_class = class_id_it->second ;
|
|
|
|
if ( (queue_it = class_to_queue.find(job->job_class)) != class_to_queue.end() ) {
|
|
curr_queue = queue_it->second ;
|
|
curr_queue->push_ignore_sim_object( job ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// Overload of Scheduler::add_sim_object that does nothing.
|
|
int Trick::IntegLoopScheduler::add_sim_object(Trick::SimObject * sim_obj __attribute((unused))) {
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Add a sim object to the set of objects integrated by this integration loop.
|
|
The job queues for this loop are rebuild after adding the sim object.
|
|
@param sim_obj Address of the sim object that should be added to scheduler.
|
|
*/
|
|
int Trick::IntegLoopScheduler::add_sim_object(Trick::SimObject & sim_obj)
|
|
{
|
|
// Disallow duplicate objects.
|
|
if (find_sim_object (sim_obj) != sim_objects.end()) {
|
|
message_publish (
|
|
MSG_ERROR,
|
|
"Integ Scheduler ERROR: "
|
|
"SimObject '%s' is already managed by this integration loop.\n",
|
|
sim_obj.name.c_str());
|
|
return 1;
|
|
}
|
|
|
|
// Object is not in the set. Add it.
|
|
sim_objects.push_back (&sim_obj);
|
|
// Rebuild jobs, but only if the manager has been initialized.
|
|
// Adding jobs prior to the initial build are legal; they are addressed
|
|
// by an S_define-level call to rebuild_jobs.
|
|
if (! manager.is_empty()) {
|
|
// If this object is already managed by a different integration loop,
|
|
// remove it from that other loop to avoid integrating the object twice.
|
|
IntegLoopScheduler * other = manager.get_integrated_by (&sim_obj);
|
|
if (other != NULL) {
|
|
other->remove_sim_object (sim_obj);
|
|
}
|
|
|
|
// Now rebuild our jobs.
|
|
rebuild_jobs();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Remove a sim object from the objects integrated by this integration loop.
|
|
The job queues for this loop are rebuilt after removing the sim object.
|
|
@param sim_obj Address of sim object that should be removed from scheduler.
|
|
*/
|
|
int Trick::IntegLoopScheduler::remove_sim_object(Trick::SimObject & sim_obj)
|
|
{
|
|
// Find the object in the set of objects managed by this loop;
|
|
// The object must be in that set if it is to be removed.
|
|
SimObjectVector::iterator iter = find_sim_object (sim_obj);
|
|
if (iter == sim_objects.end()) {
|
|
message_publish (
|
|
MSG_ERROR,
|
|
"Integ Scheduler ERROR: "
|
|
"SimObject '%s' is not managed by this integration loop.\n",
|
|
sim_obj.name.c_str());
|
|
return 1;
|
|
}
|
|
|
|
// Object is in the set. Remove it.
|
|
sim_objects.erase (iter);
|
|
|
|
// Rebuild jobs, but only if the manager has been initialized.
|
|
// Calls to remove prior to the initial build are legal (but silly).
|
|
if (! manager.is_empty()) {
|
|
rebuild_jobs();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Prepare for a restart.
|
|
*/
|
|
void Trick::IntegLoopScheduler::restart_checkpoint()
|
|
{
|
|
manager.clear_sim_object_info();
|
|
}
|
|
|
|
/**
|
|
Rebuild the integration loop's job queues.
|
|
This method is called internally upon adding or deleting sim objects,
|
|
and is called externally (S_define level) during initialization and
|
|
after a checkpoint restart.
|
|
*/
|
|
void Trick::IntegLoopScheduler::rebuild_jobs ()
|
|
{
|
|
// Rebuild the manager.
|
|
manager.build_sim_object_info();
|
|
|
|
// Reset the manager's notion of which objects this integrator integrates.
|
|
manager.clear_integrated_by (this);
|
|
for (SimObjectVector::iterator so_iter = sim_objects.begin();
|
|
so_iter != sim_objects.end();
|
|
++so_iter) {
|
|
Trick::SimObject * sim_object = *so_iter;
|
|
manager.set_integrated_by (sim_object, this);
|
|
}
|
|
|
|
// Rebuild each of this integration loop's job queues.
|
|
for (std::map<std::string, int>::iterator id_iter = class_map.begin();
|
|
id_iter != class_map.end();
|
|
++id_iter) {
|
|
const std::string & job_class_name = id_iter->first;
|
|
int job_class_id = id_iter->second;
|
|
Trick::ScheduledJobQueue & queue = *(class_to_queue.at(job_class_id));
|
|
|
|
// Rebuild the queue by first tearing it down to nothing
|
|
// and then rebuilding from scratch.
|
|
clear_queue (queue);
|
|
for (SimObjectVector::iterator so_iter = sim_objects.begin();
|
|
so_iter != sim_objects.end();
|
|
++so_iter) {
|
|
Trick::SimObject * sim_object = *so_iter;
|
|
manager.add_jobs_to_queue (
|
|
job_class_name, job_class_id, sim_object, queue);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Empty a job queue in anticipation of the queue being rebuilt.
|
|
@param job_queue Address of job queue that should be cleared.
|
|
*/
|
|
void Trick::IntegLoopScheduler::clear_queue (
|
|
Trick::ScheduledJobQueue & job_queue)
|
|
{
|
|
if (job_queue.size() != 0) {
|
|
Trick::JobData * curr_job;
|
|
job_queue.reset_curr_index();
|
|
while ((curr_job = job_queue.get_next_job()) != NULL) {
|
|
curr_job->set_handled (false);
|
|
}
|
|
job_queue.clear ();
|
|
}
|
|
}
|
|
|
|
/**
|
|
Call the enabled derivative jobs.
|
|
*/
|
|
void Trick::IntegLoopScheduler::call_deriv_jobs ()
|
|
{
|
|
call_jobs (deriv_jobs);
|
|
}
|
|
|
|
/**
|
|
Integrate objects to the current simulation time.
|
|
Note that sim_time is advanced before integration, so integration has to
|
|
be from sim_time-cycle to sim_time.
|
|
*/
|
|
int Trick::IntegLoopScheduler::integrate()
|
|
{
|
|
double t_end = exec_get_sim_time();
|
|
double t_start = t_end - next_cycle; // This is the time of the current state vector.
|
|
int status;
|
|
|
|
// Call all of the jobs in the pre-integration job queue.
|
|
call_jobs (pre_integ_jobs);
|
|
|
|
// Integrate sim objects to the current time.
|
|
status = integrate_dt (t_start, next_cycle);
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
|
|
// Process dynamic events, if any.
|
|
if (! dynamic_event_jobs.empty()) {
|
|
|
|
status = process_dynamic_events (t_start, t_end);
|
|
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
// Call the jobs in the derivative job queue one more time if indicated.
|
|
if (get_last_step_deriv()) {
|
|
call_jobs (deriv_jobs);
|
|
}
|
|
|
|
// Call all of the jobs in the post-integration job queue.
|
|
call_jobs (post_integ_jobs);
|
|
|
|
// We should now be back in sync with the nominal cycle rate.
|
|
next_cycle = nominal_cycle;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Determine whether derivative jobs should be called on the first step.
|
|
True if any integrator needs derivatives on the first step, false otherwise.
|
|
*/
|
|
bool Trick::IntegLoopScheduler::get_first_step_deriv_from_integrator()
|
|
{
|
|
// We need derivatives if the integ_ptr says so.
|
|
if ((integ_ptr != NULL) && integ_ptr->first_step_deriv) {
|
|
return true;
|
|
}
|
|
|
|
// Other integrators may be set in sup_class_data. Check them.
|
|
else {
|
|
Trick::JobData * curr_job;
|
|
void* sup_class_data;
|
|
Trick::Integrator* trick_integrator;
|
|
|
|
integ_jobs.reset_curr_index();
|
|
while ((curr_job = integ_jobs.get_next_job()) != NULL) {
|
|
if ((curr_job->job_class == Trick::IntegrationJobClassId) &&
|
|
((sup_class_data = curr_job->sup_class_data) != NULL) &&
|
|
((trick_integrator =
|
|
*(static_cast<Trick::Integrator**>(sup_class_data))) != NULL) &&
|
|
trick_integrator->first_step_deriv) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
Determine whether derivative jobs should be called prior to exiting the
|
|
main integration function. True if this object's last_deriv_flag is set,
|
|
or if any integrator's last_deriv_flag is set. False otherwise.
|
|
*/
|
|
bool Trick::IntegLoopScheduler::get_last_step_deriv()
|
|
{
|
|
// We need to calculate post-integration derivatives if this object
|
|
// or the integ_ptr says to do so.
|
|
if (last_step_deriv ||
|
|
((integ_ptr != NULL) && integ_ptr->last_step_deriv)) {
|
|
return true;
|
|
}
|
|
|
|
// Other integrators may be set in sup_class_data. Check them.
|
|
else {
|
|
Trick::JobData * curr_job;
|
|
void* sup_class_data;
|
|
Trick::Integrator* trick_integrator;
|
|
|
|
integ_jobs.reset_curr_index();
|
|
while ((curr_job = integ_jobs.get_next_job()) != NULL) {
|
|
if ((curr_job->job_class == Trick::IntegrationJobClassId) &&
|
|
((sup_class_data = curr_job->sup_class_data) != NULL) &&
|
|
((trick_integrator =
|
|
*(static_cast<Trick::Integrator**>(sup_class_data))) != NULL) &&
|
|
trick_integrator->last_step_deriv) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
Integrate over the specified time interval.
|
|
*/
|
|
int Trick::IntegLoopScheduler::integrate_dt ( double t_start, double dt) {
|
|
|
|
int ipass = 0;
|
|
int ex_pass = 0;
|
|
bool need_derivs = get_first_step_deriv_from_integrator();
|
|
|
|
double target_time = t_start + dt;
|
|
|
|
do {
|
|
ex_pass ++;
|
|
// Call all of the jobs in the derivative job queue if needed.
|
|
if (need_derivs) {
|
|
call_jobs (deriv_jobs);
|
|
}
|
|
need_derivs = true;
|
|
|
|
// Call all of the jobs in the integration job queue.
|
|
Trick::JobData * curr_job;
|
|
integ_jobs.reset_curr_index();
|
|
while ((curr_job = integ_jobs.get_next_job()) != NULL) {
|
|
|
|
|
|
void* sup_class_data = curr_job->sup_class_data;
|
|
// Jobs without supplemental data use the default integrator.
|
|
if (sup_class_data == NULL) {
|
|
trick_curr_integ = integ_ptr;
|
|
}
|
|
// Non-null supplemental data:
|
|
// Resolve as a pointer-to-a-pointer to a Trick::Integrator.
|
|
else {
|
|
trick_curr_integ =
|
|
*(static_cast<Trick::Integrator**>(sup_class_data));
|
|
}
|
|
|
|
|
|
if (trick_curr_integ == NULL) {
|
|
message_publish (
|
|
MSG_ERROR,
|
|
"Integ Scheduler ERROR: "
|
|
"Integrate job has no associated Integrator.\n");
|
|
return 1;
|
|
}
|
|
|
|
if (ex_pass == 1) {
|
|
trick_curr_integ->time = t_start;
|
|
trick_curr_integ->dt = dt;
|
|
trick_curr_integ->target_integ_time = target_time;
|
|
}
|
|
|
|
if (verbosity || trick_curr_integ->verbosity) {
|
|
message_publish (MSG_DEBUG, "Job: %s, target_integ_time: %f, integ_time: %f, dt: %f, ipass = %d\n",
|
|
curr_job->name.c_str(), target_time, t_start, dt, ipass);
|
|
}
|
|
|
|
ipass = curr_job->call();
|
|
|
|
// Trick integrators are expected to advance from step one to step
|
|
// two, etc., and then back to zero to indicate completion.
|
|
// All integrators are expected to march to the same beat.
|
|
// FIXME, future: This restricts Trick to using only rather
|
|
// simple integration techniques.
|
|
if ((ipass != 0) && (ipass != ex_pass)) {
|
|
message_publish (
|
|
MSG_ERROR,
|
|
"Integ Scheduler ERROR: Integrators not in sync.\n");
|
|
return 1;
|
|
}
|
|
}
|
|
} while (ipass);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Trick::IntegLoopScheduler::process_dynamic_events ( double t_start, double t_end, unsigned int depth) {
|
|
|
|
bool fired = false;
|
|
double t_to = t_end;
|
|
double t_from = t_start;
|
|
Trick::JobData * curr_job;
|
|
dynamic_event_jobs.reset_curr_index();
|
|
while ((curr_job = dynamic_event_jobs.get_next_job()) != NULL) {
|
|
// Call the dynamic event job to calculate an estimated time-to-go.
|
|
double tgo = curr_job->call_double();
|
|
if (tgo < 0.0) { // If there is a root in this interval ...
|
|
fired = true;
|
|
while (tgo != 0.0) {
|
|
if (tgo > 0.0) {
|
|
t_from = t_to;
|
|
t_to = t_to + tgo;
|
|
int status = integrate_dt( t_from, (t_to-t_from));
|
|
if (status != 0) { return status; }
|
|
} else {
|
|
#define FORWARD_INTEGRATION 0
|
|
#if FORWARD_INTEGRATION
|
|
integ_ptr->state_reset(); // We always want to integrate forward.
|
|
t_to = t_to + tgo;
|
|
#else
|
|
t_from = t_to;
|
|
t_to = t_from + tgo;
|
|
#endif
|
|
int status = integrate_dt( t_from, (t_to-t_from));
|
|
if (status != 0) { return status; }
|
|
}
|
|
tgo = curr_job->call_double();
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
Integrate to the end of the integration cycle using the updated derivatives.
|
|
*/
|
|
if (fired) {
|
|
t_from = t_to;
|
|
t_to = t_end;
|
|
/*
|
|
Because the derivatives have likely changed, we need to recursively
|
|
check for new events in the remaining interval.
|
|
*/
|
|
int status = integrate_dt( t_from, (t_to-t_from));
|
|
if (status != 0) { return status; }
|
|
status = process_dynamic_events(t_from, t_to, depth+1);
|
|
if (status != 0) { return status; }
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Utility function to get an integrator.
|
|
@param alg The integration algorithm to use.
|
|
@param state_size the total number of integration variables and derivative variables.
|
|
*/
|
|
Trick::Integrator * Trick::IntegLoopScheduler::getIntegrator (
|
|
Integrator_type alg, unsigned int state_size)
|
|
{
|
|
integ_ptr = Trick::getIntegrator (alg, state_size);
|
|
trick_curr_integ = integ_ptr;
|
|
return integ_ptr;
|
|
}
|
|
|
|
/**
|
|
Set the interval at which this job is called.
|
|
@param in_cycle The frequency for the integration cycle.
|
|
*/
|
|
int Trick::IntegLoopScheduler::set_integ_cycle (
|
|
double in_cycle)
|
|
{
|
|
JobData * found_job = NULL;
|
|
int loops_found = 0;
|
|
|
|
// Search through the parent sim object looking for integ_loop jobs.
|
|
// There should be exactly one such job.
|
|
for (std::vector<Trick::JobData *>::iterator vit =
|
|
parent_sim_object->jobs.begin();
|
|
vit != parent_sim_object->jobs.end();
|
|
++vit) {
|
|
JobData * vit_job = *vit;
|
|
if (! vit_job->job_class_name.compare("integ_loop")) {
|
|
++loops_found;
|
|
found_job = vit_job;
|
|
}
|
|
}
|
|
|
|
// Not finding exactly one integ_loop job is an error.
|
|
if (loops_found != 1) {
|
|
message_publish (
|
|
MSG_ERROR,
|
|
"Integ Scheduler ERROR: %s\n",
|
|
(loops_found == 0) ? "integ_loop job not found." :
|
|
"multiple integ_loop jobs found.");
|
|
return 1;
|
|
}
|
|
|
|
// Found exactly one integ_loop job.
|
|
// Set the cycle rate for that one job and for this object.
|
|
// Note: This assumes that the one found job pertains to this scheduler.
|
|
else {
|
|
long long prev_tics = found_job->next_tics - found_job->cycle_tics;
|
|
long long curr_tics = exec_get_time_tics();
|
|
found_job->set_cycle (in_cycle);
|
|
found_job->set_next_call_time (curr_tics);
|
|
nominal_cycle = in_cycle;
|
|
next_cycle = double((found_job->next_tics - prev_tics)) /
|
|
double(found_job->time_tic_value);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Write the content of the S_job_execution file.
|
|
@param fp The pointer to the file to write the S_job_execution file.
|
|
*/
|
|
int Trick::IntegLoopScheduler::write_s_job_execution(FILE *fp)
|
|
{
|
|
|
|
if (fp == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
fprintf(fp, "\n===================================================================================================\n") ;
|
|
fprintf(fp, "Integration Loop:\n\n") ;
|
|
pre_integ_jobs.write_sched_queue(fp) ;
|
|
deriv_jobs.write_sched_queue(fp) ;
|
|
integ_jobs.write_sched_queue(fp) ;
|
|
dynamic_event_jobs.write_sched_queue(fp) ;
|
|
post_integ_jobs.write_sched_queue(fp) ;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Adds the incoming instrumentation job before target job if specified, or all jobs in the list.
|
|
@param instrument_job Pointer to the job that should be run previously.
|
|
*/
|
|
int Trick::IntegLoopScheduler::instrument_job_before (
|
|
Trick::JobData * instrument_job)
|
|
{
|
|
int count = 0 ;
|
|
/** @par Detailed Design */
|
|
|
|
count += pre_integ_jobs.instrument_before(instrument_job) ;
|
|
count += deriv_jobs.instrument_before(instrument_job) ;
|
|
count += integ_jobs.instrument_before(instrument_job) ;
|
|
count += dynamic_event_jobs.instrument_before(instrument_job) ;
|
|
count += post_integ_jobs.instrument_before(instrument_job) ;
|
|
|
|
/** @li Return how many insertions were done. */
|
|
return count;
|
|
|
|
}
|
|
|
|
/**
|
|
Adds the incoming instrumentation job after target job if specified, or all jobs in the list.
|
|
@param instrument_job Pointer to the job that should be run after each job.
|
|
*/
|
|
int Trick::IntegLoopScheduler::instrument_job_after (
|
|
Trick::JobData * instrument_job)
|
|
{
|
|
int count = 0 ;
|
|
|
|
count += pre_integ_jobs.instrument_after(instrument_job) ;
|
|
count += deriv_jobs.instrument_after(instrument_job) ;
|
|
count += integ_jobs.instrument_after(instrument_job) ;
|
|
count += dynamic_event_jobs.instrument_after(instrument_job) ;
|
|
count += post_integ_jobs.instrument_after(instrument_job) ;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
/**
|
|
Removes all jobs in the list that match the name in_job.
|
|
@param in_job name of the job that should be removed.
|
|
*/
|
|
int Trick::IntegLoopScheduler::instrument_job_remove(std::string in_job)
|
|
{
|
|
pre_integ_jobs.instrument_remove(in_job) ;
|
|
deriv_jobs.instrument_remove(in_job) ;
|
|
integ_jobs.instrument_remove(in_job) ;
|
|
dynamic_event_jobs.instrument_remove(in_job) ;
|
|
post_integ_jobs.instrument_remove(in_job) ;
|
|
|
|
return 0;
|
|
}
|