[lammps-users] Problem initializing objects in Stillinger-Weber

Dear LAMMPS users,

I'm trying to write a diagnostic for the Stillinger-Weber potential,
which I want to implement as a compute (comnpute_sw_test.cpp).
Unfortunately I'm having problems initializing objects of the class
PairSW in my compute. For example, in the loop over neighbors
pair_sw.cpp contains the line
   itype = map[type[i]];
and map is declared in pair_sw.h as
   class PairSW : public Pair {
    private:
       int *map;
   };

By analogy my compute contains the line
   itype = force->pair->map[type[i]];
but LAMMPS crashes with a memory access failure when it reaches this
line. The debugger gives the error message "force should have been
initialized in a superclass ctor". Simply redefining map as public in
pair_sw.h and in pair.h doesn't solve the problem, and anyway I'm not
sure what declarations I should make in compute_SW_test.h. I get similar
problems with the array elem2param, the functions twobody and threebody
and the structure params, all of which are also defined as private in
pair_sw.h.

What changes do I need to make in order to access the objects of PairSW?
I attach my stripped-down code for compute_sw_test to illustrate what
I'm trying to do, and style.h. The changes I made to style.h are
indicated with the phrase "begin/end Philip's changes".

For the record, a similar diagnostic for the pair interaction
pair_lj_cut.cpp works without any problems. pair_lj_cut.h contains the
declaration
   class PairLJCut : public Pair {
    public:
     void single(int, int, int, int, double, double, double, int, One
&);
   };
and pair.h contains the declaration
   class Pair : protected Pointers {
    public:
     Pair(class LAMMPS *);
     virtual ~Pair() {}

force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,1,one);
   };
and my diagnostic happily executes the line
   force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,1,one);

Many thanks in advance for any help you can give me.

Philip

PS: I wrote my compute before the release of 15 December 2007, so it
still assumes the old-style structure of the neighbor lists. Obviously
I'll change this to make it compatible with the newversion, but that
has nothing to do with the above problem.

pair.h (4.84 KB)

compute_SW_test.cpp (5.08 KB)

compute_SW_test.h (1.2 KB)

From the perspective of the rest of LAMMPS, the

pair ptr is a generic pointer to a parent Pair class, not to
a child class, like PairSW. Thus you would have
to cast it to a PairSW pointer if you want to
access datums peculiar to PairSW. You can get
around the public/private issue, by your new compute
a "friend" class in the PairSW header.

However, creating a compute that accesses the inner
workings of PairSW (or any other pair class) is not
a particularly good design choice. There could be
pitfalls with trying to access/invoke various internal functions
and data from outside the class. The only really safe
way to access a lo-level Pair class is thru the public interface
provided in the parent Pair class.

Steve

Steve,

Thanks for suggesting the use of the "friend" class. However,
I'm afraid I don't understand your last comment about going
through the public interface provided in the parent Pair class.

For my compute (which calculates the heat flux) I need to know
the force exerted on atom i by stoms j and k, and
this information is only available from the inner workings of
PairSW. Thus after a Verlet step I call my compute, in which I
need to evaluate the functions "twobody" and "threebody",
which in turn requires me to use the object "map" defined in
PairSW. I thought that by writing
  itype = force->pair->map[type[i]];
I was going through the parent Pair class. Please could you
explain what I need to do to access the inner workings
of PairSW robustly (or point me to an analgous compute in
LAMMPS).

Thanks,

Philip

From the perspective of the rest of LAMMPS, the

pair ptr is a generic pointer to a parent Pair class, not to
a child class, like PairSW. Thus you would have
to cast it to a PairSW pointer if you want to
access datums peculiar to PairSW. You can get
around the public/private issue, by your new compute
a "friend" class in the PairSW header.

However, creating a compute that accesses the inner
workings of PairSW (or any other pair class) is not
a particularly good design choice. There could be
pitfalls with trying to access/invoke various internal functions
and data from outside the class. The only really safe
way to access a lo-level Pair class is thru the public interface
provided in the parent Pair class.

Steve

The issue is that you can't use a parent class ptr
and access things peculiar to a specific child class,
PairSW in this case. You'e need to do something
like this in your compute:

PairSW *pairsw = (PairSW *) pair;
pairsw->twobody();

Steve