473,326 Members | 2,175 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Template Meta Programming Techniques

I work with molecular simulations. In a normal infinate space
simulation, a particle can occupy any cartesian position in space.

If i want the distance between two particles in a system I can use:

Maths::dvector va, vb;
// Code here: Do something to initialise variables and move them around...
double distance = dist(va,vb);

I am currently looking at 'Periodic boundary simulations'. By this i
mean, I am simulating particles in a box, and when a particle goes off
one edge of the box, it comes back on the other side... Easy stuff -
very usesful in molecular dynamics.

<see example code below>

As dist(Maths::dvector& va, Maths::dvector& vb) is an inline function,
it has overall good performance. However if i want to now have a
'generalised' simulation class, my OOP experience tells me that I should
have a 'Space' class that manages calls like 'dist' for any arbritary
derived space system. Thus (via virtual calls) when I call getDistance()
in 'InfiniteSpace' I just call dist(), but when I call it in
'PeriodicRectangular' it takes the 'periodic cube' into account.

My problem is therefore one of performance. When I have a pointer to an
instance of a class that derives from 'Space', the compiler can't inline
the code when getDistance() is called, so performance sux. This goes
away if you make specialised classes, but that defeats the whole point
of inheritance and being generalised.

So my question is, is there a way of giving my simulation a Template
Meta Argument e.g. Simulation<Space sto avoid the need to have
'virtual' all over the place. I have scratched my head and cant really
think of the best way to do this...

Any Ideas Guys??

Many Thanks For Any Comments,
Jon Rea

-------------
Example Code:
-------------

class Space {
public:
Space(){};
virtual ~Space(){};

inline virtual double getDistance(
const Maths::dvector &va,
const Maths::dvector &vb
) const = 0;
}

