C++ FISH Intrinsic Plug-ins

Introduction

The methodology of writing a FISH intrinsic in C++ for operation in PFC is described in this section. This includes a description of some pertinent base classes, how to create a Visual Studio (referred to below as MSVS) project, loading the resulting DLL, and how PFC-specific data are accessed.

Base Class Interface for FISH Intrinsics

The base class interface, :pfc:`IFishLibrary <itasca::IFishLibrary>`, provides a framework for specific implementation of all FISH intrinsics. The many predefined FISH intrinsics available in PFC are implemented using this same interface. This base interface is termed an abstract interface because it consists entirely of pure virtual member functions (signified by the =0 syntax appended to the function prototypes). This means that no object of this base class can be created, and that any derived-class object must supply real member functions to replace each one of the pure virtual functions of :pfc:`IFishLibrary <itasca::IFishLibrary>`. Note that an :pfc:`IFishLibrary <itasca::IFishLibrary>` class might add one or many new FISH intrinsics when loaded.

The :pfc:`IFishLibrary <itasca::IFishLibrary>` class is just one of many classes that make up the general PFC programmer’s interface. The entirety of the computational engine is implemented as a DLL. An entirely new user interface could be created using the functions made available. In fact, the GUI provided by Itasca interacts with PFC entirely through this same interface. The interface is located in the “interface” directory of your PFC installation in the form of C++ header files.

Full documentation of the interface is provided in the “Programmer’s Interface” section and will not be duplicated here. For example, each method in the :pfc:`IFishLibrary <itasca::IFishLibrary>` interface is fully documented there. This documentation is built along with the PFC source so it reflects any modifications to PFC.

The entry point for access to all model data is the :pfc:`IProgram <itasca::IProgram>` interface. This interface is passed to the :pfc:`IFishLibrary::get() <itasca::IFishLibrary::get>` and :pfc:`IFishLibrary::set() <itasca::IFishLibrary::set>` methods. PFC-specific data (e.g., ball and contact data) are generally available through the IProgram template function :pfc:`IProgram::findInterface() <itasca::IProgram::findInterface>`; this function template parameter is the interface class that you need to access.

Creating FISH Intrinsic DLLs from the MSVS Project Template

We provide a “Project Template” that is the only supported way to create FISH intrinsic projects in MSVS 2017. The template presumes that PFC is installed in the default directory (i.e., C:Program FilesItascaPFC600). If not, you will need to edit some project settings to point directly to your installation location. Follow the steps below:

  1. Assuming PFC, Qt 5.12 and MSVS 2017 are already installed, find file “function.zip” in the pluginfilestemplatefiles directory inside the PFC installation directory.
  2. Place this zip file in your DocumentsVisual Studio 2017TemplatesProjectTemplates folder.
  3. Launch MSVS and select File -> New -> Project from the menu.
  4. Select the “Visual C++” category select the “function” project.
  5. Assign a name for the new project. You may also choose a new location in which to place the new project and solution.
  6. A project will be created for you using some simple example functions as a source. This project can be freely modified to match your specific desired behavior.
  7. Choose the {Release2D; Release} solution configuration for use with {PFC2D; PFC3D}, respectively. If one loads a DLL built for PFC2D into PFC3D, unexpected results may occur, including code crashes.

The resulting header and source files demonstrate methods to loop over balls and contacts in C++ and to make a table with sinusoidal values. In addition, a multi-threaded loop over balls is demonstrated. It is important to note that the preprocessor definition DIM is set depending on the solution configuration where {DIM = 2 for PFC2D; DIM = 3 for PFC3D}. This is important as the itascaxd namespace is used; this namespace allows for dimensional quantities, like vectors, to be assigned appropriately depending on the dimensionality of the code. The resulting intrinsic for the {Release2D; Release} configuration should only be used with {PFC2D; PFC3D}. Also note that the pfc namespace must be used to access PFC-specific information such as ball, clump, or wall data.

Loading and Running User-Written FISH DLLs

If the plug-in DLL has been placed in the “exe64\plugins\function” directory, then it will be loaded automatically at GUI start-up. Otherwise, the plug-in may be loaded explicitly by using the program load function command. If the DLL uses the Itasca naming convention, then the supplied string can be simply the library name (i.e., “test” if the library DLL is named “functiontest006.dll”). Otherwise, the full file and path can be specified. The following directories are searched automatically when attempting to load a plug-in, in order:

  • The directory in the “dir” registry entry, if present, and all sub-directories. The user must set this in registry location “HKEY CURRENT USER\Software\Itasca\pfc2d600” or “HKEY CURRENT USER\Software\Itasca\pfc3d600”.
  • The directory where the PFC executable resides and all sub-directories.
  • The current directory and all sub-directories.

Note that model state (SAV) files created with FISH code that calls user-defined FISH intrinsics require that these intrinsics be present upon restore. PFC will attempt to automatically find and load these intrinsics during restore. This process will fail if the corresponding DLL is not in one of the locations PFC automatically searches.

Was this topic helpful? Let us know...