GeMA
The GeMA main application
Adding a new physics plugin

This tutorial presents a step by step guide for creating a new physics plugin. On the first part, it will present how to create the skeleton for a new plugin based on a copy of an existing one. For those already familiar with updating and changing existing physics plugins, this part will provide the needed base for continuing on your own. The second part explains the needed structure and methods for a physics plugin.

Part I - Building the Plugin Skeleton

1) Make a copy of an existing physics.

This step will estabilish a base to begin with. The best way is to choose a simple physics as the 'source template'. In this example we will choose the temperature physics as our base and we will call our new physics diffusionFemPhysics. If you are creating a coupled physics, or a physics inheriting from another existing physics, other options might work best.

To make this copy, go to the plugins\physics directory and make a copy of the temperature physics directory, calling it diffusionFemPhysics. Please keep in mind that under the GeMA package distribution there are two 'plugins' directories. The one with the source code resides under the root directory. The other one, with plugin binaries is located under the gema application directory. Make sure to make your copy from the source code one.

If your copy was not done from a clean distribution, make sure to discard any files that are not version controled (those are in general the debug, release, generated, lib and doxygen\html directories plus *.vcxproj.*, doxygenlog.txt and doxygen\*.tag files).

2) Edit build scripts

While on the plugins\physics directory, make sure to edit both the DoxygenBuild.bat and vc_build_physics.bat files. Just follow the existing pattern adding new entries in both files for the new diffusionFemPhysics directory.

Now get into the diffusionFemPhysics directory and rename the .pro file to diffusionFemPhysics.pro. Open this file in a text editor to adjust the new project building options. The following changes should be done:

  • Update the TARGET definition to the new plugin name, diffusionFemPhysics.
  • Update the define used to tell headers whether we are compiling the shared library or just using it.
  • If your plugin inherits from another plugin, or needs to use another external library, make sure to add the required USE_XXX clauses. See the commonLibOptions.pri file on the root directory for a list of available options.
  • Update the set of project files in the HEADERS and SOURCES definitions. A physics plugin should have at least a factory header file and a pair of .h and .cpp files for its class implementation. It should also have a config and a version header files. Following the used convention, those files should be named gmpDiffusionConfig.h, gmpDiffusionVersion.h, gmpDiffusionFemPhysics.cpp, gmpDiffusionFemPhysics.h, gmpDiffusionFemPhysicsFactory.h.
  • Update the GENERATED_SOURCES definition. The version ".cpp" file is auto generated by vc_build.bat. See step 7.
  • Update the RESOURCES definition to point to luaScripts/diffusionFemPhysics_scripts.qrc

3) Rename source files

Now go inside the inc and src subdirectories and rename those files according to the names given in the diffusionFemPhysics.pro file. At this step we won't bother with those files contents, since for now we just want to be able to generate the new Visual Studio project. Files should now be named gmpDiffusionConfig.h, gmpDiffusionVersion.h, gmpDiffusionFemPhysics.cpp, gmpDiffusionFemPhysics.h and gmpDiffusionFemPhysicsFactory.h.

4) Rename and adjust resource files

Now go inside the luaScripts directory and do the following changes:

  • Edit the pluginScripts.lua file. This file contains a Lua function that is called by the model parser to validate physics options before instancing the physics object. It can be used to perform simple parameter validations. Change the function name to CheckDiffusionFemPhysicsAttributes and update the function contents to match the new plugin requirements. For starter, this function can be left with only the standard check done by the call to Gema.FemProcessPlugin.CheckFemPhysics(physDef).
  • Rename the .qrc file so that it is now called diffusionFemPhysics_scripts.qrc.
  • Edit the diffusionFemPhysics_scripts.qrc file, changing the resource prefix to "/GeMA_DiffusionFemPhysics".

5) Edit the the plugin definition file

Going back to the physics main directory, rename the plugin .lua definition file to diffusionFemPhysics.lua. Edit this file making the following changes:

  • Update the pluginName to 'DiffusionFemPhysics'.
  • Update the pluginCategory if needed. In general this field should be equal to either 'Physics'.
  • Update the objectTypes entry to reflect the objects that can be returned by this plugin. Some plugins return only one object type while others use several ones to distinguish between analysis types (like the mechanics plugin).
  • Update the pluginRsrc entry, changing it to ':/GeMA_DiffusionFemPhysics/pluginScripts.lua'. Notice that the 'GeMA_DiffusionFemPhysics' part of this field should be equal to the resource prefix defined in the previous step in the diffusionFemPhysics_scripts.qrc file.
  • Update the checkAttributesFunction entry, changing it to 'CheckDiffusionFemPhysicsAttributes'. Notice that this name should be equal to the function name edited in the previous step in the pluginScripts.lua file.
  • Update, if needed, the pluginDependencies entry. This field should contain a table specifying the names of each plugin that this plugin depends on (either by inhritance or composition, for example).
  • If your plugin needs to define constants (material names, for example), those can be defined by using the pluginAttributes.constants entry. See the plugin definition file for the mechanics or the hydraulics physics for an example.

6) Edit documentation files

Although this step can be done later on, lets do it now so that we do not forget how important documentation is. First open the file Doxyfile in a text editor and change the following tags:

  • Update the PROJECT_NAME entry to "DiffusionFemPhysics""
  • Update the PROJECT_BRIEF entry with a short but relevant description of your physics.
  • Update the GENERATE_TAGFILE entry to doxygen/diffusionFemPhysics.tag
  • If your project includes other libraries that should be referenced by the plugin documentation, update the TAGFILES entry to reflect that.

Go into the doxygen folder and edit the doxygenMainPage.h contents. Make sure to adjust the subpage name reference to the plugin options page. Now go into the doxygenPluginOptions.h file and update its tag name + the file contents to document the new plugin available options. Keep in min that several of the default options are common to all physics plugins.

