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:
-
tseries<unitval> x
to create a time series. -
unitval x
to declare a value with associated units. double x
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.allowInterp( true );
X_emissions.name = X_COMPONENT_NAME; X_emissions
Within X::init
Inform the core what data the component can provide (registerCapability) and what data the component depends on (registerDependency)
->registerCapability( D_ATMOSPHERIC_X, getComponentName() );
core->registerDependency( D_LIFETIME_X, getComponentName() ); core
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.
( logger, Logger::DEBUG ) << "Year " << runToDate << " X concentration = " << X.get( runToDate ) << std::endl; H_LOG
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
( logger, Logger::DEBUG ) << "goodbye " << getComponentName() << std::endl;
H_LOG.close(); logger
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:
= new XComponent();
temp [ temp-->getComponentName() ] = temp; modelComponents
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;
( csvFile, c, D_X_COMPONENT, current_date );
STREAM_MESSAGE_DATE}
Finally, in csv_outputsream_visitor.hpp
under public
`virtual void visit( XComponent* c);`