I'm writing a code for the Discrete Element Method where I have balls (spheres) and walls (planes) interacting with each other.
Those simulations are run for billions of time steps, so performance here really matters. Right now, I'm considering different designs and am not sure which one is the best.
I'll try to explain them and my doubts.
Alternative 1 - probably the best for maintainability
One class for the balls:
class Balls:
/* contains:
geometry
forces
positions
velocities
etc.
of balls */
One class for the walls:
class Walls:
/* contains:
geometry
forces
positions
velocities
etc.
of Walls */
An assembly which also contains the solver:
class Assembly:
/* contains:
balls object
walls object
other parameters for the assembly
Solver:
method to compute interactions balls-balls and walls-balls
method to advance time (time integration)
The question here is, how do I get the less overhead? The solver has to access almost all attributes of the other two classes. Shall I write getters or declare the World
class as friend
of the other two?
Alternative 2 - could become a mess
A solver class:
class Solver:
/* Contains:
some solver related parameters (e.g., step size)
Two methods:
method to compute interactions balls-balls and walls-balls
method to advance time (time integration)
An assembly class which contains all the definitions of the walls and balls
class Assembly:
/* contains basically all attributes of the two
classes Walls and Balls shown in the alternative 1 and
a method which calls the two methods of the class solver
by passing the balls/walls attributes by reference */
Also here, is it then better to pass the attributes by reference, to declare the World
class as friend
of the Solver
class, or to use getters?
Alternative 3 - the less maintainable
Combine everything in just one class (not really considered).
Finally, what's the design that reduce the most the overhead? Can you suggest any better design than mine?
EDIT: to be noted is that in the classes Balls
and Walls
I would store everything in one object. So an object Balls balls
will contain for example (if the whole assembly only contains 2 balls):
vector<Eigen::Vector3d> ball_positions = {Eigen::Vector3d(x1,y1,z1),
Eigen::Vector3d(x2,y2,z2)}
vector<double> ball_radii = {r1,r2}