inline void
FixedTripleListTypesInteractionTemplate<_Potential>::computeVirialTensor(Tensor &w) {
  LOG4ESPP_INFO(theLogger, "compute the virial tensor for the FixedTriple List");

  Tensor wlocal(0.0);
  const bc::BC& bc = *getSystemRef().bc;
  for (FixedTripleList::TripleList::Iterator it(*fixedtripleList); it.isValid(); ++it) {
    const Particle &p1 = *it->first;
    const Particle &p2 = *it->second;
    const Particle &p3 = *it->third;
    int type1 = p1.type();
    int type2 = p2.type();
    int type3 = p3.type();
    const Potential &potential = getPotential(type1, type2, type3);
    Real3D r12, r32;
    bc.getMinimumImageVectorBox(r12, p1.position(), p2.position());
    bc.getMinimumImageVectorBox(r32, p3.position(), p2.position());
    Real3D force12, force32;
    potential._computeForce(force12, force32, r12, r32);
    wlocal += Tensor(r12, force12) + Tensor(r32, force32);
  }

  // reduce over all CPUs
  Tensor wsum(0.0);
  boost::mpi::all_reduce(*mpiWorld, wlocal, wsum, std::plus<Tensor>());
  w += wsum;
}
    template < typename _AngularPotential > inline void
    FixedTripleAngleListInteractionTemplate < _AngularPotential >::
    computeVirialTensor(Tensor& w) {
      LOG4ESPP_INFO(theLogger, "compute the virial tensor of the triples");

      Tensor wlocal(0.0);
      const bc::BC& bc = *getSystemRef().bc;
      for (FixedTripleAngleList::TripleList::Iterator it(*fixedtripleList); it.isValid(); ++it){
        const Particle &p1 = *it->first;
        const Particle &p2 = *it->second;
        const Particle &p3 = *it->third;
        //const Potential &potential = getPotential(0, 0);
        Real3D r12, r32;
        bc.getMinimumImageVectorBox(r12, p1.position(), p2.position());
        bc.getMinimumImageVectorBox(r32, p3.position(), p2.position());
        Real3D force12, force32;

        real currentAngle = fixedtripleList->getAngle(p1.getId(), p2.getId(), p3.getId());
        
        potential->_computeForce(force12, force32, r12, r32, currentAngle);
        wlocal += Tensor(r12, force12) + Tensor(r32, force32);
      }
      
      // reduce over all CPUs
      Tensor wsum(0.0);
      boost::mpi::all_reduce(*mpiWorld, (double*)&wlocal,6, (double*)&wsum, std::plus<double>());
      w += wsum;
    }
    inline void
    FixedQuadrupleListInteractionTemplate < _DihedralPotential >::
    computeVirialTensor(Tensor& w) {
      LOG4ESPP_INFO(theLogger, "compute the virial tensor of the quadruples");
    
      Tensor wlocal(0.0);
      const bc::BC& bc = *getSystemRef().bc;

      for (FixedQuadrupleList::QuadrupleList::Iterator it(*fixedquadrupleList); it.isValid(); ++it) {
        const Particle &p1 = *it->first;
        const Particle &p2 = *it->second;
        const Particle &p3 = *it->third;
        const Particle &p4 = *it->fourth;

        Real3D dist21, dist32, dist43; 

        bc.getMinimumImageVectorBox(dist21, p2.position(), p1.position());
        bc.getMinimumImageVectorBox(dist32, p3.position(), p2.position());
        bc.getMinimumImageVectorBox(dist43, p4.position(), p3.position());

        Real3D force1, force2, force3, force4;

        potential->_computeForce(force1, force2, force3, force4,
                                dist21, dist32, dist43);

        // TODO: formulas are not correct yet

        wlocal += Tensor(dist21, force1) - Tensor(dist32, force2);
      }
      // reduce over all CPUs
      Tensor wsum(0.0);
      boost::mpi::all_reduce(*mpiWorld, (double*)&wlocal, 6, (double*)&wsum, std::plus<double>());
      w += wsum;
    }
inline void
FixedQuadrupleListTypesInteractionTemplate<_DihedralPotential>::
computeVirialTensor(Tensor &w, real z) {
    LOG4ESPP_INFO(theLogger, "compute the virial tensor of the quadruples");

    Tensor wlocal(0.0);
    const bc::BC &bc = *getSystemRef().bc;

    std::cout << "Warning!!! computeVirialTensor in specified volume doesn't work for "
              "FixedQuadrupleListTypesInteractionTemplate at the moment" << std::endl;

    for (FixedQuadrupleList::QuadrupleList::Iterator it(*fixedquadrupleList); it.isValid(); ++it) {
        const Particle &p1 = *it->first;
        const Particle &p2 = *it->second;
        const Particle &p3 = *it->third;
        const Particle &p4 = *it->fourth;

        longint type1 = p1.type();
        longint type2 = p2.type();
        longint type3 = p3.type();
        longint type4 = p4.type();

        const Potential &potential = getPotential(type1, type2, type3, type4);

        Real3D dist21, dist32, dist43;

        bc.getMinimumImageVectorBox(dist21, p2.position(), p1.position());
        bc.getMinimumImageVectorBox(dist32, p3.position(), p2.position());
        bc.getMinimumImageVectorBox(dist43, p4.position(), p3.position());

        Real3D force1, force2, force3, force4;

        potential.computeForce(force1, force2, force3, force4,
                               dist21, dist32, dist43);

        // TODO: formulas are not correct yet

        wlocal += Tensor(dist21, force1) - Tensor(dist32, force2);
    }
    // reduce over all CPUs
    Tensor wsum(0.0);
    boost::mpi::all_reduce(*mpiWorld, (double *) &wlocal, 6, (double *) &wsum, std::plus<double>());
    w += wsum;
}