|Version 3 (modified by dlonie, 13 months ago)|
This page is to serve as a guide for implementing your own structure search extension using the libglobalsearch library.
There is an example extension in the source code at src/examplesearch. This is a stripped down version of RandomDock which only generates and optimizes O2 molecules. This code can be used as a template for implementing your own search extensions.
Many of the common features of structure searching algorithm are abstracted away into the libglobalsearch library, including queue management, optimizer interfaces, DRMS interfaces, error handling, etc. The code in ExampleSearch provides a starting point that already has most of these functions integrated in.
The classes in libglobalsearch are documented here.
A word of warning: I was a very inexperience programmer when I started writing libglobalsearch. There are portions of the code that exhibit poor programming practices (public member variables, unnecessary type conversion, etc). I apologize in advance for these. I've been slowly cleaning them up as I've developed XtalOpt and related projects, but the amount of effort that would be required to fix all of them far exceeds the time I have available. If you have any questions, concerns, or comments, please do not hesitate to contact me for assistance at loniedavid at gmail dot com. This page is meant to serve as a starting point and may not be complete. If you find something that is not well explained, feel free to modify this wiki page to clarify it, or email me if you need help figuring something out.
Now that that's out of the way, let's get started!
The files in the examplesearch directory each have a specific functions, and are designed for use with the libglobalsearch library.
This class is the glue that connects the search extension to Avogadro. It controls the creation of the Avogadro menu item that launches the extension, creates the extension dialog window, and is responsible for sending structures to Avogadro for visualization.
This is the workhorse of the extension. The ExampleExtension class derives from GlobalSearch::OptBase, see the link for details about this class. This is where the initial search begins and new structures are generated.
This file controls how the extension is compiled and linked.
ui/*.cpp, ui/*.h, ui/*.ui
These files implement the GUI for the search extension. The ui files can be opened in QtCreator or QtDesigner to create/modify widgets, windows, etc.
- dialog: The main dialog that contains the save/resume/hide buttons, progress bar, and tab widget. See GlobalSearch::AbstractDialog.
- tab_edit: Provides an standard interface for editing optimizer/DRMS input templates. See GlobalSearch::AbstractEditTab and GlobalSearch::DefaultEditTab
- tab_init: This is where input information about the structures in the search is entered (e.g. composition, size, etc). It is blank in ExampleSearch, since the extension will only produce O2 molecules. It simply inherits from GlobalSearch::AbstractTab.
- tab_log: A log widget. Inherits from GlobalSearch::AbstractTab.
- tab_plot: A plotting interface. Inherits from GlobalSearch::AbstractTab.
- tab_progress: A progress table widget. Inherits from GlobalSearch::AbstractTab.
The classes under optimizers/ inherit from GlobalSearch::Optimizer and each provides information for interfacing with various external optimization codes.
Adapting ExampleSearch for your needs
First, just copy the contents of the examplesearch directory into a new directory (under src/).
cd [xtalopt-source-root]/src/ cp -rv examplesearch/ mysearch
Change ExampleSearch to the name of your extension
The classes, namespaces, and header-guards will need to be updated to reflect that the extension is now different from ExampleSearch. If you're on a UNIX environment, sed will save you a lot of time. If you are not, you'll need to manually replace all occurances of examplesearch with the name of your extension.
- Create a sed script named, e.g., convert.sed with the following (after changing mysearch to something more meaningful, and fill in the name and year):
# Replace all instances of examplesearch s/examplesearch/mysearch/g s/ExampleSearch/MySearch/g s/EXAMPLESEARCH/MYSEARCH/g # Update copyrights /Copyright.\+Lonie/ a \ \ Copyright (C) <year> by <your name>
Run sed on the files: sed -i -f convert.sed [list of filenames to convert]
- Rename the examplesearch.cpp/h files
cp examplesearch.cpp mysearch.cpp cp examplesearch.h mysearch.h
- Update CMakeLists.txt files. There are two files that will need modification:
- [xtalopt-source-root]/src/mysearch/CMakeList.txt: Change examplesearch to mysearch. If you add more files to the project later, you will need to add them here so that they will get compiled and linked.
- [xtalopt-source-root]/src/CMakeList.txt: Replicate all of the examplesearch bits in this file, modifying them so that they reflect the name of your extension.
- Change the extension name and description. In mysearch/extension.h, change the lines:
AVOGADRO_EXTENSION("ExampleSearch", tr("Example Search"), tr("Example of a structure search Avogadro extension " "using libglobalsearch"))
The first entry should have been changed by sed -- this is the static name of the extension, and is used to identify it programmatically within Avogadro. The second entry is a more user-friendly name of the extension. The third entry is a brief description of what the extension does. The tr(...) bits are part of the Qt library, and are used to identify strings that need to be translated when adding support for another language.
- Change the menu entry. In mysearch/extension.cpp, search for action->setText(tr("&Example Search..."));. This is where the menu entry for the extension is specified. Change it as you see fit. The "&" character indicates which letter should be used as a keyboard shortcut (in this case, "E").
At this point, the extension should compile. Go to your XtalOpt build directory (usually [xtalopt-source-root]/build) and run cmake .. -DENABLE_MYSEARCH=1, assuming that the option you added in src/CMakeLists.txt was named ENABLE_MYSEARCH. Clean up any issues that remain, and from here you're free to modify the search algorithm at will. Some areas of interest are:
- mysearch.cpp, MySearch::generateRandomStructure(): This is the function that is used to generate a structure randomly, for use in creating an initial population for an evolutionary algorithm or all structures in a Monte Carlo search.
- mysearch.cpp, MySearch::generateNewStructure(): This is currently configured for a Monte Carlo search, all new structure are generated randomly. For something like an EA, which will switch from random structures to mutated offspring, you can modify this method to produce structures by any means you wish.
- ui/* You'll probably want to configure the UI for your specific algorithm.
- optimizers/* Add or remove optimizer interfaces here.