-
Pascal Engeler authoredPascal Engeler authored
- RBComb simulation framework
- Unit tests
- Implementing a new project
- Classes
- Vec2 (vec2.hpp), 2-vector utility class
- Diagonalizer (diagonalizer.hpp), class to diagonalize symmetric Matrices
- DrumParameters(drum_parameters.hpp), describes static state of a drum
- DrumVariables (drum_variables.hpp), describes dynamic state of a drum
- Drum (drum.hpp), represents a single drum top resonator
- Force (force.hpp), force functional
- Driver (driver.hpp), calculate drive of drums
- Coupler (coupler.hpp), calculate couplings between drums
- LatticeGenerator (lattice_generator.hpp), generates drum lattices
- Neighbour ordering convention
- Inexistent neighbour convention
- MatrixElementCalculator (matrix_element_calculator.hpp), calculates matrix elements
- RK4Buffer (rk4_buffer.hpp), holds Rk4Stepper intermediate results
- Rk4Stepper (rk4_stepper.hpp), performs timesteps using rk4 scheme
- SystemParameters (system_parameters.hpp), holds system parameters
- Grabber (grabber.hpp), grabs and saves data
- System (system.hpp), holds all parts together
RBComb simulation framework
This project aims at developing a framework that can be used to simulate any project that is to be undertaken on the RBComb platform. It is designed in modular fashion, such that it is flexible enough to adapt easily to any given situation. The list of contents is the following:
Unit tests
Unit tests are available in the subfolder unit_tests
. They can be run from within
that directory by issuing make run
. They should all compile and run fine.
Implementing a new project
In order to implement a new project, follow these steps:
- Create a new folder in
projects
.- Create subfolders
bin
,include
,lib
andresults
- Copy the
lib
contents intoprojects/newproj/lib
- Create subfolders
- Identify force on a single drum
- Depends on static parameters (w, m, a, etc.) and dynamic parameters and variables (x, v, etc.).
- Coupling and driving parameters are dynamic.
- Write custom versions of classes
DrumParameters
(everything that is static) andDrumVariables
(everything that is dynamic) to accomodate these. Inspiration inlib/drum_variables.hpp
andlib/drum_parameters.hpp
. - Write custom
Grabber
that extracts the relevant data (inspiration ininclude/grabber.hpp
) - Write custom child of
Force
to calculate the force. - Write custom children of
Coupler
andDriver
to correctly update the drive and couplings. - If desired, write a custom child of
LatticeGenerator
to generate a custom lattice, or use the generatorprojects/braidingTightBinding/include/rbcomb_generator_braid.hpp
to create the RBComb. - If desired, write a child of
MatrixElementCalculator
to calculate matrix elements for the dynamic matrix. - Check the unit tests (
unit_tests
) or other projects to see how amain.cpp
could be constructed.
Hints for organizing, building and running simulations
- Use a Makefile.
- The framework should be compiled with c++ 2a.
- The
Diagonalizer
requires LAPACK to be linked. - Get inspiration from other projects.
- Organize executables in
bin
- Store data and plots in subfolders of
results
Classes
The code is structured in an object oriented approach. The classes that likely will
not need to be adapted for a new situation are found in the lib
folder. They are
described in the following. Note that qualifiers, references and the like are discarded
where it improves legibility. Consult the source files for more information.
Vec2
(vec2.hpp), 2-vector utility class
- Template arguments
-
value_t
: type of vector entries
-
- Explicit constructors
Vec2(const value_t, const value_t)
Vec2(const Vec2&)
Vec2()
Vec2& operator=(const Vec2&)
- Members
- Access
-
value_t x()
- returns x entry
-
value_t y()
- returns y entry
-
Vec2 normalized()
- returns normalized version of vector
-
value_t r()
- returns length
-
value_t phi()
- returns angle (
std::atan2
version of it)
- returns angle (
-
- Member functions
-
value_t r_wrt(Vec2)
- returns length with origin at argument
-
value_t phi_wrt(Vec2)
- returns angle with origin at argument
-
value_t norm()
- returns norm
-
value_t norm_sq()
- returns square of norm
-
- Modifiers
-
Vec2 normalize()
- normalizes the vector and returns it
- throws when zero-vector
-
Vec2 rotate(Vec2, value_t)
- rotates the vector and returns it
-
- Supported Operators, All of these work as one would expect
-
*
withVec2
(inner product) andvalue_t
-
/
withvalue_t
- throws upon division by zero
-
+, -
withVec2
- All versions of
op=
of the above -
[]
withstd::size_t
-
<<
withstd::ostream
-
- Access
- Dependents
DrumParameters
-
LatticeGenerator
children
- Dependencies
- None
Diagonalizer
(diagonalizer.hpp), class to diagonalize symmetric Matrices
- Explicit constructors
Diagonalizer()
- Member functions
-
std::vector<double> ev(std::vector<double> mat, size_t N)
- returns eigenvalues of the symmetric matrix mat of linear size N
- throws upon diagonalization failure
-
std::pair<std::vector<double>, std::vector<double> > evv(std::vector<double> mat, size_t N)
- returns pair of (eigenvalues, eigenvectors) of the symmetric matrix mat of size N
- throws upon diagonalization failure
-
- Further developments
- Only finding eigenvectors and -values in a certain range may be added later on
- Dependents
System
- Dependencies
- None
DrumParameters
(drum_parameters.hpp), describes static state of a drum
- Explicit constructors
- Determined by implementation
- Member functions
- None or determined by implementation
- Public data members
- Determined by implementation
- Typical dependents
Driver
Coupler
-
Force
children Grabber
-
MatrixElementCalculator
children -
LatticeGenerator
children
- Typical dependencies
Vec2
DrumVariables
(drum_variables.hpp), describes dynamic state of a drum
- Explicit constructors
- Determined by implementation
- Member functions
- None or determined by implementation
- Public data members
- Determined by implementation
- Must include (required by System and Drum)
- Central drive coupling
value_t V
- Neighbour couplings
value_t t0
,value_t t1
,value_t t2
- Central drive coupling
- Must include (required by Rk4Stepper)
- current displacement
value_t x
- current displacement storage
value_t x_temp
- current velocity
value_t xdot
- current velocity storage
value_t xdot_temp
-
var
andvar_temp
must be initialized to the same value.
- current displacement
- Typical dependents
Driver
Coupler
-
Force
children Grabber
-
MatrixElementCalculator
children -
System
through private push_dc() -
Drum
(see this issue).
- Typical dependencies
Vec2
- Remarks
- Respect the constraints given by this issue.
Drum
(drum.hpp), represents a single drum top resonator
- Template arguments
-
value_t
: Scalar type -
params_t
: Drum parameters container type -
vars_t
: Drum variables container type -
sbuffer_t
: Stepper buffer container type
-
- Explicit constructors
Drum(const params_t&)
Drum() = delete
Drum(const Drum&)
Drum& operator=(const Drum&)
- Access
-
params_t get_parameters()
- returns the parameters, const and reference versions implemented
-
vars_t get_variables()
- returns the variables, const and reference versions implemented
-
sbuffer_t get_sbuffer()
- returns the stepper buffer, const and reference versions implemented
-
- Modifiers
-
void set_coupling_0(value_t)
- Sets coupling 0
- deprecated
-
void set_coupling_1(value_t)
- Sets coupling 1
- deprecated
-
void set_coupling_2(value_t)
- Sets coupling 2
- deprecated
-
void set_drive(value_t)
- Sets central electrode coupling
- deprecated
-
- Dependents
-
Coupler
children -
Driver
children -
Force
children -
LatticeGenerator
children -
MatrixElementCalculator
children Rk4Stepper
System
Grabber
-
- Dependencies
- None
- Description
- A drum is described by a set of (static) parameters (stiffness, mass, x-y position, etc),
which are to be stored in a container of type
params_t
. The variables (displacement, velocity, electrode charges, etc.) are stored in a container of typevars_t
. Example classes for these two types arelib/drum_parameters.hpp
andlib/drum_variables.hpp
. However, these containers likely need to be adapted to the situation at hand. When time evolving, the stepper will use the container of typesbuffer_t
to store its intermediate results. Note that the default constructor of this class isdelete
'd. It should be constructed from an object of typeparams_t
.
- A drum is described by a set of (static) parameters (stiffness, mass, x-y position, etc),
which are to be stored in a container of type
- Further developments
- Abstract interfaces for
params_t
andvars_t
could be added, but they would be trivial.
- Abstract interfaces for
Force
(force.hpp), force functional
- Template arguments
-
value_t
: Scalar type -
params_t
: Drum parameters type -
vars_t
: Drum variables type -
buffer_t
: Stepper buffer type
-
- Explicit constructors
Force()
- Virtual functions
-
value_t operator()(drum_t drum, drum_t n1, drum_t n2, drum_t n3, value_t time)
- Returns force on
drum
attime
, given its three neighboursn1
,n2
,n3
- Returns force on
-
- Typical dependents
-
Rk4Stepper
, but only virtually
-
- Typical dependencies
Drum
params_t
vars_t
- Description
- This interface is a guide to complete implementation of a force functional. Any force functional should derive from this class, but the child type should then be used in order to avoid the vtable penalty.
- The type
drum_t
is aDrum
with the given template arguments. Typically, this functional would make heavy use of theDrum
access membersget_parameters()
andget_variables()
. Thetime
argument of the functional exists to fit special cases as well. The fileinclude/force_simple.hpp
showcases how a real force functional could be written.
Driver
(driver.hpp), calculate drive of drums
- Template arguments
-
value_t
: Scalar type -
drum_t
: Drum type
-
- Explicit constructors
Driver()
- Virtual functions
-
void precompute(value_t t_end, value_t dt, std::vector<drum_t> drum_vec)
- Called once at begin of
System
lifetime
- Called once at begin of
-
void step(value_t dt)
- Move in time by
dt
- Move in time by
-
value_t operator()(size_t drum_index)
- Returns drive of drum
drum_index
(wrtdrum_vec
) at current time
- Returns drive of drum
-
- Typical dependents
-
System
, but only virtually
-
- Typical dependencies
drum_t
DrumParameters
DrumVariables
- Description
- This interface is a guide to complete implementation of a drive calculation class. Any driver class should derive from this class, but the child type should then be used in order to avoid the vtable penalty.
- The purpose of this class is to set the drive of each drum at specific times.
- In the
precompute
function, this class is passed all information it could need about the system. Hence it can in principle precompute all values for all drums and all times of the simulation. - The member
step
is called to inform theDriver
that time is advanced by the passed argument. Note that an rk4 scheme advances time in twinned steps ofdt/2
. - The functional should return the current drive on the drum with index passed as argument.
- An example implementation of a
Driver
is shown ininclude/driver_simple.hpp
.
Coupler
(coupler.hpp), calculate couplings between drums
- Template arguments
-
value_t
: Scalar type -
drum_t
: Drum type
-
- Explicit constructors
Coupler()
- Virtual functions
-
void precompute(value_t t_end, value_t dt, std::vector<drum_t> drum_vec)
- Called once at begin of
System
lifetime
- Called once at begin of
-
void step(value_t dt)
- Move in time by
dt
- Move in time by
-
value_t operator()(size_t drum_index, size_t neighbour_index)
- Returns coupling between drums
drum_index
andneighbour_index
(wrtdrum_vec
) at current time
- Returns coupling between drums
-
- Typical dependents
-
System
, but only virtually
-
- Typical dependencies
drum_t
DrumParameters
DrumVariables
- Description
- This interface is a guide to complete implementation of a coupling calculation class. Any coupler class should derive from this class, but the child type should then be used in order to avoid the vtable penalty.
- The purpose of this class is to set the coupling of each neighbouring pair of drums at specific times.
- In the
precompute
function, this class is passed all information it could need about the system. Hence it can in principle precompute all values for all drums and all times of the simulation. - The member
step
is called to inform theCoupler
that time is advanced by the passed argument. Note that an rk4 scheme advances time in twinned steps ofdt/2
. - The functional should return the current coupling between the two drums with indices passed as arguments.
- An example implementation of a
Coupler
is shown ininclude/coupler_simple.hpp
.
LatticeGenerator
(lattice_generator.hpp), generates drum lattices
- Template arguments
-
value_t
: Scalar type -
params_t
: Drum parameters type -
vars_t
: Drum variables type -
sbuffer_t
: Stepper buffer type
-
- Explicit constructors
LatticeGenerator()
- Virtual functions
-
std::pair<std::vector<drum_t>, std::vector<int> > operator()(params_t)
- Takes a
params_t
- Returns a pair that characterizes the generated lattice
- a vector of drums
ds
- an adjacency vector of vectors
adj
, such thatds[i]
andds[adj[i][0]]
are neighbours
- a vector of drums
- All drums have the same
params_t
, except that theposition
members differ.
- Takes a
-
- Description
- An example child of the
LatticeGenerator
is shown in the fileinclude/rbcomb_generator.hpp
.
- An example child of the
- Further developments
- In the future, there may be another overload for the functional. For example, it could either take an
std::vector<params_t>
or an additional random number generator to construct the drums differently.
- In the future, there may be another overload for the functional. For example, it could either take an
- Dependents
- None
- Typical dependencies
Neighbour ordering convention
An important note is the convention of neighbour ordering. Each drum has neighbours 0 thru 3. For drums in different sublattices, these neighbours are:
- Sublattice 'A':
- 0,
adj[0]
: straight down - 1,
adj[1]
: top left - 2,
adj[2]
: top right
- 0,
- Sublattice 'B':
- 0,
adj[0]
: straight up - 1,
adj[1]
: bottom right - 2,
adj[2]
: bottom left Here adj[] signifies the adjacency list of the given drum. Similarly, the couplings t0 thru t2 in objects of typeparams_t
should also respect this ordering. More generally, whenever neighbours of a specific drum are ordered in some fashion, they are assumed to respect the above convention. Note that with this convention, neighbours see each other as the same neighbour index (the i-th neighbour of j sees j as its i-th neighbour). Never violate this convention.
- 0,
Inexistent neighbour convention
Another convention concerns inexistent neighbours. For that purpose, this class should append
an auxiliary drum to the end of the drum vector. If neighbour i of a drum does not exist
(due to boundary, for example), the corresponding neighbour index will point to the
auxiliary drum, i.e. it will show an index drum_vec.size()
. All couplings of this auxiliary
drum are to be kept at 0. This condition can then be applied in force calculation to avoid branching,
if one uses the couplings of the neighbours instead of the considered drum.
MatrixElementCalculator
(matrix_element_calculator.hpp), calculates matrix elements
- Template arguments
-
value_t
: Scalar type -
params_t
: Drum parameters type -
vars_t
: Drum variables type -
drum_t
: Drum type
-
- Explicit constructors
MatrixElementCalculator()
- Virtual functions
-
value_t operator()(size_t index, std::vector<drum_t>)
- Returns the diagonal element (index, index).
-
value_t operator()(size_t index1, size_t index2, std::vector<drum_t>)
- Returns the coupling element (index1, index2), where these are each others neighbour 0
-
value_t operator()(size_t index1, size_t index2, std::vector<drum_t>, int)
- Returns the coupling element (index1, index2), where these are each others neighbour 1
-
value_t operator()(size_t index1, size_t index2, std::vector<drum_t>, int, int)
- Returns the coupling element (index1, index2), where these are each others neighbour 2
-
- Description
- The overload of the functional is done to avoid branching. When building the matrix, one calls the individual functions correctly to accomodate the correct neighbours.
- Dependents
-
System
, but only virtually
-
- Typical dependencies
params_t
vars_t
-
drum_t
(existence ofget_parameters()
andget_variables()
)
RK4Buffer
(rk4_buffer.hpp), holds Rk4Stepper intermediate results
- Description
- This class must never be changed except when changing stepper
Rk4Stepper
(rk4_stepper.hpp), performs timesteps using rk4 scheme
- Template arguments
-
value_t
: Scalar type -
params_t
: Drum parameters container type -
vars_t
: Drum variables container type -
buffer_t
: Stepper buffer container type -
force_t
: Force functional type
-
- Explicit constructors
Rk4Stepper()
- Member functions
void step_1(force_t, std::vector<drum_t>, std::vector<std::vector<int> >, value_t dt, value_t time)
void step_2(force_t, std::vector<drum_t>, std::vector<std::vector<int> >, value_t dt, value_t time)
-
void step_3(force_t, std::vector<drum_t>, std::vector<std::vector<int> >, value_t dt, value_t time)
- All of the above perform one step of a timestep, between successive steps certain other updates need to be taken care of by the owner object.
- Arguments: Force functional, Drum vector, Adjacency vector, time step, start time of current step
- Dependents
System
- Dependencies
-
force_t
, but only virtually buffer_t
Drum
-
vars_t
, see DrumVariables
-
SystemParameters
(system_parameters.hpp), holds system parameters
- Template arguments
-
coupler_t
: Coupler type -
driver_t
: Driver type
-
- Explicit constructors
SystemParameters(coupler_t, driver_t, std::vector<std::vector<int> >)
- Public data members
-
coupler
: The coupler_t object of the system -
driver
: The driver_t object of the system -
adjacency_vector
: Astd::vector<std::vector<int> >
representing the adjacency vector
-
- Dependents
System
- Dependencies
- None
Grabber
(grabber.hpp), grabs and saves data
- Template arguments
-
value_t
: Scalar type -
drum_t
: Drum type
-
- Explicit constructors
-
Grabber(const size_t grab_every, const std::string params_file, const std::string adjacency_file, const std::string dynamic_file)
-
grab_every
: stride between data grabs -
params_file
: file for parameters saving -
adjacency_file
: file for lattice adjacency saving -
dynamic_file:
file for dynamics saving
-
Grabber() = delete
Grabber(const Grabber&)
-
- Member functions
-
void init(value_t t_end, value_t dt, std::vector<drum_t>, std::vector<std::vector<int> >)
- Called upon
System
lifetime start.
- Called upon
-
bool grab(std::vector<drum_t>, value_t time)
- Grabs data from the drums.
- May use current time to decide if to grab data.
- Returns
true
if data was grabbed.
-
bool save()
- Saves data to the specified files.
- Is called by
System
. - Returns
true
on success.
-
- Dependents
System
- Dependencies
Drum
DrumParameters
DrumVariables
- Description
- This class needs to be re-implemented whenever either
DrumParameters
orDrumVariables
changes. - One should also implement a helper struct, as seen in
include/grabber.hpp
- This class needs to be re-implemented whenever either
System
(system.hpp), holds all parts together
- Template arguments
-
value_t
: Scalar type -
drum_t
: Drum type -
grabber_t
: Data exfiltrator type -
sysparams_t
: System parameters type -
force_t
: Force functional type -
coupler_t
: Coupler type -
driver_t
: Driver type -
stepper_t
: Stepper type -
matelecalc_t
: Matrix element calculator type
-
- Explicit constructors
-
System(const value_t t_end, const value_t dt, const std::vector<drum_t>& ds, const stepper_t s, const force_t f, const sysparams_t sp, const grabber_t g)
-
t_end
: Temporal simulation length -
dt
: Simulation time step -
ds
: Vector of drums -
s
: Time stepper -
f
: Force functional -
sp
: System parameters -
g
: Grabber
-
-
- Member functions
-
void simulate()
- Runs a simulation with the set parameters.
-
void step()
- Performs one timestep with the set parameters.
-
void reset_time()
- Resets the simulation time to zero.
-
void set_step(value_t)
- Sets the timestep.
-
bool save()
- Calls
grabber_t::save()
.
- Calls
-
std::vector<value_t> get_matrix(matelecalc_t)
- Returns the dynamic matrix as provided by the argument.
-
- Dependents
- None
- Dependencies
- All of them. Don't change this class before thinking a lot.