ComputeTool¶
The ComputeTool object is used to perform calculations that may be re-used by various modules. Unlike a Module, a ComputeTool is assumed to perform its functions independently, and so does not require any data sharing paradigm beyond passing arguments into its methods. All ComputeTool objects are owned by Simulation. When a Module wants to create or release a ComputeTool it calls a method of Simulation to do so.
When to use a ComputeTool¶
The ComputeTool provides services for free that a simple function or user defined object does not. There are also services that are not provided, being reserved for Module objects. The basic characteristics are:
Easy management of input file and restart file interactions
Easy access to OpenCL kernel functions.
Management of allocation and de-allocation of resources, accounting for the possibility of multiple references to the tool.
No data sharing. A
ComputeTooldoes not participate in publisher-consumer data movement, and oneComputeToolcannot contain another.No direct invocation within the main simulation loop. All data processing has to be initiated by a
Modulewhich has a pointer to theComputeTool.
Example¶
A straightforward example of a module that uses a ComputeTool inheritance tree is the FieldSolver module in fieldSolver.h and FieldSolver.cpp. This FieldSolver base class exists largely to manage various types of elliptical solvers. The elliptical solver tools themselves are implemented in elliptic.h and Elliptic.cpp.
Implementing a ComputeTool¶
Declaration¶
When implementing a new ComputeTool, first carry out the following.
In
computeTool.h, introduce a newtw::tool_typeelement. This is a label for the type of tool.In
ComputeTool.cpp, add a case to theCreateObjectFromTypemethod for the new type.In an appropriate header file, derive the new type from
ComputeTool.In an appropriate source file, implement the
ComputeTool.
The tool can implement whatever methods are desired. A function that moves data forward by one time level is conventionally called
Advance.Further implementation details follow.
Association with Module¶
Carry out the following for any Module that wants to use the tool.
In the
Moduledeclaration, declare a pointer to the tool. Polymorphism may be used to whatever extent is desired.In the constructor, set the pointer to
NULL.In the destructor, if the pointer is not
NULL, callowner->RemoveToolwith the pointer as the argument.
Input File Support¶
If you want the tool to be accessible from the input file, carry out the following steps.
In the tool’s constructor define the input file directives. For each directive make one call to
directives.Add(std::string&,tw::input::Directive*).Add an entry to the hash table returned by
MapinComputeTool.cpp. This connects the directive key with thetw::tool_type.In the
VerifyInputmethod of eachModulethat wants to use the tool:
Search the
moduleToolvector for a compatible tool, and copy the dynamically typecast compatible pointer to your pointer.If no compatible tool is found, either throw an error, or create a default tool using
owner->CreateTool.If you need to set the tool’s member variables based on module data, it is safest to do this in the
Initializemethod, since this is called only after all modules have exchanged resources.
Tip
If you want to create a tool exclusively for the use of a particular module, and there is no need for input file or restart file interaction, you can simply create it in the module constructor, and remove it in the module destructor.
Tip
If implemented correctly, tools are ready to be used by the time Module::Initialize is called.
Restart File Support¶
As of version 4.0, only time varying quantities need to be checkpointed (no need to store constants or structural information). To support restarting a tool, carry out the following steps.
Override the tool’s
ReadCheckpointmethod. Call the inheritedReadCheckpointmethod first. Then read any necessary data from the restart file.Override the tool’s
WriteCheckpointmethod. Call the inheritedWriteCheckpointmethod first. Then write any necessary data to the restart file.Verify that
ReadCheckpointandWriteCheckpointaccess the data in the same order.
Best Practices¶
Avoid making the tool the owner of heavyweight data. Instead pass such data to member functions by reference.
Keep self-contained, i.e., avoid using references to modules or other objects in the containment hierarchy. If this seems unavoidable consider using a
Module.