A compile-time formulated symbolic algebra framework for numerical solutions of phase-field-problems.
Papers:
- SymPhas—General purpose software for phase-field, phase-field crystal and reaction-diffusion simulations, Steven A. Silber and Mikko Karttunen, Adv. Theor. Sim. 5, 2100351 (2022).
- Preprint: arXiv:2109.02598
Article accepted for publication in Advanced Theory and Simulations (Nov 2021)
Phase-field modeling is a computational approach for simulating the microstructure evolution of various materials and systems. It has far reaching applications from dendrite growth, reaction-diffusion systems, damage and fracture models, biological systems, and more. By representing the dynamics of one or more evolution parameters (called order parameters) in a system of coupled differential equations, one is able to solve the system using standard numerical methods.
SymPhas has been developed as an API that, when combined with a driver file, uses a chosen numerical solver to generate solutions to a given phase-field model. The model can be any type that is expressed as a set of dynamical equations. In other words, SymPhas supports any multi-phase-field problem that can be formulated field-theoretically. The numerical solvers in SymPhas are those which are based on uniform grids, such as finite difference solvers.
The primary advantages that SymPhas provides are C-like optimized run times, parallelization, symbolic algebra, a modular design for straightforward third party development, and extensive documentation. A brief list of features offered by SymPhas are:
- An optimized symbolic algebra functionality that fully formulates expression trees at compile time to evaluate an expression. This design is completely eliminates branching at runtime. This is coupled with a rich symbolic algebra feature set to give the user significant ability to transform, manipulate and manage expressions.
- Template meta-programming design that optimizes control paths and eliminates branching, providing fast runtimes with linear scaling for any type of model.
- Modular framework with object design and interactions based on the physical phase-field problem. Separation between functional components, and separation between functional elements within components. Alongside documentation, this ensures development and extension by users is as convenient as possible.
- Multiple numerical solvers and extensive support for integration of user-implemented numerical solvers.
SymPhas is free software, distributed under the GNU Lesser General Public License (LGPL), version 3. SymPhas is designed and distributed with community development in mind, and we greatly appreciate contributions and feedback about bugs. This will not only help keep SymPhas as a valuable phase-field simulations API, but support research by ensuring other people's results can be reproduced correctly! You can let us know about bugs via the GitHub issues page.
For any major modifications to SymPhas you would wish to be included, please ensure that SymPhas can compile the examples provided and the different CMake configurations. If you would like to distribute a modified version or use part of SymPhas in your own program, the project must still be licensed using the same license as SymPhas, which is LGPL v3. It also must clearly be labeled as derived work.
Since SymPhas is supported purely by academic funding, we kindly ask you cite our paper listed at the top of this page.
While our goal is to continue expanding and improving SymPhas to enhance its usefulness for the research community, our resources are limited. We welcome any support such as bug reports, code and funding. Please feel free to contact the developers if you wish to reach out.
The API is distributed between a collection of several modules:
- lib
- Basic elements and functions used in the other modules of SymPhas. This includes program parameters, timing, Fourier transforms and more.
- Defines elements under the
symphas
namespace.
- datatypes
- Defines the basic objects and functions used in the finite difference numerical solvers.
- Defines the
Grid
class and management of grid boundaries. - Defines the
grid
namespace.
- sym
- Defines all symbolic algebra elements and their functionality.
- Defines rules of symbolic algebra expressions.
- Defines the
expr
namespace.
- sol
- Consolidates functionalities of the sym and datatypes modules into a solution framework for applying numerical solvers.
- Defines the
Solver
andModel
classes. - Defines finite difference stencils,
Stencil
for up to 4th order derivatives.
- io (optional)
- Defines functionality for input and output.
- Defines elements under the
symphas::io
namespace.
- conf (optional)
- Allows reading and writing configuration files.
The modules required for the simplest build of Symphas are lib, datatypes, sym and sol.
A driver file is then written which uses these modules to define, setup and solve a phase-field problem.
The entire SymPhas package can be downloaded from https://github.com/SoftSimu/SymPhas from the main
branch. The package can be obtained by either downloading the repository packaged as a zip (i.e. through the Github website) or by cloning the repository, which will make it convenient to be up to date with the latest development.
The SymPhas package comes with predefined model definitions and solvers, but can also be installed as a standalone API where the user defines custom solvers, models and drivers.
Before moving on to installation, please ensure:
- All the necessary requirements for the SymPhas installation are satisfied.
- You are familiar with the organization of a SymPhas installation, e.g. location of modules and how to enable them; the location of examples; the location of driver files with respect to the CMake file; and other points discussed in this tutorial.
The compilation is cross-platform compatible through CMake for either the Linux or Windows (Windows 7 and 10 are both compatible) platforms. CMake version 3.14 or higher is required for compiling and installing. The minimum required versions of the compilers which are verified to work are:
Compiler | Tested Minimum Version |
---|---|
MSVC++ | 14.28 |
gcc7 | 7.5 |
gcc10 | 10.2 |
clang | 11.0.1 |
SymPhas uses the C++17 standard. Depending on the compiler, this usually has to be explicitly indicated when compiling, either on the command line or in the CMake configuration.
Third party packages that are used and the version they have been tested with are as follows:
Package | Tested Minimum Version | Required? |
---|---|---|
FFTW3 | 3.3.7 | Yes* |
xdrfile | 2.1.2 | No |
VTK | 9.0 | No |
*FFTW may be disabled, but it would not be possible to use Fourier transform capability in SymPhas.
For any packages which are not required, they will automatically be excluded from the CMake build process if they are not found. If the required packages are not found, then the CMake configuration step will fail, in which case, the user can provide CMake with the installation location of that package.
The xdrfile package will allow output to the binary xdr format used in Gromacs. This is recommended if the output is very large. Additionally, VTK is recommended if real-time visualization is desired.
SymPhas is provided with examples of solvers, models and driver files in the examples
directory. In practise, solvers and models are defined separately from the driver file, and then included using the Cmake configuration. Although the program can be compiled without any drivers or solvers (nothing in the provided examples
directory is necessary for a successful compilation), it is recommended that at least one of the solvers is included in your compilation. Continue reading this section for more information on including models and solvers.
When installing SymPhas, it is recommended to install to a directory which different from the system install directory (such as your home directory), and also name the installation output according to the configuration, as it may be desirable to install multiple configurations at once. An example would be having one installation configured only with the core modules (e.g., so headers are installed to symphas-base/include/
), or another configured with all modules (e.g., so headers are installed to symphas-all/include
).
This will be further explained in the next sections.
Installing Dependencies
Follow the steps below to install the dependencies. If any of the packages are installed to a directory not in the CMake search directories, the location will have to be provided during the CMake configuration of SymPhas.
-
FFTW3
To install FFTW, first download the source and then use CMake to configure and install the library.
Note: Do not configure using the provided configuration file (i.e. the procedure explained here), as this will result in the package not being found by CMake.
-
xdrfile
Installing the xdrfile package is optional. Download the xdrfile source repository from the Github link provided above, or clone it using
git
, and follow the instructions provided therein to configure and install using CMake. -
VTK
Installing VTK is optional. Download the source from the website and install VTK using CMake. Select the configurations which best suit you.
Quick SymPhas Installation + Setup
This section describes setting up an installation of SymPhas for writing an empty driver file.
Once SymPhas has been downloaded, use CMake to configure the build and installation process. Assuming that the current directory is /path/of/download/
, and that FFTW is installed and detectable by cmake, downloading and configuring can be done with:
git clone https://github.com/SoftSimu/SymPhas
cd SymPhas
git checkout main
mkdir ./build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/path/to/install <desired_cmake_configuration> ..
The correct cmake configuration needs to be provided in place of desired_cmake_configuration
, which can be chosen to specify the location of the solvers and models (this is explained further below). You may wish to immediately build SymPhas using example solvers and models, which can be acccomplished using the cmake command:
cmake -DCMAKE_INSTALL_PREFIX=/path/to/install -DSOLVER_INCLUDE_HEADER_DIR=../examples/solvers -DMODEL_INCLUDE_HEADER_DIR=../examples/models -DSOLVER_INCLUDE_HEADER_NAME=solverinclude.h -DMODEL_INCLUDE_HEADER_NAME=modelinclude.h ..
If you are using CMake for building projects using your installation: The system installation should not include models or solvers, as these should typically be added through the CMake configuration of the project.
If you are using g++ for building projects using your installation: The solvers and models should be included in the installation so that they become packaged in the
symphas_all
library, and can be used in the current project.
If you wish to use SymPhas headers and library without specifying the location directly to the compiler each time, then change CMAKE_INSTALL_PREFIX
to the primary installation directory of your system. This directory is typically /usr
.
Alternatively, it is possible to set up SymPhas implementations as individual projects, that is, without installing and linking to the installation.
Depending on the FFTW installation, CMake might not be able to find the FFTW cmake include directory. In this case, change the above cmake
command to add the argument pointing to the FFTW installation:
cmake <desired configuration> -DFFTW3_DIR=/<FFTW3 installation dir>/lib/cmake/fftw3/ ..
where <desired configuration>
is the
cmake configuration you used. Change the example directory <FFTW3 installation dir>
as appropriate.
Using the SymPhas files in the directory /path/of/download
, the current directory, symphas-build
, will be populated with the default build configuration files and set the installation path of SymPhas to /path/to/install
. Cache variables may be provided to the cmake
invocation after the directory specification to change the configuration. The cache variables are listed and described in Advanced Installation.
If using a graphical interface to CMake, then all the variables and descriptions will be listed.
In a graphical interface, some variables may not appear until prerequisite variables are defined. Ensure that the project is fully configured by repeating the configuration step after any modification of variables.
Once SymPhas has been configured, execute the following commands to build and then install SymPhas:
make
make install
A new driver file may now be created, compiled and linked to the SymPhas API.
Note: Depending on the configuration of the installation, building the driver might require additional macro defines to be provided, such as
MODEL_INCLUDE_HEADER
in order to point to the directory containing model definitions. This is described in advanced installation.
The following tools are available on Windows for configuring, building and installing CMake projects:
- CMake for Windows.
- The MSVC compilers must be installed on the system.
- Visual Studio
- It must be installed with the Desktop Development for C++ component, or at least the correct
- Community version is free to use.
- Visual Studio Code
- Visual C++ (MSVC++) compilers are required, and are obtained from the C/C++ for Visual Studio Code extension.
- The CMake Tools extension is also required.
It is beyond the scope of this installation guide to provide a detailed procedure of using these tools to configure a CMake project. To get started, these tools can be used to set up SymPhas and its dependencies on Windows by:
- Using CMake for the Windows platform alongside Visual Studio.
- Using only Visual Studio (with Desktop Development for C++ component installed).
- Using Visual Studio Code.
Installing Dependencies
Using any of the methods above, the dependencies can be installed with the respective CMake tool, following the same instructions as in Linux Installation.
Note: xdrfile must be configured with the
BUILD_ARCHIVE
flag set to true in order to be used in the SymPhas build for the Windows platform.
Installing SymPhas
Use any of the methods above to configure a CMake project. Set CMAKE_INSTALL_PREFIX
to the desired installation directory when configuring.
After the CMake project is configured, compile and install the project using the appropriate tool or program.
When configuring SymPhas, providing the variable COMBINE_SHARED
set to true to the CMake invocation, a shared library called symphas_all
will be created which combines all the modules built for that configuration library. This is useful when compiling a driver file with g++
, so that only a single SymPhas library needs to be provided to the command line. This will result in increased compile time.
The following is a list of all CMake cache variables used for configuring SymPhas.
-
MODEL_CALL_FUNCTION
Specifies the name of a function templated on the specialized model type. When models are associated with string names (seeLINK_WITH_NAME
in the documentation for details), selecting a model will invoke this function with the concrete model type passed as a template parameter. The full usage of this parameter is described in the documentation. Empty by default.Models cannot be associated or selected by string names in an installation that does not have
MODEL_CALL_FUNCTION
configured. -
AVAILABLE_STENCILS_BASIC_ONLY
When this is true, configures the build so that only a small subset of stencils are allowed in the model selection, rather than all the stencils. By compiling with all the stencils, the compile times will dramatically increase, because a concrete type is generated for each stencil-model combination. True by default. -
AVAILABLE_STENCILS_AUTOGENERATION
When this is true, stencils will automatically be generated for all derivatives needed for the models included int the build. False by default. -
AVAILABLE_DIMENSIONS
Specifies the dimensions ( that are made available when compiling the solvers. Activates the definitionsAVAILABLE_STENCIL_ACCURACY_*D
corresponding to the dimension chosen. Also specifies the dimension that can be chosen when selecting a model. Specifying only a single dimension will speed up compilation times. This value is2
by default. -
MODEL_INCLUDE_HEADER_NAME
The name of the file containing the model definitions. If model definitions are distributed between multiple header files, then this file will include each one in order to combine all model definitions. This is empty by default.When
MODEL_INCLUDE_HEADER_NAME
is configured, macros associated with model definitions are undefined after including the model definitions header in order to avoid name conflicts. Consequently, models cannot be defined elsewhere, such as in the driver file. If it is not configured, models must be specified through the driver file or by providing to the compiler the definitionMODEL_INCLUDE_HEADER
set to the name of the model definitions header. -
MODEL_INCLUDE_HEADER_DIR
The directory containing the fileMODEL_INCLUDE_HEADER_NAME
. All files included by this file must also exist in this directory. If this is a relative path, this will be relative to the source code root directory (that is, relative to the source projectCMakeLists.txt
). This is.
(the current working directory) by default. -
SOLVER_INCLUDE_HEADER_NAME
The name of the file defining all the solvers. If solvers are defined in multiple header files, then this file includes those solvers which are desired to be compiled. This is empty by default.If it is not configured in the installation, solvers must be included by providing to the compiler the definition
SOLVER_INCLUDE_HEADER
set to the name of the solver definitions header. -
SOLVER_INCLUDE_HEADER_DIR
The directory containing the fileSOLVER_INCLUDE_HEADER_NAME
and solver definitions. All files included by this file must also exist in this directory. If this is a relative path, this will be relative to the source code root directory (relative toCMakeLists.txt
). This is.
by default. -
PRINTABLE_EQUATIONS
Ensures that all equations and transformed expressions can still appear as coherent text when printed. Sometimes, particularly in the case of large expressions and significant transformations on those expressions, runtimes will be shorter when this is false. This is true by default. -
USE_IO
Enable the use of the io module. -
USE_CONF
Enable compilation and usage of the conf module. RequiresUSE_IO
to be true. -
USE_VTK
Enable compiling with the VTK library to use real time visualization.
The source code is provided with solvers already available and can be found in the folder examples/solvers
in the root directory. There are also model definitions available in the examples/models
folder in the root directory.
These can be specified in the CMake configuration with the variables above, in which case installing SymPhas will also put the solvers and models in the installation directory, allowing them to be accessed from any driver file. This will effectively introduce a group of "default" models available to all driver files which use this installation.
Each element in SymPhas is extensively documented in Doxygen, and the listing can be found in docs
from the source code root directory. This section will describe how they are all used together, starting with a simple example of a driver file. A driver file requires at least one solver definition in a separate header file, and at least one model definition, defined either within in the driver file, or outside in a separate header file.
In describing elements in SymPhas, colour coding is applied to some names. The meaning of the colours is:
Color | Meaning |
---|---|
blue |
Represents a functional class in SymPhas. |
teal |
A class that represents problem information. |
purple |
An important C++ macro. |
violet |
An enum class. |
A driver file can be configured and compiled with CMake by including SymPhas with the find_package
command, or compiled directly with g++
by specifying the include and library directories. These processes will be described in more detail through the examples below.
Before writing or using any driver file, locate the solver definitions. Depending on the installation configuration, these might be included in the installation directory. If there are no solvers in the installation directory, they must be added when building the driver by passing to the compiler the definition
SOLVER_INCLUDE_HEADER
set to the solver definitions header. Solvers are required for building the driver and running any simulation.
From the source code root directory, the example discussed in this section can be found in examples/simple-driver
. Included in this directory are two files: main.cpp
, a driver file with its own model definition, and CMakeLists.txt
for configuring the CMake project. This driver file uses essential elements of SymPhas, ideal for describing the functionality and usage of SymPhas.
The driver file presents a very simple scenario where a single model is defined and solved. This begins by including the SymPhas header, symphas.h
, which includes all SymPhas components that were installed, and is required by any driver file. The model definition follows.
#include <symphas.h>
#define psi op(1)
#define dpsi dop(1)
MODEL(EX, (SCALAR),
MODEL_DEF(
dpsi = lap(psi) + (c(1) - c(2) * psi * psi) * psi)
)
In its simplest form, the model definition is constructed using C++ macros defined within SymPhas, beginning with the macro MODEL
, which takes at least three arguments:
- The model name, which can be any C++ compliant name;
- The phase-field types, surrounded by parentheses, and are any of
SCALAR
,COMPLEX
orVECTOR
; and - The dynamical equations, specified by providing the equations to the macro
MODEL_DEF
.
In the equation, the order parameter of index N
is referred to by op(N)
, and its time derivative is dop(N)
. The dynamical equation of field N
has the form: dop(N) = ...
. The symbol c(N)
are parameters of the model that are passed to the model constructor, with default value 1.0
.
The first two lines use macro definitions to create a new name for the order parameter and its derivative with respect to time, to make it easier to use in the model definition. The model definition represents a phase-field system with a real-valued order parameter evolved according to the equation:
The definition of a model introduces to the global namespace a type alias,
model_<NAME>_t
for the model class, where<NAME>
is the name of the model. This is referenced later in the file to create the model, e.g.,MODEL(EX...
introduces the type aliasmodel_EX_t
. Refer to Defining Models for more information about this.
After the model definition, the main
function is defined (program entry point), and directly specifies the simulation that will be performed.
In the main function, the model is created and the numerical solution is computed. Before initializing the model, the problem parameters have to be specified via the class problem_parameters_type
in the symphas
namespace. The configuration model conf offers an automatic way to do this by parsing an input file; refer to section Configuration. Initializing the problem parameters object is done in the line:
symphas::problem_parameters_type pp{ 1 };
where 1
is passed to indicate the problem parameters is for a single field. The problem parameters instance is invalid at this stage, and requires information about the phase-field systems, provided as arrays to the member functions:
-
The axis intervals of the phase-field systems:
set_interval_data
-
The boundary specifications of the phase-field system:
set_boundary_data
-
The initial conditions used to seed the phase-field system:
set_initial_data
The order of the elements in the data arrays corresponds to the order of the phase-fields as they are defined in the model definition. In other words, the phase-fields are initialized from the problem parameters data element whose index corresponds to the phase-field index in the model definition.
The problem parameters also takes the solution time step, dt
, used to initialize the solver.
In cases where the solver is not initialized with the time step from the problem parameters, then the time step provided to the step routine is the one used. How the time step provided to the step routine is used by the solver depends on the solver implementation.
The main function begins by setting up the problem parameters by initializing each of the data elements first:
double dt = 0.1;
symphas::problem_parameters_type pp{ 1 };
symphas::interval_element_type interval;
interval.set_count(0, 80, 128);
symphas::b_data_type bdata(2, BoundaryType::PERIODIC);
symphas::interval_data_type vdata(2, interval);
symphas::init_data_type tdata(Inside::UNIFORM, { -1, 1 });
bdata[Side::TOP] = BoundaryTag::CONSTANT << 1;
bdata[Side::BOTTOM] = BoundaryTag::CONSTANT << 1;
It is recommended to refer the documentation of these objects to know their usage specifics, as what follows is only a brief explanation related to this example.
The objects b_data_type
, init_data_type
and interval_data_type
in the symphas
namespace represent the type of the boundary, initial condition and interval data, respectively.
First, the interval is specified:
symphas::interval_element_type interval;
interval.set_count(0, 80, 128);
This creates the object interval
that represents an interval in [0, 80] with 128 discrete points. Next, the interval is used to initialize the interval data for the problem parameters by associating specific sides to the interval.
Then, the boundary and interval data objects are constructed:
symphas::b_data_type bdata(2, BoundaryType::PERIODIC);
symphas::interval_data_type vdata(2, interval);
In both cases, the first parameter represents the dimension. In order to construct the initial data, the parameters are passed directly to the constructor:
symphas::init_data_type tdata(Inside::UNIFORM, { -1, 1 });
This establishes the initial condition of the phase-field to be the uniform distribution in the range [-1, 1]. That is, each point of the phase-field is generated by seeding it with the uniform distribution with values between -1 and 1.
The boundary data is now generated:
bdata[Side::TOP] = BoundaryTag::CONSTANT << 1;
bdata[Side::BOTTOM] = BoundaryTag::CONSTANT << 1;
where the <<
operator is used to pass a parameter to the boundary type, which in this case means that the boundary will have a constant value of 1.
It is also possible to specify periodic boundary conditions in a similar way:
bdata[Side::RIGHT] = BoundaryType::PERIODIC;
bdata[Side::LEFT] = BoundaryType::PERIODIC;
but it is for the user in this case to ensure that there is consistency (i.e., both left and right have to be periodic).
Each line creates a new entry for the specified Side
in bdata
of type b_element_type
. This demonstrates the shorthand that is available which associates a BoundaryType
with a b_element_type
to directly construct the entry. This defines the boundary conditions on all sides of the system. Each side must be explicitly specified, otherwise the problem parameters are in an invalid state.
Also, it is possible to explicitly set intervals in a similar fashion:
vdata[Axis::X] = interval;
vdata[Axis::Y] = interval;
Finally, the model can be created:
model_EX_t<2, SolverSP<Stencil2d2h<5, 9, 6>>> model{ pp };
The model type corresponding to the defined model is a template type of two types: the dimension of the problem and the solver that should be used, respectively. This line therefore initializes the model as a 2-dimensional problem and specifies that the used solver is SolverSP<Stencil2d2h<5, 9, 6>>
(see Solvers for more details).
To solve the new constructed phase-field problem, the function is called:
symphas::find_solution(model, dt, 100);
which will perform 100 solver iterations. Although the time step dt
is provided to this function, depending on the solver implementation, the value may not be used. For example, the provided spectral
solver SolverSP
computes solution data based only on the time step which was provided at model construction, and does not update it afterwards.
A copy of the phase-field can be obtained with:
auto pfdata = model.grid<0>();
which takes the first phase-field in the 0-indexed list from the model.
The resulting type of the function called on last line is
Grid
, templated on the phase-field type and the model dimension. In this case, it would be the typeGrid<scalar_t, 2>
.
Linux
To compile this program, there are two options. The first is using CMake with the provided CMakeLists.txt
. This offers the potential for more customization as well as better management of larger projects. The second option is using g++
, more appropriate for this single driver file. To compile this driver file with g++
, install SymPhas and see the section Compiling and Running.
The CMake compilation can be configured by creating a directory build
inside the simple-driver
directory and executing the following command from inside build
:
cmake -DCMAKE_BUILD_TYPE:STRING="Release" -DUSE_IO:BOOL="True" -DSOLVER_INCLUDE_HEADER_DIR:PATH="../../examples/solvers" -DSOLVER_INCLUDE_HEADER_NAME:FILEPATH="solverinclude.h" ..
This can be directly executed and does not require the SymPhas package to be installed beforehand. The reason is that the configuration provided in CMakeLists.txt
will add the source code directory as a subdirectory to this build. This will also add the io module to the build.
The
solvers
directory is added relative to theCMakeLists.txt
file which is being executed.
Additionally defining the variables:
-DMODEL_INCLUDE_HEADER_DIR:PATH="../../examples/models" -DMODEL_INCLUDE_HEADER_NAME:FILEPATH="modelinclude.h"
will add all the models included in SymPhas, but will require that the model defined in main.cpp
is removed or commented away.
Subsequently running make
will create an executable symphas_impl
.
Windows
See Compiling and Running for Windows.
Always ensure that the build directory is clean.
Linux
There are two options to build and run a program, and both require that SymPhas has been installed. The first is using CMake and importing SymPhas with find_library(SymPhas)
. In order to add the SymPhas library, the variable ${SymPhas_LIBRARIES}
is provided. CMake offers the potential for customization as well as better management of larger projects.
As shown in the example of compiling the simple driver program, it is also possible to make a CMake project which uses the SymPhas source code directly, but typically it is best practise to install SymPhas with the desired configuration and add it through
find_library
.
The second option is using g++
, and typically more appropriate for a single driver file. To compile a driver file with g++
, provide the location of the installed headers and the library; these will come from the install step. The library directory also needs to be listed in the system variable LD_LIBRARY_PATH
. In the following commands, it is assumed that SymPhas was installed in /symphas/install/folder/
, use:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/symphas/install/folder/lib
If the include and library files were installed to /usr
, then these arguments can be omitted and LD_LIBRARY_PATH
does not have to be modified.
If COMBINE_SHARED
was enabled in the CMake configuration step of the installation, only a single link to SymPhas needs to be indicated by adding -lsymphas_all
.
This shared library compiles all object files that were used to compile the individual modules, so there is no explicit library dependence, except on external DSOs such as pthread
and potentially tbb
.
If the driver file is called main.cpp
, then g++
is invoked with:
g++ main.cpp -std=c++17 -I/symphas/install/folder/include -L/symphas/install/folder/lib -lsymphas_all -lpthread
Note the dependence on the pthread
library.
If this fails due to some linkage to tbb, then include
-ltbb
.
The compiler option
-std=c++17
is included because SymPhas requires the C++17 specification. Typically, this is not the default selection of the compiler so this argument must be explicitly included.
In some cases, it might be necessary to include
-lxdrfile
and-lfftw
.
This will generate an executable a.out
in the current working directory.
If COMBINE_SHARED
was not provided or is false in the CMake configuration step of the installation, then -lsymphas_all
would be replaced with -lSymPhas -l...
where ...
indicates the library files of individual modules. For example, for a base installation:
g++ main.cpp -std=c++17 -I/symphas/install/folder/include -L/symphas/install/folder/lib -lSymPhas -lsymphas_lib -lsymphas_datatypes -lsymphas_sym -lsymphas_sol -ltbb
In some cases, it might be necessary to include
-lxdrfile
and-lfftw
.
The shared libraries generated for each of the modules of SymPhas need to be explicitly linked since they are all used in the driver through the SymPhas header. If additional modules were enabled during the installation, then those would also have to be linked even if the driver does not directly use them.
If the io module is enabled, linking with the
pthread
library is also required. The headers define a class that creates a new thread which asynchronously writes phase-field data. Add-lpthread
to the compile command.
Windows
There are two options to compile in Windows, one of which is CMake. The other option is creating a new Visual Studio C++ project. In either method, the resulting executable requires that the shared libraries from both SymPhas and its dependencies are together in the folder with the executable. The simple method is copying all the necessary shared libraries after the program is compiled, as this only has to be done once, unless that folder is cleared in a clean process or otherwise deleted.
The symbolic algebra library is a very powerful part of SymPhas, equipped with full featured functionality including various expression types, a large set of expression rules and the ability to define custom expression algebra data objects. The primary function of the symbolic algebra is to define the equations of motion, but it can also be used as a standalone feature.
For a list of available expression objects, refer to Modules -> Symbolic Algebra Modules, which also includes an explanation for defining custom data objects for use in the symbolic algebra library. This section outlines a brief tutorial.
A typical use of symbolic algebra is operating on a grid in a point-wise fashion. An instance of the type Grid
is the data that is operated on. The following code will create a grid, define a variable to represent the grid, and then obtain the result of the square of the variable to update the grid.
Grid<scalar_t, 2> gridu({ 10, 10 }); // Creates a grid of dimensions 10 x 10.
// Fill the grid with random values.
srand (time(NULL));
std::generate(
gridu.values,
gridu.values + gridu.len,
[](){ return rand() / RAND_MAX; }
);
auto u = expr::make_term(gridu); // Create a variable from the grid.
expr::result(u = u * u); // Evaluate the result of squaring u, saving it back to u.
Another, longer example is given, assuming there are two grids, gridu
and gridv
, both randomly generated as above.
// Define variables u and v of the grids.
auto u = expr::make_term(gridu);
auto v = expr::make_term(gridv);
// Define an expression of u and v.
auto a0 = expr::make_literal(2.5);
auto a1 = expr::make_literal(10);
auto expr = v + a0 * expr::pow<3>(u) + v / (a1 * u);
// Store the result objects.
auto resultu = (u = expr);
auto resultv = (v = expr + v);
// Update the grids u and v.
expr::result(resultu);
expr::result(resultv);
The variable expr
above is equivalent to:
In order to get u
to the power of 3, it is possible to multiply u
three times, or use the function expr::pow
as above (which is functionally the same thing), a template function with template parameter of non-negative integer.
Expressions can be printed, and when the cmake option PRINTABLE_EQUATIONS
set to true, all expressions are guaranteed to be printable (if it is false, some expressions will be named automatically, and therefore not have a meaningful string representation). Expressions can be print to a file or print to a char
array (C-style string).
In order to print an expression expr
to a file f
, use:
expr.print(f); // Prints the expression to the given file stream.
To print to a string, a preliminary step is required, which is to ensure that the string buffer is sufficiently sized. The length of the expression is obtained through
the member function print_length()
:
char *out = new char[expr.print_length() + 1];
expr.print(out); // Prints the expression to the string.
By setting the cmake option
LATEX_FORMAT
to true, the expressions are printed in LaTeX format, in order to be copied directly into a LaTeX file and be compiled.
A full model definition takes the form:
MODEL(
NAME, // Name given to the model.
(TYPE1, TYPE2, ...), // Types of one or more order parameters.
PROVISIONAL_DEF( // Defining provisional variables is optional.
(VTYPE1, VTYPE2, ...) // Types of one more provisional variables.
var(1) = ..., // This is the definition of the first provisional
// variable, and is of type VTYPE1.
var(2) = ..., // This is the definition of the second provisional
// variable, and is of type VTYPE2.
... // More provisional variable definitions.
)
MODEL_PREAMBLE_DEF(
(
PREAMBLE // This is the preamble to the equation
... // definitions, and can define elements to
... // to use in the equations to make writing
... // easier or more clear.
)
dop(1) = ..., // This is the definition of the first order
// parameter, and is of type TYPE1.
dop(2) = ..., // This is the definition of the second order
// parameter, and is of type TYPE2.
... // More provisional variable definitions.
)
)
The indexed terms TYPE
refers to the order parameter types, and VTYPE
refers to the provisional variable types. These are any of SCALAR
, COMPLEX
or VECTOR
. The equations are always given as a comma delimited list.
The PROVISIONAL_DEF
section is entirely optional and can be omitted in a model definition.
A model definition results in the type model_<NAME>_t
, where <NAME>
is the given model name. This is the alias to the actual model object that is defined by invoking these macros. The alias is a template of two types: the dimension and the solver type. In order to instantiate a model instance, these template arguments must be provided to the alias to constitute a concrete type.
In the documentation, refer to the following items for clear explanations of the above:
MODEL
:
The beginning of a model definition. This takes all the terms associated with defining a model and constructs one.MODEL_PREAMBLE_DEF
orMODEL_DEF
:
The macros to which the equations of motion are provided. The documentation for the macroMODEL_PREAMBLE_DEF
contains all the information about defining an equation of motion for the model. This is also pasted, in part, below. The documentation also refers to how to usePREAMBLE
.
The following derivatives of expressions are supported:
grad(E)
lap(E)
gradlap(E)
bilap(E)
where E
is the expression that is being differentiated.
Derivatives of higher orders can also be specified using dx(O)
, where O
is the desired order. The usage of dx
is different from the derivatives
above, as in order to apply it, it must be multiplied by an expression. This
applies the derivative to the expression using symbolic algebra rules.
When O
< 5, then it is equivalent to the
functions above when multiplied by an expression.
A unique aspect of using dx
is that it can be added to another
dx
of a different order to create a new operator. I.e.:
dop(1) = (dx(2) + dx(4)) * op(1)
To use the model coefficients, there is the macro param(N)
, where N
refers to the N
-th coefficient in the that is given to the model, as a
1-indexed list. That is, the first coefficient is param(1)
.
Constants are used with lit(v)
, where v
is the value of the constant.
Imaginary numbers are also included. An imaginary number is referenced
using the term Ii
. The following operations of imaginary numbers are supported:
modulus(Z)
, the modulus of the number.conj(Z)
, the conjugate of the number.Re(Z)
, the real part of the complex number.Im(Z)
, the imaginary part of the complex number.
where Z
is the complex number. This usage applies to the order parameter
as well, not just coefficients.
It is also possible to use the Gaussian kernel in the equations of motion, which is a grid of the wavenumbers. Refer to the documentation for OpFuncConvolution.
Also, where the number 1 (i.e. the multiplicative identity) should be used
in an expression explicitly, it is recommended to use one
, to maximize
the advantage of the compile-time symbolic algebra.
In order to execute models, an instance of object problem_parameters_type
must be constructed
and appropriately initialized through its member functions. This is based on the parameters that represent a phase-field problem in a physical setting:
- The initial conditions.
- The boundary conditions.
- The size of the system and the spatial discretization.
Once this information is provided to the problem_parameters_type
instance, it is used to initialize the specialized model by providing it as an argument to the constructor.
This process can be automated by the conf module. By providing a configuration file, the module will parse the information and construct a parameters object.
To do this manually, each element of the parameters must be manually constructed.
The initial conditions are represented by the object init_data_type
. This contains the following information:
in
A representation of the initial condition as anInside
value.intag
A number that indicates a variation of the initial condition is used.- One of either:
data
Parameters of the initial algorithm generation.file
A file that the data is read from, as ainit_data_read
object.f_init
A wrapper for a functor which returns values for the initial condition, instead of the following algorithms.
The
intag
is a number that represents up to two enumInsideTag
values. There are constructor overloads ofinit_data_type
that allow either a singleInsideTag
or a number representing the combination ofInsideTag
values to be provided. Constructing anintag
value is done using thesymphas::build_intag
function.
An Inside
is an enum with values from the list:
Value | Description | Variations |
---|---|---|
GAUSSIAN |
Uses a Gaussian distribution to randomly assign values. | None |
UNIFORM |
Uses a uniform distribution to randomly assign values. | None |
CAPPED |
Values are assigned to be either the minimum or maximum parameter. | None |
CONSTANT |
All values are assigned to the same parameter. | None |
CIRCLE |
Value are assigned to be the shape of a circle. | RANDOM , A , A+RANDOM |
HEXAGONAL |
Values are assigned into circles arranged in a hexagonal pattern. | RANDOM |
CUBIC |
Values are assigned into circles arranged in a cubic pattern. | RANDOM |
SQUARE |
Values are assigned to be the shape of a square. | RANDOM , A , A+RANDOM |
SQUARESEEDS |
Values are put into randomly arranged squares. | RANDOM , A , A+RANDOM , B , B+RANDOM |
CIRCLESEEDS |
Values are put into randomly arranged circles. | RANDOM , A , A+RANDOM , B , B+RANDOM |
FILE |
Values are read in from a file. | None |
CHECKPOINT |
Values are read in from a checkpoint. | None |
NONE |
Represents no initial condition. | None |
An InsideTag
is an enum with values from the list:
Value | Description |
---|---|
DEFAULT |
The default initial generation algorithm is chosen. |
RANDOM |
The generation is modified to include some kind of randomness. |
VARA |
The A variation is chosen (different from the default variation). |
VARB |
The B variation is chosen. |
INVERT |
The interior and outer values are switched in the generation. (In some algorithms, the generated value is multiplied by -1.) |
NONE |
Represents no tag. |
The table that lists Inside
values also lists the variations that are compatible with that initial condition. All initial conditions support the INVERT
tag except the last three, and an initial condition without a tag is considered to be the DEFAULT
variation.
If an initial condition is generated with Inside
::NONE
and InsideTag
::NONE
, then no values are populated. If an initial condition is combined with an invalid modifier, the program reports an error and no values will be populated. The default constructed init_data_type
is initialized with Inside
::NONE
and InsideTag
::NONE
, so it is valid but will not generate any initial conditions.
Future releases of SymPhas might add more values of the above enums, refer directly to the documentation for full details.
Some initial conditions have more than one variation associated with the algorithm which populates the values, and are selected by a number representing an InsideTag
combination. For example, most algorithms support the InsideTag
::RANDOM
modifier. Refer to the documentation of class InitialConditions
, which implements all the algorithms and fully describes each of the generation algorithms. All initial conditions are defined by specializing InitialConditionsAlg
for the Inside
value and InsideTag
values.
Custom Initial Conditions
The method of algorithm types (based on Inside
values) and variations thereof is designed to accommodate configuration-based initial condition selection. However, initial condition generation is not restricted to the available algorithms, and can apply user defined algorithms instead. The requirement on the
user supplied algorithm is that it must be a functor-like object that can be called with the argument types: iter_type
(the "flattened" index of the value of the system to generate), len_type const*
(the dimensions of the system) and size_t
(the number of dimensions), and returning any type of the valid order parameter types (scalar_t
, complex_t
or vector_t
of 1, 2 or 3 dimensions). A trivial example is the following lambda:
auto all_one = [](iter_type, len_type const*, size_t dimension) -> scalar_t { return dimension; };
This algorithm would populate the entire system with a value equal to the dimension of the system.
To actually use an algorithm, it is passed directly to the init_data_type
constructor, in place of any enum values or initial condition parameters. For example, the above algorithm would be used to construct the initial conditions with:
symphas::init_data_type tdata{ all_one };
The following is another example of how to pass an initial condition algorithm based on a custom functor object that is not a lambda:
struct MirrorInitAlg
{
MirrorInitAlg(double constant) : constant{ constant } {}
scalar_t operator()(iter_type n, len_type const* dims, size_t dimension) const
{
if (dimension == 2)
{
axis_coord_t x = n % dims[0];
return (x < dims[0] / 2) ? constant : -constant;
}
return 0;
}
double constant;
};
int main()
{
symphas::init_data_type tdata{ MirrorInitAlg{ 1.0 } };
return 0;
}
This algorithm would populate half a 2-dimensional system with the given constant, and the other half with negative of the given constant. For any other dimension, the initial conditions would be uniformly 0.
The data container which represents information about boundary conditions in the context of the problem parameters is represented by b_data_type
, a map that relates the enum Side
to an object b_element_type
.
A Side
value is any of LEFT
, RIGHT
, BOTTOM
, TOP
, FRONT
and BACK
.
While the notion of a "side" of a system can be extended to other coordinate systems since it is only based on a surface bounded by a set of the intervals, these names are chosen since the design of SymPhas solvers is based in a Cartesian coordinate system.
It is assumed that the system is oriented such that x is the horizontal axis, y is the vertical axis, and z is the depth axis. Hence, LEFT
and RIGHT
are surfaces with an x-axis normal vector, BOTTOM
and TOP
are surfaces with an y-axis normal vector and FRONT
and BACK
are surfaces with an z-axis normal vector.
A 1-dimensional system is fully represented by the first two
Side
values, a 2-dimensional system by the first four, and a 3-dimensional system is represented with all values.
The relationship of the Side
value to the dimension of the system can be summarized:
Value | Axis Point | In 1 dimension (x0, x1) |
In 2 dimensions (x0, x1) × (y0, y1) |
In 3 dimensions (x0, x1) × (y0, y1) × (z0, z1) |
---|---|---|---|---|
LEFT |
x0 | x0 | y-axis at x0 | zy-plane at x0 |
RIGHT |
x1 | x1 | y-axis at x1 | zy-plane at x1 |
BOTTOM |
y0 | - | x-axis at y0 | zx-plane at y0 |
TOP |
y1 | - | x-axis at y1 | zx-plane at y1 |
FRONT |
z0 | - | - | xy-plane at z0 |
BACK |
z1 | - | - | xy-plane at z1 |
Empty entries indicate that the Side
value is inapplicable to the corresponding dimension. For each Side
value, the entries in the table describe: 1) the point in the Cartesian coordinate system corresponding to the boundary, and; 2) the boundary in terms of their relationship to a D-dimensional system as a (D-1)-dimensional object at the boundary point. The latter is best described by example:
- In a 2-dimensional system, the value
Side
::LEFT
represents the boundary at x0, given by the equation which is parallel to the y-axis. - In a 3-dimensional system, the value
Side
::BACK
corresponds to the grid points at z1, which is the boundary that is oriented to the xy-plane and given by the equation .
In this way, a local coordinate system with origin based on the global coordinate system may be imposed on the boundary, allowing SymPhas to treat boundaries as independent systems in order to populate boundary values according to a given function (these are described in the documentation).
A b_element_type
specifies the boundary information for the corresponding side, containing data for:
type
Represents the boundary condition and of typeBoundaryType
.tag
An array of twoBoundaryTag
values, representing a modification of thetype
.params
A list of values used in applying the boundary condition algorithms.args
The number of elements inparams
.
The type of boundary condition is represented by the enum BoundaryType
. These are split into two groups: periodic boundary conditions represented by PERIODIC
and all other boundary conditions,
which are considered "default", as they apply some function to the boundary to update it. To initialize a b_element_type
, provide the necessary data to the constructor.
To specify the boundary data of a system, create an instance of b_data_type
and assign b_element_type
instances to each Side
value that is part of the full system representation.
In assigning to b_data_type
, a BoundaryType
value can be used instead, in which case the other parameters will be initialized to default values.
The domain of the system is represented by intervals associated with each axis. Each interval represents the extent of the system on the corresponding axis. The interval data is managed by the object interval_data_type
, which is a map that associates Axis
values with instances of type interval_element_type
. The Axis
values of a system are:
Value | Corresponding Physical Axis |
---|---|
X |
Horizontal (1, 2 and 3 dimensions) |
Y |
Vertical (2 and 3 dimensions) |
Z |
Depth (only 3 dimensions) |
The table shows the relationship between axes and system dimensions, and shows for which dimensions the Axis
values are applicable. For example, Z
is not a valid value for a 1-dimensional system, only the value X
can be used. This is because, as was similarly mentioned in the description of boundaries, the dimensionality of a system is considered to be an extension of the previous dimension.
The type interval_element_type
represents a simple interval, unrelated to a specific axis. It stores the endpoints of the interval and the width between discrete elements, h.
An instance of interval_element_type
is constructed using the endpoints along with either the spatial discretization, or the number of discrete points.
The endpoint values when provided to the interval construction are interpreted as [A,B], meaning that the last endpoint is included in the grid points. The implication is that B-A+h is the length of the axis used in computing the number of grid points. This is intended to make interval specification more convenient and clear. For example, specifying that an interval spans from 1 to 64 means that the number of elements is 64 when h=1, however, when h=0.5, the number of elements is 127 (not 128).
To specify the interval data of a system, create an instance of interval_data_type
and assign interval_element_type
instances to each Axis
value that is part of the full system representation.
The SymPhas API offers an extremely versatile framework to allow the user to develop their own solver, centered primarily around the functionality provided by the symbolic algebra library. Defining the body of a solver is straightforward and explained in the documentation, under Modules -> Solver Definition.
Two solvers are included with the distribution of SymPhas. These are the Euler solver, which is forward time, central space (SolverFT
); and a semi-implicit Fourier spectral solver (SolverSP
).
The SolverFT
supports all order parameter types, and up to fourth order derivatives; SolverSP
supports only complex and scalar types, and any even-order derivatives.
Checkpoints are saved 10 times over the course of a solution, meaning that over N
steps, every N % 10
will have the phase-fields saved to a checkpoint file. This behaviour can be changed by specifying checkpoint_count=N
on the command line. If N=0
, no checkpoints are saved.
In order to load a previous checkpoint, the user specifies the command line option checkpoint=<checkpoint_location>[,index]
, where checkpoint_location
specifies the checkpoint directory of a previous execution, and index
is the optional value which specifies the index to load from. If it is not given, then the index is the most recent one determined from the backup configuration.
If the index given in the checkpoint
option is not found in the loaded checkpoint data, then the execution will not be able to proceed (the program will exit) because the systems must be initialized from the precise index.
The configuration file contains the name of the model to simulate and the parameters of its solution. The basic syntax of the configuration file allows the user to include comments when the line text begins with the #
(pound) character. Additionally, if the line begins with the !
(exclamation mark) character, the text that follows is taken to be the title of the simulation (there can only be one such line).
The given title is also parsed into a filename friendly format which is assigned to the subdirectory into which the program output is saved.
The documentation of Configuration
goes into detail about the format, including about how to specify more than one system simultaneously, but some simple information is presented here.
The parameters can be divided into 5 groups: 1) solution parameters; 2) system parameters; 3) the model parameter; 4) data parameters; and 5) name parameters. These groups are purely logical in nature and the manner in which they are set or defined is unrelated to the implementation.
The solution parameters are the group of parameters which control the behaviour of the solver. These parameters and their descriptions are:
-
DIM
the dimension of the system being modeled.- Valid input are the numbers 1, 2 or 3.
-
ORDER
the chosen order of accuracy for finite difference stencils (which may or may not be used depending on the solver itself).- Valid input are the numbers 2 or 4.
-
WIDTH
the spatial separation between cell boundaries in the grid.- Takes any positive floating point number.
-
PTL
the number of cells covered by the Laplacian finite difference stencil.- Valid input depends on the order and dimension.
-
PTB
as above, but for the Bilaplacian stencil. -
PTG
as above, but for the Gradlaplacian stencil.
The next group of parameters controls the system and the system generation:
-
RNG(X|Y|Z)
two floating point numbers specifying the start and end of the interval on the given axis. This may also be specified asRNG(R|T|F)
if theFORM
is not chosen to beCARTESIAN
. They can also be specified as@ N
whereN
indicates the number of points to put on that axis. -
BND(LEFT|RIGHT|TOP|BOTTOM|FRONT|BACK)
a keyword, optionally followed by values, specifying the boundary condition and its parameters. -
INSIDE
specifies the initial conditions of the system by passing a keyword followed by parameters associated with that keyword. There are both random and nonrandom types of initial conditions, as well as the ability to pass in a file of values with which to initialize the system. In multi-phase-field systems, separate initial conditions can be given to every field by surrounding each initial condition specification in either quotes or brackets. The initial conditions are applied in order of the fields specified in the model definition. Any field not explicitly specified will use the initial conditions of the first field.
The third parameter group only contains a single parameter, MODEL
; it chooses the dynamical equations used to evolve the system from its initial conditions by selecting a specialized model. The configuration saves the string, and it is left to the user in the implementation to choose how to interpret it. By using the CMake configuration parameter MODEL_CALL_FUNCTION
and defining models with LINK_WITH_NAME
, this process can be automated.
See the documentation for model_select
.
The next parameter group, in part, specifies the time evolution characteristics of the solution. It also controls the output data of the solution. The parameters and their description are:
-
DELTA
the time difference between concurrent steps in the solution.- Takes any positive floating point number.
-
FRAMES
the total number of frames or indices that the solution simulates.- Valid input is any nonnegative integer. If 0, then the program will execute but no solution iterations are performed.
-
SAVE
the frame interval at which the solution state is saved to the output directory.- Valid input is any positive integer.
-
SAVEINIT
chooses whether to save the data for the initialized state (the system at the 0th index).- Valid input is either "YES" or "NO". If nothing is provided, then it is automatically "NO".
SymPhas defines a number of program parameters in order to change behaviour of various aspects involved in simulating a model. There are a number of parameters, some of which are module-dependent. The current list is:
Base Parameters:
EXTEND_BOUNDARY
When true, ghost cells are added to the dimensions of a generated system, instead of being incorporated in the total dimensions. That is, if a system is generated of size128 x 128
, then settingEXTEND_BOUNDARY
to true will set the memory size of the system to be134 x 134
(the thickness of the boundary is 3 on each edge).false
by default.VIZ_ENABLED
Enables VTK visualization,false
by default.VIZ_INTERVAL
Sets the frame interval at which to update the visualization. Setting this value to anything will setVIZ_ENABLED
totrue
automatically.VIZ_INDEX
Defines the index of the field to visualize.0
by default.INIT_INSIDE_VAL
For initial generation algorithms, defines the interior values use.1
by default.INIT_OUTSIDE_VAL
For initial generation algorithms, defines the outer values to use.-1
by default.INIT_RAND_VAL
For initial generation algorithms with random variation, typically sets the strength of the randomness.1
by default.PARALLELIZATION
Turns parallelization of expression evaluation on or off.true
by default.
IO module Parameters:
SINGLE_INPUT
All input is read to a single file,true
by default.SINGLE_OUTPUT
All output is put to a single file,true
by default.USE_TIMESTAMP
The plotting output will have an additional parent directory named using the timestamp that the plotting output was initialized.PLOTS_ONLY
Only the plots will be generated. This is only useful when running the simulation through a chosenMODEL_CALL_FUNCTION
given to the cmake configuration.READER
The type of the reader that is used to in processing input files. Chosen by values ofsymphas::IOType
; eitherGNU
,XDR
,COLUMN
,MOVIE
, orCSV
.WRITER
The type of the reader that is used to in processing input files. Possible values are the same as inREADER
.READER_AND_WRITER
Sets both theREADER
andWRITER
.
sol module Parmaeters
REG_RESIZE_FACTOR
Sets the factor by which the minimum iterable area found for a field is expanded to become the regional grid.REG_RESIZE_TIME
Sets the time increment at which the regional grid dimensions and position reevalauted.REG_RESIZE_FIXED
Defines that the original shape found for the regional grid is fixed.REG_RESIZE_CUTOFF
This value is added to the minimum value to get the cutoff used in determining the area of the grid.
To set these parameters, names and values are "appended" to a specific enum value, PARAMS
. The line using namespace params;
needs to be written before the parameters are set. The convenient format is used:
PARAMS += <NAME> << <VALUE>, ...;
Additional <NAME> << <VALUE>
pairs can be added after the comma. An example of setting single output file behaviour to false, as well as the visualiztion interval to 10, is:
using namespace params;
PARAMS += SINGLE_OUTPUT << false, VIZ_INTERVAL << 10;
This will set single output to false, and the visualization interval to one update every 10 frames, with one call.
In the example driver functionality
, examples of setting the parameters are provided as shown above.
These parameters are typically changed through the command line. In the example driver simultaneous-config
, the symphas::init
function initializes program parameters from the command line, as well as the global configuration. This function takes either the configuration name, or if it detects an argument, treats the first argument as a parameter instead.
Calling symphas::init
with no arguments will print the command line options for changing all the parameters, plus a short description.