Skip to contents

Here are the steps to create a new component X in Hector’s C++ codebase.

Step one:

Add two new files:

  • A header file in inst/include/X.hpp
  • A corresponding source file in src/core/X.cpp

It is best to copy and modify the corresponding files from an already constructed component.

Step two (within X.hpp):

Under private, list the variables that are used in the component and their corresponding type. Because of Hector’s ability to reset, every state variable generally needs an associated time series history variable. For example:

Step three (within X.cpp):

Make sure that you #include X.hpp.

In the class constructor

If the variable is a tseries, add all of the variables allowing for interpolation and their corresponding names

    XComponent::XComponent() {
        X_emissions.allowInterp( true ); 
        X_emissions.name = X_COMPONENT_NAME; 

Within X::init

Inform the core what data the component can provide (registerCapability) and what data the component depends on (registerDependency)

    core->registerCapability( D_ATMOSPHERIC_X, getComponentName() );
    core->registerDependency( D_LIFETIME_X, getComponentName() );

Within X::setData

Set the data that are used as inputs within this component, typically coming from the INI file.
For examples of tseries vs. unitvals in Time Series.

Within X::prepareToRun

This code can vary but this can be where hard-coded parameters are coded.

Within X::run

The run method contains the equations and code used in this component. Here is where you would want a log statement, written out to the component’s log.

H_LOG( logger, Logger::DEBUG ) << "Year " << runToDate << " X concentration = " << X.get( runToDate ) << std::endl;

Within X::getData

These are data that the component can provide to another component or the data that is being generated within the component. [[For examples of tseries vs. unitvals in getData|AddTSeries]].

Within X::shutDown

H_LOG( logger, Logger::DEBUG ) << "goodbye " << getComponentName() << std::endl;
logger.close();

Step four (Outside of X.cpp and X.hpp):

In avistor.hpp

Add class XComponent under the declarations of subclasses and add virtual void visit( XComponent*c ) {}

In core.cpp

Add #include "xcomponent.hpp"

Under Core::init() section add code to create your new component:

temp = new XComponent();
modelComponents[ temp-->getComponentName() ] = temp;

In component_names.hpp

Under component names:

#define X_COMPONENT_NAME “x”

In component_data.hpp

Define the variables within the component; this is the string that will be passed into the core via sendMessage or via the R wrapper.

#define D_ATMOSPHERIC_X "X"

In csv_outputstream_visitor.cpp (and for any other visitor necessary; see in particular the carbon-tracking visitor) you need to add code to write out the component’s outputs:

#include 'xcomponent.hpp'

void CSVOutputStreamVisitor::visit( XComponent* c ) {
    if( !core->outputEnabled( c->getComponentName() ) && !in_spinup ) return;
    STREAM_MESSAGE_DATE( csvFile, c, D_X_COMPONENT, current_date );
    }

Finally, in csv_outputsream_visitor.hpp

    under public  
    `virtual void visit( XComponent* c);`