class InfiniteSpace: public Space {
public:
InfiniteSpace(){};
virtual ~InfiniteSpace(){};

inline virtual double getDistance(
const Maths::dvector &va,
const Maths::dvector &vb
) const
{
return dist(va,vb);
}
}
class PeriodicRectangular: public Space {
public:
PeriodicRectangular(double allsize):
boxSize(allsize,allsize,allsize),
halfBoxSize(boxSize);

virtual ~PeriodicRectangular(){};

inline void getVector(
const Maths::dvector &va,
const Maths::dvector &vb,
Maths::dvector &vavb
) const
{
vavb.diff(vb,va);

if(vavb.innerdot() < sqrSaveDistance) return;

// find closest image of vb.x;
if(vavb.x halfBoxSize.x) vavb.x -= boxSize.x;
if(vavb.x < -halfBoxSize.x) vavb.x += boxSize.x;

// find closest image of vb.y;
if(vavb.y halfBoxSize.y) vavb.y -= boxSize.y;
if(vavb.y < -halfBoxSize.y) vavb.y += boxSize.y;

// find closest image of vb.z;
if(vavb.z halfBoxSize.z) vavb.z -= boxSize.z;
if(vavb.z < -halfBoxSize.z) vavb.z += boxSize.z;
}
inline virtual double getDistance(
const Maths::dvector &va,
const Maths::dvector &vb
{
Maths::dvector vavb;
getVector(va,vb,vavb);
return vavb.mag();
}
)

Simulate( Space* mySpace )
{
// Do some simulating ...
for( int i = 0; i < xxx; i++ )
mySpace->getDistance( blaA, blaB );
}
Oct 9 '06 #1
5 1824
Jon Rea wrote:
I work with molecular simulations. [..]

I am currently looking at 'Periodic boundary simulations'. By this i mean,
I am simulating particles in a box, and when a particle goes off one edge
of the box, it comes back on the other side... [..]
"It" comes back? Are you sure? I thought the whole point is that when
a particle leaves, it leaves forever, and *another one* comes into the
box to play.
As dist(Maths::dvector& va, Maths::dvector& vb) is an inline function,
it has overall good performance. However if i want to now have a
'generalised' simulation class, my OOP experience tells me that I
should have a 'Space' class that manages calls like 'dist' for any
arbritary derived space system. Thus (via virtual calls) when I call
getDistance() in 'InfiniteSpace' I just call dist(), but when I call
it in 'PeriodicRectangular' it takes the 'periodic cube' into account.

My problem is therefore one of performance. [..]
I don't have an immediate solution for you, especially considering that
I don't have a slightest idea about molecular simulations. But if the
molecule goes outside the box, shouldn't you stop using it in your
simulation and instead use the other one (not "it"), which comes into
the box from the opposite side?

The idea here is that instead of trying to simulate the infinite space
and the infinite number of particles, you take a sample of the space,
limiting it to your box, and only use those particles that are inside
your box at any time.

If you continue trying to track those particles, you're essentially
trying to solve the same infinite space problem using the same number
of particles, only now you make it more difficult to track them.

Of course, it all could be pointless blabber, since I don't really
know squat about molecular simulations.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 9 '06 #2
Jon Rea wrote:
>
So my question is, is there a way of giving my simulation a Template
Meta Argument e.g. Simulation<Space sto avoid the need to have
'virtual' all over the place. I have scratched my head and cant really
think of the best way to do this...
I'm not sure if this will help ... but take a look at this paper
(especially sections 1.3 and 1.3.3):
http://osl.iu.edu/~tveldhui/papers/techniques/

This is from the same webpage that you mentioned in your last post.

-- Szabolcs
Oct 9 '06 #3
Jon Rea wrote:
So my question is, is there a way of giving my simulation a Template
Meta Argument e.g. Simulation<Space sto avoid the need to have
'virtual' all over the place. I have scratched my head and cant really
think of the best way to do this...

Any Ideas Guys??
Hi Jon,

Why do you want to use polymorphism? Why not just use a common
functional interface? I'm a bit puzzled, because what you describe
seems to be standard stuff for the most simple usage of templates
conceivable.

As I don't know your surrounding program, it is impossible to tell
whether you want to store the space group in some global variable. In
that case boost::any would be your candidate.

Anyway, have a look at the following which should both be fast and
generic:

#include <iostream>
struct InfiniteSpace {
inline double getDistance(){std::cout << "using infinite space\n";}
};
struct PeriodicRectangular {
inline double getDistance(){std::cout << "using periodic
boundaries\n";}
};
template <typename T>
void Simulate(T& t)
{
std::cout << "Calling function "<<__FUNCTION__<<"\n";
t.getDistance();
};
int main() {
bool use_periodic=true;
InfiniteSpace i;
PeriodicRectangular p;
if (use_periodic)
Simulate (p);
else
Simulate (i);
}

Oct 9 '06 #4
F.J.K. wrote:
Jon Rea wrote:
>So my question is, is there a way of giving my simulation a Template
Meta Argument e.g. Simulation<Space sto avoid the need to have
'virtual' all over the place. I have scratched my head and cant really
think of the best way to do this...

Any Ideas Guys??

Hi Jon,

Why do you want to use polymorphism? Why not just use a common
functional interface? I'm a bit puzzled, because what you describe
seems to be standard stuff for the most simple usage of templates
conceivable.

As I don't know your surrounding program, it is impossible to tell
whether you want to store the space group in some global variable. In
that case boost::any would be your candidate.

Anyway, have a look at the following which should both be fast and
generic:

#include <iostream>
struct InfiniteSpace {
inline double getDistance(){std::cout << "using infinite space\n";}
};
struct PeriodicRectangular {
inline double getDistance(){std::cout << "using periodic
boundaries\n";}
};
template <typename T>
void Simulate(T& t)
{
std::cout << "Calling function "<<__FUNCTION__<<"\n";
t.getDistance();
};
int main() {
bool use_periodic=true;
InfiniteSpace i;
PeriodicRectangular p;
if (use_periodic)
Simulate (p);
else
Simulate (i);
}
The issue is this:

Avove is not quite right for my system because there's a single place
where the particular type of Space is stored: so more like this:

struct Space{
inline double getDistance(){std::cout << "base space\n";}
};

struct InfiniteSpace:puiblic Space {
inline double getDistance(){std::cout << "using infinite space\n";}
};

struct PeriodicRectangular: public Space {
inline double getDistance(){std::cout << "using periodic
boundaries\n";}
};

template <typename T>
void Simulate(T& t)
{
std::cout << "Calling function "<<__FUNCTION__<<"\n";
t.getDistance();
};

int main() {
bool use_periodic=true;
InfiniteSpace i;
PeriodicRectangular p;
Space = the_chosen_space;
if (use_periodic)
the_chosen_space = &p;
else
the_chosen_space = &i;

Simulate( *t );
}

now this wont work because *t is of type Space (no matter what it
actually points to) and so you'll always get the <Spaceversion of
the template function not the appropriate one (i think) - one'd have
to do a dynamic up cast ..

Am I making sense?

Cheers,
Jon
Oct 9 '06 #5
Jon Rea wrote:
F.J.K. wrote:
As I don't know your surrounding program, it is impossible to tell
whether you want to store the space group in some global variable. In
that case boost::any would be your candidate.
Avove is not quite right for my system because there's a single place
where the particular type of Space is stored: so more like this:
Actually that was what I was referring to in above sentence ;-) At this
point you have two choices. You can use boost::any and its any.type() +
anycast <>() to do the the proper typecasting. I think (but I'm only a
newbie and welcome being corrected) that RTTI and typeid() won't work,
if you don't use virtual functions, which is the whole point.

Or you can keep track of what's really in your variable yourself with
an extra variable like use_periodic and do the typecasting yourself.

Most quantum mechanical or molecular mechanics programs I know of keep
track themselves. While theoretically this allows for runtime errors,
practically it gives you total control over when and where you use
polymorphism (manually, in your if clauses) and when you can't afford
the cost. Even very old QM Fortran programs like Gaussian use
polymorphism in that sense.
now this wont work because *t is of type Space (no matter what it
actually points to) and so you'll always get the <Spaceversion of
the template function not the appropriate one (i think) - one'd have
to do a dynamic up cast ..
Am I making sense?
Yup. That's exactly what dynamic_casts<are good for. However in
certain situations, union + static_cast would be equally good, maybe
even better. Ask yourself if there really is a common implementation
base for your Space classes. In the example you gave, there isn't. The
only thing they share is a functional interface, the availability of
the getDistance() function. In that case: don't use inheritance.

Take a look at vector<and list<>. They both implement functions like
push_back() or size(). Yet there's practically no overlap in
implementation. Consequently the STL isn't so stupid as to define a
class container<so that vector<T>:container<Tand
list<T>:container<T>. Learn from the mistakes of the early class
libraries which did exactly this and were slow as hell and do it the
STL way :-)

#include <iostream>
struct InfiniteSpace{
double getDistance(){std::cout << "using infinite space\n";}
};
struct PeriodicRectangular{
double getDistance(){std::cout << "using periodic boundaries\n";}
};
union Space {
InfiniteSpace infinite_space;
PeriodicRectangular periodic_rectangular;
};
template <typename T>
void Simulate(T& t)
{
std::cout << "Calling function "<<__FUNCTION__<<"\n";
t.getDistance();
};
int main() {
bool use_periodic=false;
Space space;
if (use_periodic)
Simulate(space.periodic_rectangular);
else
Simulate(space.infinite_space);
}

Oct 10 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Dave | last post by:
Would people agree with the statement that to a large degree, using template metaprogramming techniques turns a C++ compiler into a C++ interpreter (but just for the metaprogrammed portions of the...
4
by: Ingo Nolden | last post by:
Hi, I want to write a template class that holds another class that uses the same template. This recursion should stop after a predefined number. I think it's either impossible or easy, but I...
5
by: Steve | last post by:
Hi, Does C++ allow the programmer to declare a template with in a template so that a generic function can instantiate the embedded template? For example, could code such as this exist: ...
2
by: Ganesh | last post by:
I am not sure if the question is relevant to this group. Is there a proof that template metaprogramming is Turing-complete? Is the proof trivial - just replace all the template instantiaion with...
8
by: Jon Rea | last post by:
http://osl.iu.edu/~tveldhui/papers/Template-Metaprograms/meta-art.html Can anyone shed some light on the need for stuff like this when using any of the most modern compilers? If i have a...
35
by: Steven T. Hatton | last post by:
Perhaps I'm just a bit frustrated, and I will soon realize the clear truth of the matter, but right now I have some serious misgivings about the value of investing a lot of time and effort into...
3
by: gary.bernstein | last post by:
I want to call a singleton getInstance function to retrieve a templatized object without knowing what types were used to create the singleton object in the first call to getInstance. How can I do...
7
by: Kevin | last post by:
I'm creating a template to support state machines. In doing so, I need to pass an enumeration for the number of transitions and a non type parameter for the range of the enum (to allow me to...
3
by: stdlib99 | last post by:
Hi, I have a simple question regarding templates and meta programming. I am going to try and work my way through the C++ Template Metaprogramming, a book by David Abrahams and Aleksey...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.