To link your new plugin documentation to the global documentation, the files doxygenPluginReferenceIndex.h and doxygenClassDocumentationIndex.h, both located in the gema\doxygen directory should be updated with links to the new plugin. Just follow the existing pattern in both files (and do not forget to later rebuild the documentation following the instructions in the documentation tutorial, but don't do it now - wait until we finish with this part of the tutorial). The Doxyfile in the gema directory should also be updated by adding an entry in the TAGFILES list corresponding to the new plugin.

7) Give your plugin a version number

Go back to the root gema directory and open the versionList.lua file. Add a new line for your plugin specifying its path (plugins/physics/diffusionFemPhysics), version number, the name of the version header file (gmpDiffusionVersion.h), the prefix used for the auto-generated version functions (GmpDiffusionFemPhysics) and the list of libraries and other plugins that this plugin depends on. This list is used for dependency version check when loading a plugin.

8) Create the Visual Studio Project

Execute the standard vc_build.bat on the project root directory as you regularly do after a project update or adding files to the project. After this the plugin .vcxproj files should have been created. Take special care to look if any warnings or errors where written to the console.

Open the gema.sln in the Visual Studio application. On the solution explorer, select the Physics folder under the Plugins folder. With a right click, select the "Add Existing Project" option. On the file selection dialog, choose the newly created vcxproj file for your plugin. This will add your new plugin to the solution.

On the solution explorer, right click on the root "Solution" entry and select the "Project Dependencies" option. On the dialog shown, mark that the gema application depends on the new physics. Select your new physics on the Projects combo box and mark bellow the projects that it depends upon. Use the base physics as a template. In general a physics plugin will depend at least on femProcess, gemaCoreLib, luautils and unit projects.

9) Edit the physics class

Edit the GmpDiffusionFemPhysics class definition and implementation on files gmpDiffusionFemPhysics.h and gmpDiffusionFemPhysics.cpp. The contents of a minimum physics class that compiles, but does nothing, is given below. We are going to fill that class with meaningfull code on Part II of this tutorial. While editing the files, please remember to update file names and #ifdefs accordingly.

In the class definition, please notice that the value returned by the pluginName() method should match the pluginName given in the plugin definition file (step 5). Also, the pluginType should match one of the names given in the objectTypes table of that same file. If the physics supports several object types, there should either be a class for each type or the type should be received as an object constructor parameter and used in this function return value.

class GmpDiffusionFemPhysics: public GmpFemPhysicsCommon
{
public:
GmpDiffusionFemPhysics(GmSimulationData* simulation, QString id, QString description, GmLogCategory& logger);
virtual ~GmpDiffusionFemPhysics();
virtual const char* pluginName() const { return "DiffusionFemPhysics"; }
virtual const char* pluginType() const { return "diffusion"; }
virtual const QVariantMap* physicsMetaDataMap();
virtual bool fillElementData(const GmElement* e, GmpFemMatrixSet& elemMatrices, GmpFemVectorSet& elemVectors);
};
GmpDiffusionFemPhysics::GmpDiffusionFemPhysics(GmSimulationData* simulation, QString id, QString description, GmLogCategory& logger)
: GmpFemPhysicsCommon(simulation, id, description, NULL, logger)
{
}
GmpDiffusionFemPhysics::~GmpDiffusionFemPhysics()
{
}
const QVariantMap* GmpDiffusionFemPhysics::physicsMetaDataMap()
{
static QVariantMap m;
if(m.isEmpty())
{
// Fill meta data map
}
return &m;
}
bool GmpDiffusionFemPhysics::fillElementData(const GmElement* e, GmpFemMatrixSet& elemMatrices, GmpFemVectorSet& elemVectors)
{
return false;
}

10) Edit the factory class

Edit the GmpDiffusionFemPhysicsFactory class implementation on file gmpDiffusionFemPhysicsFactory.h. The contents of a minimum physics factory class is given below. We are going to explore that class further on Part II of this tutorial. While editing the files, please remember to update file names and #ifdefs accordingly.

In the class implementation, please notice that the string passed to the GmPluginObjectFactory() inherited constructor is the base name for the plugin logger and should be equal to the plugin name. The functions used to return the plugin version information are automatically created from the version information filled on step 7.

#include <QObject>
#include "gmpDiffusionFemPhysics.h"
class GmpDiffusionFemPhysicsFactory: public QObject, GmPluginObjectFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID GmPluginObjectFactoryInterfaceIID)
Q_INTERFACES(GmPluginObjectFactory)
public:
GmpDiffusionFemPhysicsFactory() : GmPluginObjectFactory("DiffusionFemPhysics") {}
virtual GmPluginObject* instance(QString category, QString objType, GmSimulationData* simulation,
QString id, QString description)
{
assert(category == GM_PLUGIN_PHYSICS);
// Common object instanciation
if(objType == "diffusion")
return new GmpDiffusionFemPhysics(simulation, id, description, logger());
else
return NULL;
}
virtual const QStringList& versionInfo() const { return GmpDiffusionFemPhysicsVersionInfo(); }
virtual const QStringList& depVersionInfo() const { return GmpDiffusionFemPhysicsRevisionDependencies(); }
};

11) Compile

If the steps above where followed correctly, your code should compile. Check that the plugin DLL + static library where created on the lib directory and also on the gema application equivalent plugin directory.

12) Add files to the repository

Now that your plugin is compiling, add the new files to the SVN source control. Remeber that generated files (such as those on the debug, release, generated, lib and doxygen\html directories plus *.vcxproj.*, doxygenlog.txt and doxygen\*.tag files) should not be added to the repository and should be marked as ignored.

Part II - Physics plugin structure and main methods