Exemplo n.º 1
0
/* ///////////////////////////////////////////////////////////////////////////
// Routine:  Vopot_gradient
//
// Authors:  Nathan Baker
/////////////////////////////////////////////////////////////////////////// */
VPUBLIC int Vopot_gradient(Vopot *thee, double pt[3], double grad[3]) {

    Vatom *atom;
    int iatom;
    double T, charge, eps_w, xkappa, size, val, *position;
    double dx, dy, dz, dist;
    Valist *alist;

    VASSERT(thee != VNULL);

    eps_w = Vpbe_getSolventDiel(thee->pbe);
    xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe);
    T = Vpbe_getTemperature(thee->pbe);
    alist = Vpbe_getValist(thee->pbe);


    if (!Vmgrid_gradient(thee->mgrid, pt, grad)) {

        switch (thee->bcfl) {

            case BCFL_ZERO:
                grad[0] = 0.0;
                grad[1] = 0.0;
                grad[2] = 0.0;
                break;

            case BCFL_SDH:
                grad[0] = 0.0;
                grad[1] = 0.0;
                grad[2] = 0.0;
                size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe);
                position = Vpbe_getSoluteCenter(thee->pbe);
                charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe);
                dx = position[0] - pt[0];
                dy = position[1] - pt[1];
                dz = position[2] - pt[2];
                dist = VSQR(dx) + VSQR(dy) + VSQR(dz);
                dist = (1.0e-10)*VSQRT(dist);
                val = (charge)/(4*VPI*Vunit_eps0*eps_w);
                if (xkappa != 0.0) 
                  val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                val = val*Vunit_ec/(Vunit_kb*T);
                grad[0] = val*dx/dist*(-1.0/dist/dist + xkappa/dist);
                grad[1] = val*dy/dist*(-1.0/dist/dist + xkappa/dist);
                grad[2] = val*dz/dist*(-1.0/dist/dist + xkappa/dist);
                break;

            case BCFL_MDH:
                grad[0] = 0.0;
                grad[1] = 0.0;
                grad[2] = 0.0;
                for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) {
                    atom = Valist_getAtom(alist, iatom);
                    position = Vatom_getPosition(atom);
                    charge = Vunit_ec*Vatom_getCharge(atom);
                    size = (1e-10)*Vatom_getRadius(atom);
                    dx = position[0] - pt[0];
                    dy = position[1] - pt[1];
                    dz = position[2] - pt[2];
                    dist = VSQR(dx) + VSQR(dy) + VSQR(dz);
                    dist = (1.0e-10)*VSQRT(dist);
                    val = (charge)/(4*VPI*Vunit_eps0*eps_w);
                    if (xkappa != 0.0)
                      val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                    val = val*Vunit_ec/(Vunit_kb*T);
                    grad[0] += (val*dx/dist*(-1.0/dist/dist + xkappa/dist));
                    grad[1] += (val*dy/dist*(-1.0/dist/dist + xkappa/dist));
                    grad[2] += (val*dz/dist*(-1.0/dist/dist + xkappa/dist));
                }
                break;

            case BCFL_UNUSED:
                Vnm_print(2, "Vopot:  Invalid bcfl (%d)!\n", thee->bcfl);
                return 0;

            case BCFL_FOCUS:
                Vnm_print(2, "Vopot:  Invalid bcfl (%d)!\n", thee->bcfl);
                return 0;

            default:
                Vnm_print(2, "Vopot_pot:  Bogus thee->bcfl flag (%d)!\n", 
                  thee->bcfl);
                return 0;        
                break;
        }

        return 1;
    } 

    return 1;

}
Exemplo n.º 2
0
/* ///////////////////////////////////////////////////////////////////////////
// Routine:  Vopot_curvature
//
//   Notes:  cflag=0 ==> Reduced Maximal Curvature
//           cflag=1 ==> Mean Curvature (Laplace)
//           cflag=2 ==> Gauss Curvature
//           cflag=3 ==> True Maximal Curvature
//   If we are off the grid, we can still evaluate the Laplacian; assuming, we
//   are away from the molecular surface, it is simply equal to the DH factor.
//
// Authors:  Nathan Baker
/////////////////////////////////////////////////////////////////////////// */
VPUBLIC int Vopot_curvature(Vopot *thee, double pt[3], int cflag, 
  double *value) {

    Vatom *atom;
    int i, iatom;
    double u, T, charge, eps_w, xkappa, dist, size, val, *position, zkappa2;
    Valist *alist;

    VASSERT(thee != VNULL);

    eps_w = Vpbe_getSolventDiel(thee->pbe);
    xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe);
    zkappa2 = Vpbe_getZkappa2(thee->pbe);
    T = Vpbe_getTemperature(thee->pbe);
    alist = Vpbe_getValist(thee->pbe);

    u = 0;

    if (Vmgrid_curvature(thee->mgrid, pt, cflag, value)) return 1;
    else if (cflag != 1) {
        Vnm_print(2, "Vopot_curvature:  Off mesh!\n");
        return 1;
    } else {

        switch (thee->bcfl) {

            case BCFL_ZERO:
                u = 0;
                break;

            case BCFL_SDH:
                size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe);
                position = Vpbe_getSoluteCenter(thee->pbe);
                charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe);
                dist = 0;
                for (i=0; i<3; i++)
                  dist += VSQR(position[i] - pt[i]);
                dist = (1.0e-10)*VSQRT(dist);
                if (xkappa != 0.0) 
                  u = zkappa2*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                break;

            case BCFL_MDH:
                u = 0;
                for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) {
                    atom = Valist_getAtom(alist, iatom);
                    position = Vatom_getPosition(atom);
                    charge = Vunit_ec*Vatom_getCharge(atom);
                    size = (1e-10)*Vatom_getRadius(atom);
                    dist = 0;
                    for (i=0; i<3; i++)
                      dist += VSQR(position[i] - pt[i]);
                    dist = (1.0e-10)*VSQRT(dist);
                    if (xkappa != 0.0)
                      val = zkappa2*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                    u = u + val;
                }
                break;

            case BCFL_UNUSED:
                Vnm_print(2, "Vopot_pot:  Invlid bcfl (%d)!\n", thee->bcfl);
                return 0;

            case BCFL_FOCUS:
                Vnm_print(2, "Vopot_pot:  Invlid bcfl (%d)!\n", thee->bcfl);
                return 0;

            default:
                Vnm_print(2, "Vopot_pot:  Bogus thee->bcfl flag (%d)!\n", 
                  thee->bcfl);
                return 0;        
                break;
        }

        *value = u;
    }

    return 1;

}
Exemplo n.º 3
0
void pbdirectpolforce_(double uind[maxatm][3], double uinp[maxatm][3],
                       double rff[maxatm][3], double rft[maxatm][3]) {

    Vpmg  *pmg[NOSH_MAXCALC];
    Vpmgp *pmgp[NOSH_MAXCALC];
    Vpbe  *pbe[NOSH_MAXCALC];
    MGparm *mgparm = VNULL;
    PBEparm *pbeparm = VNULL;
    Vatom *atom = VNULL;
    double kT, force[3], torque[3];
    double sign, zkappa2, epsp, epsw;
    int i,j;

    for (i=0; i<NOSH_MAXCALC; i++) {
       pmg[i] = VNULL;
       pmgp[i] = VNULL;
       pbe[i] = VNULL;
    }

    // Read the converged induced dipole data into APBS Vatom structures.
    for (i=0; i < alist[0]->number; i++){
       atom = Valist_getAtom(alist[0],i);
       Vatom_setInducedDipole(atom, uind[i]);
       Vatom_setNLInducedDipole(atom, uinp[i]);
       for (j=0;j<3;j++){
          rff[i][j] = 0.0;
          rft[i][j] = 0.0;
       }
    }

    for (i=0; i<2; i++) {

       VASSERT(permU[i] != VNULL);
       VASSERT(indU[i] != VNULL);
       VASSERT(nlIndU[i] != VNULL);

       pmg[i] = VNULL;
       pmgp[i] = VNULL;
       pbe[i] = VNULL;

       /* Useful local variables */
       mgparm = nosh->calc[i]->mgparm;
       pbeparm = nosh->calc[i]->pbeparm;

       /* Set up problem */
       if (!initMG(i, nosh, mgparm, pbeparm, realCenter, pbe,
                   alist, dielXMap, dielYMap, dielZMap,
                   kappaMap, chargeMap, pmgp, pmg, potMap)) {
           Vnm_tprint( 2, "Error setting up MG calculation!\n");
           return;
       }

       if (i == 0) {
         sign = -1.0;
       } else {
         sign = 1.0;
       }

       // Q-Phi Force & Torque
       if (!pmg[i]->pmgp->nonlin &&
          (pmg[i]->surfMeth == VSM_SPLINE ||
           pmg[i]->surfMeth == VSM_SPLINE3 ||
           pmg[i]->surfMeth == VSM_SPLINE4)) {
          for (j=0; j < alist[0]->number; j++){
             Vpmg_qfDirectPolForce(pmg[i], permU[i], indU[i], j, force, torque);
             rff[j][0] += sign * force[0];
             rff[j][1] += sign * force[1];
             rff[j][2] += sign * force[2];
             rft[j][0] += sign * torque[0];
             rft[j][1] += sign * torque[1];
             rft[j][2] += sign * torque[2];
             Vpmg_qfNLDirectPolForce(pmg[i], permU[i],
                                     nlIndU[i], j,force,torque);
             rff[j][0] += sign * force[0];
             rff[j][1] += sign * force[1];
             rff[j][2] += sign * force[2];
             rft[j][0] += sign * torque[0];
             rft[j][1] += sign * torque[1];
             rft[j][2] += sign * torque[2];
           }
           // Dieletric Boundary Force
           epsp = Vpbe_getSoluteDiel(pmg[i]->pbe);
           epsw = Vpbe_getSolventDiel(pmg[i]->pbe);
           if (VABS(epsp-epsw) > VPMGSMALL) {
              for (j=0; j < alist[0]->number; j++){
                 Vpmg_dbDirectPolForce(pmg[i], permU[i], indU[i], j, force);
                 rff[j][0] += sign * force[0];
                 rff[j][1] += sign * force[1];
                 rff[j][2] += sign * force[2];
                 Vpmg_dbNLDirectPolForce(pmg[i], permU[i], nlIndU[i], j, force);
                 rff[j][0] += sign * force[0];
                 rff[j][1] += sign * force[1];
                 rff[j][2] += sign * force[2];
              }
           }
           // Ionic Boundary Force
           zkappa2 = Vpbe_getZkappa2(pmg[i]->pbe);
           if (zkappa2 > VPMGSMALL) {
               for (j=0; j < alist[0]->number; j++){
                  Vpmg_ibDirectPolForce(pmg[i], permU[i], indU[i], j, force);
                  rff[j][0] += sign * force[0];
                  rff[j][1] += sign * force[1];
                  rff[j][2] += sign * force[2];
                  Vpmg_ibNLDirectPolForce(pmg[i], permU[i],
                                          nlIndU[i], j, force);
                  rff[j][0] += sign * force[0];
                  rff[j][1] += sign * force[1];
                  rff[j][2] += sign * force[2];
               }
           }
       }
    }

    // kT in kcal/mol
    kT = Vunit_kb * (1e-3) * Vunit_Na * 298.15 / 4.184;
    for (i=0; i<alist[0]->number; i++){
       rff[i][0] *= kT;
       rff[i][1] *= kT;
       rff[i][2] *= kT;
       rft[i][0] *= kT;
       rft[i][1] *= kT;
       rft[i][2] *= kT;
    }

    killMG(nosh, pbe, pmgp, pmg);
}
Exemplo n.º 4
0
VPUBLIC int Vopot_pot(Vopot *thee, double pt[3], double *value) {

    Vatom *atom;
    int i, iatom;
    double u, T, charge, eps_w, xkappa, dist, size, val, *position;
    Valist *alist;

    VASSERT(thee != VNULL);

    eps_w = Vpbe_getSolventDiel(thee->pbe);
    xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe);
    T = Vpbe_getTemperature(thee->pbe);
    alist = Vpbe_getValist(thee->pbe);

    u = 0;

    /* See if we're on the mesh */
    if (Vmgrid_value(thee->mgrid, pt, &u)) {

        *value = u;

    } else {

        switch (thee->bcfl) {

            case BCFL_ZERO:
                u = 0;
                break;

            case BCFL_SDH:
                size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe);
                position = Vpbe_getSoluteCenter(thee->pbe);
                charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe);
                dist = 0;
                for (i=0; i<3; i++)
                  dist += VSQR(position[i] - pt[i]);
                dist = (1.0e-10)*VSQRT(dist);
                val = (charge)/(4*VPI*Vunit_eps0*eps_w*dist);
                if (xkappa != 0.0) 
                  val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                val = val*Vunit_ec/(Vunit_kb*T);
                u = val;
                break;

            case BCFL_MDH:
                u = 0;
                for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) {
                    atom = Valist_getAtom(alist, iatom);
                    position = Vatom_getPosition(atom);
                    charge = Vunit_ec*Vatom_getCharge(atom);
                    size = (1e-10)*Vatom_getRadius(atom);
                    dist = 0;
                    for (i=0; i<3; i++)
                      dist += VSQR(position[i] - pt[i]);
                    dist = (1.0e-10)*VSQRT(dist);
                    val = (charge)/(4*VPI*Vunit_eps0*eps_w*dist);
                    if (xkappa != 0.0)
                      val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size));
                    val = val*Vunit_ec/(Vunit_kb*T);
                    u = u + val;
                }
                break;

            case BCFL_UNUSED:
                Vnm_print(2, "Vopot_pot:  Invalid bcfl flag (%d)!\n", 
                  thee->bcfl);
                return 0;

            case BCFL_FOCUS:
                Vnm_print(2, "Vopot_pot:  Invalid bcfl flag (%d)!\n", 
                  thee->bcfl);
                return 0;

            default:
                Vnm_print(2, "Vopot_pot:  Bogus thee->bcfl flag (%d)!\n", 
                  thee->bcfl);
                return 0;        
                break;
        }

        *value = u;

    }

    return 1;

}
Exemplo n.º 5
0
void apbsempole_(int *natom, double x[maxatm][3],
                 double rad[maxatm], double rpole[maxatm][13],
                 double *total,
                 double energy[maxatm], double fld[maxatm][3],
                 double rff[maxatm][3], double rft[maxatm][3]) {

    /* Misc. pointers to APBS data structures */
    Vpmg  *pmg[NOSH_MAXCALC];
    Vpmgp *pmgp[NOSH_MAXCALC];
    Vpbe  *pbe[NOSH_MAXCALC];
    MGparm *mgparm = VNULL;
    PBEparm *pbeparm = VNULL;
    Vatom *atom = VNULL;

    /* Vgrid configuration for the kappa and dielectric maps */
    double nx,ny,nz,hx,hy,hzed,xmin,ymin,zmin;
    double *data;
    double zkappa2, epsp, epsw;

    /* Loop indeces */
    int i,j;

    /* Observables and unit conversion */
    double sign, force[3], torque[3], field[3];
    double kT,electric,debye;
    double charge, dipole[3], quad[9];
    debye = 4.8033324;

    for (i=0; i<NOSH_MAXCALC; i++) {
       pmg[i] = VNULL;
       pmgp[i] = VNULL;
       pbe[i] = VNULL;
    }

    /* Kill the saved potential Vgrids */
    for (i=0; i<2; i++){
        if (permU[i] != VNULL) Vgrid_dtor(&permU[i]);
        if (indU[i] != VNULL) Vgrid_dtor(&indU[i]);
        if (nlIndU[i] != VNULL) Vgrid_dtor(&nlIndU[i]);
    }

    /* Kill the old atom list */
    if (alist[0] != VNULL) {
       Valist_dtor(&alist[0]);
    }

    /* Create a new atom list (mol == 1) */
    if (alist[0] == VNULL) {
       alist[0] = Valist_ctor();
       alist[0]->atoms = Vmem_malloc(alist[0]->vmem, *natom, (sizeof(Vatom)));
       alist[0]->number = *natom;
    }

    /* Read TINKER input data into Vatom instances. */
    for (i=0; i < alist[0]->number; i++){
       atom = Valist_getAtom(alist[0],i);
       Vatom_setAtomID(atom, i);
       Vatom_setPosition(atom, x[i]);
       Vatom_setRadius(atom, rad[i]);
       charge = rpole[i][0];
       Vatom_setCharge(atom, charge);
       dipole[0] = rpole[i][1];
       dipole[1] = rpole[i][2];
       dipole[2] = rpole[i][3];
       Vatom_setDipole(atom, dipole);
       quad[0] = rpole[i][4];
       quad[1] = rpole[i][5];
       quad[2] = rpole[i][6];
       quad[3] = rpole[i][7];
       quad[4] = rpole[i][8];
       quad[5] = rpole[i][9];
       quad[6] = rpole[i][10];
       quad[7] = rpole[i][11];
       quad[8] = rpole[i][12];
       Vatom_setQuadrupole(atom, quad);
       /* Useful check
       printf(" %i %f (%f,%f,%f)\n",i,rad[i], x[i][0], x[i][1], x[i][2]);
       printf(" %f\n %f,%f,%f\n", charge, dipole[0], dipole[1], dipole[2]);
       printf(" %f\n", quad[0]);
       printf(" %f %f\n", quad[3], quad[4]);
       printf(" %f %f %f\n", quad[6], quad[7], quad[8]); */
       energy[i] = 0.0;
       for (j=0;j<3;j++){
          fld[i][j] = 0.0;
          rff[i][j] = 0.0;
          rft[i][j] = 0.0;
       }
    }

    nosh->nmol = 1;
    Valist_getStatistics(alist[0]);

    /* Only call the setupCalc routine once, so that we can
       reuse this nosh object */
    if (nosh->ncalc < 2) {
       if (NOsh_setupElecCalc(nosh, alist) != 1) {
          printf("Error setting up calculations\n");
          exit(-1);
       }
    }

    /* Solve the LPBE for the homogeneous and then solvated states */
    for (i=0; i<2; i++) {

       /* Useful local variables */
       mgparm = nosh->calc[i]->mgparm;
       pbeparm = nosh->calc[i]->pbeparm;

       /* Just to be robust */
       if (!MGparm_check(mgparm)){
          printf("MGparm Check failed\n");
          printMGPARM(mgparm, realCenter);
          exit(-1);
       }
       if (!PBEparm_check(pbeparm)){
          printf("PBEparm Check failed\n");
          printPBEPARM(pbeparm);
          exit(-1);
       }

       /* Set up the problem */
       mgparm->chgs = VCM_PERMANENT;
       if (!initMG(i, nosh, mgparm, pbeparm, realCenter, pbe,
                   alist, dielXMap, dielYMap, dielZMap,
                   kappaMap, chargeMap, pmgp, pmg, potMap)) {
              Vnm_tprint( 2, "Error setting up MG calculation!\n");
              return;
       }

       /* Solve the PDE */
       if (solveMG(nosh, pmg[i], mgparm->type) != 1) {
           Vnm_tprint(2, "Error solving PDE!\n");
           return;
       }

       /* Set partition information for observables and I/O */
       /* Note - parallel operation has NOT been tested. */
       if (setPartMG(nosh, mgparm, pmg[i]) != 1) {
           Vnm_tprint(2, "Error setting partition info!\n");
           return;
       }

       nx = pmg[i]->pmgp->nx;
       ny = pmg[i]->pmgp->ny;
       nz = pmg[i]->pmgp->nz;
       hx = pmg[i]->pmgp->hx;
       hy = pmg[i]->pmgp->hy;
       hzed = pmg[i]->pmgp->hzed;
       xmin = pmg[i]->pmgp->xmin;
       ymin = pmg[i]->pmgp->ymin;
       zmin = pmg[i]->pmgp->zmin;

       /* Save dielectric/kappa maps into Vgrids, then change the nosh
        * data structure to think it read these maps in from a file.
        * The goal is to save setup time during convergence of the
        * induced dipoles. This is under consideration...
        * */
       /*
       // X (shifted)
       data = Vmem_malloc(mem, nx*ny*nz, sizeof(double));
       Vpmg_fillArray(pmg[i], data, VDT_DIELX, 0.0, pbeparm->pbetype);
       dielXMap[i] = Vgrid_ctor(nx,ny,nz,hx,hy,hzed,
                                xmin + 0.5*hx,ymin,zmin,data);
       dielXMap[i]->readdata = 1;
       // Y (shifted)
       data = Vmem_malloc(mem, nx*ny*nz, sizeof(double));
       Vpmg_fillArray(pmg[i], data, VDT_DIELY, 0.0, pbeparm->pbetype);
       dielYMap[i] = Vgrid_ctor(nx,ny,nz,hx,hy,hzed,
                                      xmin,ymin + 0.5*hy,zmin,data);
       dielYMap[i]->readdata = 1;
       // Z (shifted)
       data = Vmem_malloc(mem, nx*ny*nz, sizeof(double));
       Vpmg_fillArray(pmg[i], data, VDT_DIELZ, 0.0, pbeparm->pbetype);
       dielZMap[i] = Vgrid_ctor(nx,ny,nz,hx,hy,hzed,
                                      xmin,ymin,zmin + 0.5*hzed,data);
       dielZMap[i]->readdata = 1;
       // Kappa
       data = Vmem_malloc(mem, nx*ny*nz, sizeof(double));
       Vpmg_fillArray(pmg[i], data, VDT_KAPPA, 0.0, pbeparm->pbetype);
       kappaMap[i] = Vgrid_ctor(nx,ny,nz,hx,hy,hzed,xmin,ymin,zmin,data);
       kappaMap[i]->readdata = 1;

       // Update the pbeparam structure, since we now have
       // dielectric and kappap maps
       pbeparm->useDielMap = 1;
       pbeparm->dielMapID = i + 1;
       pbeparm->useKappaMap = 1;
       pbeparm->kappaMapID = i + 1;

       */

       data = Vmem_malloc(mem, nx*ny*nz, sizeof(double));
       Vpmg_fillArray(pmg[i], data, VDT_POT, 0.0, pbeparm->pbetype, pbeparm);
       permU[i] = Vgrid_ctor(nx,ny,nz,hx,hy,hzed,xmin,ymin,zmin,data);
       permU[i]->readdata = 1;
       // set readdata flag to have the dtor to free data

       if (i == 0){
          sign = -1.0;
       } else {
          sign = 1.0;
       }

       /* Calculate observables */
       for (j=0; j < alist[0]->number; j++){
         energy[j] += sign * Vpmg_qfPermanentMultipoleEnergy(pmg[i], j);
         Vpmg_fieldSpline4(pmg[i], j, field);
         fld[j][0] += sign * field[0];
         fld[j][1] += sign * field[1];
         fld[j][2] += sign * field[2];
       }

       if (!pmg[i]->pmgp->nonlin &&
          (pmg[i]->surfMeth == VSM_SPLINE ||
           pmg[i]->surfMeth == VSM_SPLINE3 ||
           pmg[i]->surfMeth == VSM_SPLINE4)) {
          for (j=0; j < alist[0]->number; j++){
            Vpmg_qfPermanentMultipoleForce(pmg[i], j, force, torque);
            rff[j][0] += sign * force[0];
            rff[j][1] += sign * force[1];
            rff[j][2] += sign * force[2];
            rft[j][0] += sign * torque[0];
            rft[j][1] += sign * torque[1];
            rft[j][2] += sign * torque[2];
          }
          kT = Vunit_kb * (1e-3) * Vunit_Na * 298.15 * 1.0/4.184;
          epsp = Vpbe_getSoluteDiel(pmg[i]->pbe);
          epsw = Vpbe_getSolventDiel(pmg[i]->pbe);
          if (VABS(epsp-epsw) > VPMGSMALL) {
             for (j=0; j < alist[0]->number; j++){
                Vpmg_dbPermanentMultipoleForce(pmg[i], j, force);
                rff[j][0] += sign * force[0];
                rff[j][1] += sign * force[1];
                rff[j][2] += sign * force[2];
             }
          }
          zkappa2 = Vpbe_getZkappa2(pmg[i]->pbe);
          if (zkappa2 > VPMGSMALL) {
             for (j=0; j < alist[0]->number; j++) {
                Vpmg_ibPermanentMultipoleForce(pmg[i], j, force);
                rff[j][0] += sign * force[0];
                rff[j][1] += sign * force[1];
                rff[j][2] += sign * force[2];
             }
          }
       }
    }

    //nosh->ndiel = 2;
    //nosh->nkappa = 2;
    /*
    printf("Energy (multipole) %f Kcal/mol\n", *energy);
    printf("Energy (volume)    %f Kcal/mol\n", evol * 0.5 * kT);
    */

    // Convert results into kcal/mol units
    kT = Vunit_kb * (1e-3) * Vunit_Na * 298.15 * 1.0/4.184;
    // Electric converts from electron**2/Angstrom to kcal/mol
    electric = 332.063709;
    *total = 0.0;
    for (i=0; i<alist[0]->number; i++){
       /* starting with the field in KT/e/Ang^2 multiply by kcal/mol/KT
          the field is then divided by "electric" to convert to e/Ang^2 */
       energy[i] *= 0.5 * kT;
       *total += energy[i];
       fld[i][0] *= kT / electric;
       fld[i][1] *= kT / electric;
       fld[i][2] *= kT / electric;
       rff[i][0] *= kT;
       rff[i][1] *= kT;
       rff[i][2] *= kT;
       rft[i][0] *= kT;
       rft[i][1] *= kT;
       rft[i][2] *= kT;
    }

    killMG(nosh, pbe, pmgp, pmg);
}