/*!
Print information about private variables {plots,resolution,minmax}
*/
int Nodes_method::showinfo(ostream & os)
{
   sysprop->showinfo(os);
    os << endl << endl;
    os << "                               Wavefunction  "
       << endl << endl;
    wfdata->showinfo(os);
  os<<"#############Nodes_method#################\n";
  if (doublemove)
    os <<"Doing doublemoves with"<<endl;
  os<<"Plots= "<<plots(0);
  for(int i=1;i<plots.GetSize();i++)
    os<<", "<<plots(i);
  os<<endl;

  if (doublemove){
    os << "Translation vector(s): "<<endl;
    for(int i=0;i<dxyz.GetDim(0);i++)    
      os<<"( "<<dxyz(i,0)<<" , "<<dxyz(i,1)<<" , "<<dxyz(i,2)<<" )"<<endl;
    }
  

  os<<"resolution "<<resolution<<endl;
  os<<"xmin="<<minmax(0)<<" xmax="<<minmax(1)<<endl;
  os<<"ymin="<<minmax(2)<<" ymax="<<minmax(3)<<endl;
  os<<"zmin="<<minmax(4)<<" zmax="<<minmax(5)<<endl;
  os<<"done"<<endl;
  return 1;
}
STKUNIT_UNIT_TEST(function, stringFunction_derivative_2)
{
  EXCEPTWATCH;
  for (unsigned ipts = 0; ipts < NPTS; ipts++)
  {
    double x = testpoints_fd[ipts][0];
    double y = testpoints_fd[ipts][1];
    double z = testpoints_fd[ipts][2];
    double t = testpoints_fd[ipts][3];

    double eps=1.e-10;
    double eps_loc = eps*(std::fabs(x) + std::fabs(y) + std::fabs(z) + std::fabs(t))/4.0;

    // start_demo_stringFunction_derivative_2
    StringFunction sf(" sin(x*y*z*z) " );
    std::string grad[] = {"y*z*z*cos(x*y*z*z)",  "x*z*z*cos(x*y*z*z)", "2*x*y*z*cos(x*y*z*z)"};
    std::string gradv = "v[0]="+grad[0]+"; v[1]="+grad[1]+" ; v[2]="+grad[2]+";";
    StringFunction dsf_grad(gradv.c_str(), Name("test"), Dimensions(3), Dimensions(3) );
    MDArrayString dxyz(3,1);
    dxyz(0,0)="x"; dxyz(1,0)="y"; dxyz(2,0)="z";
    sf.set_gradient_strings(grad, 3);
    Teuchos::RCP<Function> dsf_grad_fd = sf.derivative_test_fd(dxyz, eps_loc);
    Teuchos::RCP<Function> dsf_grad_2  = sf.derivative(dxyz);

    MDArray dv_fd = eval_vec3(x, y, z, t, *dsf_grad_fd);
    MDArray dv2   = eval_vec3(x, y, z, t, *dsf_grad_2);
    MDArray dv    = eval_vec3(x, y, z, t, dsf_grad);

    // the two different functions should give the same result
    for (int ii = 0; ii < 3; ii++)
    {
      //std::cout << "\n ii= " << ii << "\n"<< std::endl;
      STKUNIT_EXPECT_DOUBLE_EQ(dv(ii), dv2(ii));
      if (std::fabs(dv(ii)-dv_fd(ii)) > 0.5*(std::fabs(dv_fd(ii))+std::fabs(dv(ii)))*1.e-6)
      {
        std::cout << "\nii = " << ii << " x= "<<x<<" y= "<<y<<" z= " << z << " expected= " << dv(ii) << " actual= " << dv_fd(ii) << std::endl;
      }

      STKUNIT_EXPECT_DOUBLE_EQ_APPROX_TOL(dv(ii), dv_fd(ii), 1.e-4);
    }


    // end_demo
  }
}
STKUNIT_UNIT_TEST(function, stringFunction_derivative_1)
{
  EXCEPTWATCH;
  for (unsigned ipts = 0; ipts < NPTS; ipts++)
  {
    double x = testpoints[ipts][0];
    double y = testpoints[ipts][1];
    double z = testpoints[ipts][2];
    double t = testpoints[ipts][3];

    double eps=1.e-6;
    double eps_loc = eps*(std::fabs(x) + std::fabs(y) + std::fabs(z) + std::fabs(t))/4.0;

    // start_demo_stringFunction_derivative_1
    StringFunction sfxy(" x - y ");
    StringFunction dsfxy_grad("v[0]=1; v[1]= -1; v[2]=0", Name("test"), Dimensions(3), Dimensions(3) );
    MDArrayString dxyz(3,1);
    dxyz(0,0)="x"; dxyz(1,0)="y"; dxyz(2,0)="z";
    std::string grad[] = {"1","-1","0"};
    sfxy.set_gradient_strings(grad, 3);
    Teuchos::RCP<Function> dsfxy_grad_1  = sfxy.derivative_test(dxyz);
    Teuchos::RCP<Function> dsfxy_grad_fd = sfxy.derivative_test_fd(dxyz, eps_loc);
    Teuchos::RCP<Function> dsfxy_grad_2  = sfxy.derivative(dxyz);

    MDArray dvxy1   = eval_vec3(x, y, z, t, *dsfxy_grad_1);
    MDArray dvxy_fd = eval_vec3(x, y, z, t, *dsfxy_grad_fd);
    MDArray dvxy2   = eval_vec3(x, y, z, t, *dsfxy_grad_2);
    MDArray dvxy    = eval_vec3(x, y, z, t, dsfxy_grad);

    // the two different functions should give the same result
    for (int ii = 0; ii < 3; ii++)
    {
      STKUNIT_EXPECT_DOUBLE_EQ(dvxy(ii), dvxy1(ii));
      STKUNIT_EXPECT_DOUBLE_EQ(dvxy(ii), dvxy2(ii));
      STKUNIT_EXPECT_DOUBLE_EQ_APPROX(dvxy(ii), dvxy_fd(ii));
    }

    // and they should give the same result as C++
    STKUNIT_EXPECT_DOUBLE_EQ(dvxy(0), 1.0);
    STKUNIT_EXPECT_DOUBLE_EQ(dvxy(1), -1.0);

    // end_demo
  }
}
void akGeometryDeformer::DLBAntipodalitySkinningNoNormals(
    const btAlignedObjectArray<akMatrix4>* mpalette,
    const btAlignedObjectArray<akDualQuat>* dqpalette,
    const UTsize vtxCount,
    const float*     weights, const UTsize weightsStride,
    const UTuint8*   indices, const UTsize indicesStride,
    const akVector3* vtxSrc,  const UTsize vtxSrcStride,
    akVector3*       vtxDst,  const UTsize vtxDstStride)
{
    const btAlignedObjectArray<akMatrix4>& matrices = *mpalette;
    const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette;

    for(unsigned int i=0; i<vtxCount; i++)
    {

        // position 1st pass for non rigid part of the transformation using matrices
        akVector4 pos(vtxSrc[0].getX(), vtxSrc[0].getY(), vtxSrc[0].getZ(), 1);
        akVector4 posout(0,0,0,1);
        if (weights[0]) posout += matrices[indices[0]] * weights[0] * pos;
        if (weights[1]) posout += matrices[indices[1]] * weights[1] * pos;
        if (weights[2]) posout += matrices[indices[2]] * weights[2] * pos;
        if (weights[3]) posout += matrices[indices[3]] * weights[3] * pos;

        akDualQuat dq0 = dquats[indices[0]];
        akDualQuat dq1 = dquats[indices[1]];
        akDualQuat dq2 = dquats[indices[2]];
        akDualQuat dq3 = dquats[indices[3]];

        if( dot(dq0.n, dq1.n) < 0.0) dq1 *= -1.0;
        if( dot(dq0.n, dq2.n) < 0.0) dq2 *= -1.0;
        if( dot(dq0.n, dq3.n) < 0.0) dq3 *= -1.0;

        akDualQuat dq = dq0 * weights[0];
        if (weights[1]) dq += dq1 * weights[1];
        if (weights[2]) dq += dq2 * weights[2];
        if (weights[3]) dq += dq3 * weights[3];

        dq /= length(dq.n);

        akVector3 ndxyz(dq.n.getXYZ());
        akVector3 dxyz(dq.d.getXYZ());

        //position
        akVector3 in(posout.getXYZ());
        *vtxDst = in + 2.0 * cross( ndxyz, cross(ndxyz, in) + dq.n.getW() * in ) +
                  2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) );

        akAdvancePointer(weights, weightsStride);
        akAdvancePointer(indices, indicesStride);
        akAdvancePointer(vtxSrc, vtxSrcStride);
        akAdvancePointer(vtxDst, vtxDstStride);
    }
}
void akGeometryDeformer::DLBSkinning(
    const btAlignedObjectArray<akMatrix4>* mpalette,
    const btAlignedObjectArray<akDualQuat>* dqpalette,
    const UTsize vtxCount,
    const float*     weights, const UTsize weightsStride,
    const UTuint8*   indices, const UTsize indicesStride,
    const akVector3* vtxSrc,  const UTsize vtxSrcStride,
    akVector3*       vtxDst,  const UTsize vtxDstStride,
    const akVector3* normSrc, const UTsize normSrcStride,
    akVector3*       normDst, const UTsize normDstStride)
{
    const btAlignedObjectArray<akMatrix4>& matrices = *mpalette;
    const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette;

    for(unsigned int i=0; i<vtxCount; i++)
    {
        // position 1st pass for non rigid part of the transformation using matrices
        akMatrix4 mat(matrices[indices[0]] * weights[0]);
        if (weights[1]) mat += matrices[indices[1]] * weights[1];
        if (weights[2]) mat += matrices[indices[2]] * weights[2];
        if (weights[3]) mat += matrices[indices[3]] * weights[3];

        akVector3 tmpPos = (mat * akVector4(*vtxSrc, 1.f)).getXYZ();

        // position 2nd pass for rigid transformation (rotaion & location) using dual quats
        akDualQuat dq = dquats[indices[0]] * weights[0];
        if (weights[1]) dq += dquats[indices[1]] * weights[1];
        if (weights[2]) dq += dquats[indices[2]] * weights[2];
        if (weights[3]) dq += dquats[indices[3]] * weights[3];

        dq /= length(dq.n);

        akVector3 ndxyz(dq.n.getXYZ());
        akVector3 dxyz(dq.d.getXYZ());
        *vtxDst = tmpPos + 2.0 * cross( ndxyz, cross(ndxyz, tmpPos) + dq.n.getW() * tmpPos ) +
                  2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) );

        // normal 1st pass
        inverseTranspose(mat);
        akVector3 tmpNorm = (mat * akVector4(*normSrc, 0.0f)).getXYZ();

        // normal 2nd pass
        *normDst = tmpNorm + 2.0 * cross( ndxyz, cross(ndxyz, tmpNorm) + dq.n.getW() * tmpNorm );
        *normDst = normalize(*normDst);

        akAdvancePointer(normSrc, normSrcStride);
        akAdvancePointer(normDst, normDstStride);
        akAdvancePointer(weights, weightsStride);
        akAdvancePointer(indices, indicesStride);
        akAdvancePointer(vtxSrc, vtxSrcStride);
        akAdvancePointer(vtxDst, vtxDstStride);
    }
}
void akGeometryDeformer::DLBAntipodalitySkinningNoScaling(
    const btAlignedObjectArray<akMatrix4>* mpalette,
    const btAlignedObjectArray<akDualQuat>* dqpalette,
    const UTsize vtxCount,
    const float*     weights, const UTsize weightsStride,
    const UTuint8*   indices, const UTsize indicesStride,
    const akVector3* vtxSrc,  const UTsize vtxSrcStride,
    akVector3*       vtxDst,  const UTsize vtxDstStride,
    const akVector3* normSrc, const UTsize normSrcStride,
    akVector3*       normDst, const UTsize normDstStride)
{
    const btAlignedObjectArray<akMatrix4>& matrices = *mpalette;
    const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette;

    for(unsigned int i=0; i<vtxCount; i++)
    {
        akDualQuat dq0 = dquats[indices[0]];
        akDualQuat dq1 = dquats[indices[1]];
        akDualQuat dq2 = dquats[indices[2]];
        akDualQuat dq3 = dquats[indices[3]];

        if( dot(dq0.n, dq1.n) < 0.0) dq1 *= -1.0;
        if( dot(dq0.n, dq2.n) < 0.0) dq2 *= -1.0;
        if( dot(dq0.n, dq3.n) < 0.0) dq3 *= -1.0;

        akDualQuat dq = dq0 * weights[0];
        if (weights[1]) dq += dq1 * weights[1];
        if (weights[2]) dq += dq2 * weights[2];
        if (weights[3]) dq += dq3 * weights[3];

        dq /= length(dq.n);

        akVector3 ndxyz(dq.n.getXYZ());
        akVector3 dxyz(dq.d.getXYZ());

        //position
        akVector3 in(*vtxSrc);
        *vtxDst = in + 2.0 * cross( ndxyz, cross(ndxyz, in) + dq.n.getW() * in ) +
                  2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) );

        // normal
        akVector3 inn(*normSrc);
        *normDst = inn + 2.0 * cross( ndxyz, cross(ndxyz, inn) + dq.n.getW() * inn );

        akAdvancePointer(normSrc, normSrcStride);
        akAdvancePointer(normDst, normDstStride);
        akAdvancePointer(weights, weightsStride);
        akAdvancePointer(indices, indicesStride);
        akAdvancePointer(vtxSrc, vtxSrcStride);
        akAdvancePointer(vtxDst, vtxDstStride);
    }
}
void akGeometryDeformer::DLBSkinningNoNormals(
    const btAlignedObjectArray<akMatrix4>* mpalette,
    const btAlignedObjectArray<akDualQuat>* dqpalette,
    const UTsize vtxCount,
    const float*     weights, const UTsize weightsStride,
    const UTuint8*   indices, const UTsize indicesStride,
    const akVector3* vtxSrc,  const UTsize vtxSrcStride,
    akVector3*       vtxDst,  const UTsize vtxDstStride)
{
    const btAlignedObjectArray<akMatrix4>& matrices = *mpalette;
    const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette;

    for(unsigned int i=0; i<vtxCount; i++)
    {
        // position 1st pass for non rigid part of the transformation using matrices
        akVector4 pos(vtxSrc[0].getX(), vtxSrc[0].getY(), vtxSrc[0].getZ(), 1);
        akVector4 posout(0,0,0,1);
        if (weights[0]) posout += matrices[indices[0]] * weights[0] * pos;
        if (weights[1]) posout += matrices[indices[1]] * weights[1] * pos;
        if (weights[2]) posout += matrices[indices[2]] * weights[2] * pos;
        if (weights[3]) posout += matrices[indices[3]] * weights[3] * pos;

        // position 2nd pass for rigid transformation (rotaion & location) using dual quats
        akDualQuat dq = dquats[indices[0]] * weights[0];
        if (weights[1]) dq += dquats[indices[1]] * weights[1];
        if (weights[2]) dq += dquats[indices[2]] * weights[2];
        if (weights[3]) dq += dquats[indices[3]] * weights[3];

        dq /= length(dq.n);

        akVector3 tmpPos2(posout.getXYZ());
        akVector3 ndxyz(dq.n.getXYZ());
        akVector3 dxyz(dq.d.getXYZ());
        *vtxDst = tmpPos2 + 2.0 * cross( ndxyz, cross(ndxyz, tmpPos2) + dq.n.getW() * tmpPos2 ) +
                  2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) );

        akAdvancePointer(weights, weightsStride);
        akAdvancePointer(indices, indicesStride);
        akAdvancePointer(vtxSrc, vtxSrcStride);
        akAdvancePointer(vtxDst, vtxDstStride);
    }
}
Beispiel #8
0
void PointGroup<scalar_type>::solve(Timers& timers, bool compute_rmm, bool lda, bool compute_forces, bool compute_energy,
                                    double& energy, double* fort_forces_ptr)
{
  HostMatrix<scalar_type> rmm_output;
  uint group_m = total_functions();
  if (compute_rmm) { rmm_output.resize(group_m, group_m); rmm_output.zero(); }

  #if CPU_RECOMPUTE
  /** Compute functions **/
  timers.functions.start();
  compute_functions(compute_forces, !lda);
  timers.functions.pause();
  #endif

  // prepare rmm_input for this group
  timers.density.start();
  HostMatrix<scalar_type> rmm_input(group_m, group_m);
  get_rmm_input(rmm_input);
  timers.density.pause();

  HostMatrix<vec_type3> forces(total_nucleii(), 1); forces.zero();
  HostMatrix<vec_type3> dd;

  /******** each point *******/
  uint point = 0;
  for (list<Point>::const_iterator point_it = points.begin(); point_it != points.end(); ++point_it, ++point)
  {
    timers.density.start();

    /** density **/
    scalar_type partial_density = 0;
    vec_type3 dxyz(0,0,0);
    vec_type3 dd1(0,0,0);
    vec_type3 dd2(0,0,0);

    if (lda) {
      for (uint i = 0; i < group_m; i++) {
        float w = 0.0;
        float Fi = function_values(i, point);
        for (uint j = i; j < group_m; j++) {
          scalar_type Fj = function_values(j, point);
          w += rmm_input(j, i) * Fj;
        }
        partial_density += Fi * w;
      }
    }
    else {
      for (uint i = 0; i < group_m; i++) {
        float w = 0.0;
        vec_type3 w3(0,0,0);
        vec_type3 ww1(0,0,0);
        vec_type3 ww2(0,0,0);

        scalar_type Fi = function_values(i, point);
        vec_type3 Fgi(gradient_values(i, point));
        vec_type3 Fhi1(hessian_values(2 * (i + 0) + 0, point));
        vec_type3 Fhi2(hessian_values(2 * (i + 0) + 1, point));

        for (uint j = 0; j <= i; j++) {
          scalar_type rmm = rmm_input(j,i);
          scalar_type Fj = function_values(j, point);
          w += Fj * rmm;

          vec_type3 Fgj(gradient_values(j, point));
          w3 += Fgj * rmm;

          vec_type3 Fhj1(hessian_values(2 * (j + 0) + 0, point));
          vec_type3 Fhj2(hessian_values(2 * (j + 0) + 1, point));
          ww1 += Fhj1 * rmm;
          ww2 += Fhj2 * rmm;
        }
        partial_density += Fi * w;

        dxyz += Fgi * w + w3 * Fi;
        dd1 += Fgi * w3 * 2 + Fhi1 * w + ww1 * Fi;

        vec_type3 FgXXY(Fgi.x(), Fgi.x(), Fgi.y());
        vec_type3 w3YZZ(w3.y(), w3.z(), w3.z());
        vec_type3 FgiYZZ(Fgi.y(), Fgi.z(), Fgi.z());
        vec_type3 w3XXY(w3.x(), w3.x(), w3.y());

        dd2 += FgXXY * w3YZZ + FgiYZZ * w3XXY + Fhi2 * w + ww2 * Fi;
      }
    }
    timers.density.pause();

    timers.forces.start();
    /** density derivatives **/
    if (compute_forces) {
      dd.resize(total_nucleii(), 1); dd.zero();
      for (uint i = 0, ii = 0; i < total_functions_simple(); i++) {
        uint nuc = func2local_nuc(ii);
        uint inc_i = small_function_type(i);
        vec_type3 this_dd = vec_type3(0,0,0);
        for (uint k = 0; k < inc_i; k++, ii++) {
          scalar_type w = 0.0;
          for (uint j = 0; j < group_m; j++) {
            scalar_type Fj = function_values(j, point);
            w += rmm_input(j, ii) * Fj * (ii == j ? 2 : 1);
          }
          this_dd -= gradient_values(ii, point) * w;
        }
        dd(nuc) += this_dd;
      }
    }
    timers.forces.pause();

    timers.pot.start();

    timers.density.start();
    /** energy / potential **/
    scalar_type exc = 0, corr = 0, y2a = 0;
    if (lda)
      cpu_pot(partial_density, exc, corr, y2a);
    else {
      cpu_potg(partial_density, dxyz, dd1, dd2, exc, corr, y2a);
    }

    timers.pot.pause();

    if (compute_energy)
      energy += (partial_density * point_it->weight) * (exc + corr);
    timers.density.pause();


    /** forces **/
    timers.forces.start();
    if (compute_forces) {
      scalar_type factor = point_it->weight * y2a;
      for (uint i = 0; i < total_nucleii(); i++)
        forces(i) += dd(i) * factor;
    }
    timers.forces.pause();

    /** RMM **/
    timers.rmm.start();
    if (compute_rmm) {
      scalar_type factor = point_it->weight * y2a;
      HostMatrix<scalar_type>::blas_ssyr(LowerTriangle, factor, function_values, rmm_output, point);
    }
    timers.rmm.pause();
  }

  timers.forces.start();
  /* accumulate force results for this group */
  if (compute_forces) {
    FortranMatrix<double> fort_forces(fort_forces_ptr, fortran_vars.atoms, 3, fortran_vars.max_atoms); // TODO: mover esto a init.cpp
    for (uint i = 0; i < total_nucleii(); i++) {
      uint global_atom = local2global_nuc[i];
      vec_type3 this_force = forces(i);
      fort_forces(global_atom,0) += this_force.x();
      fort_forces(global_atom,1) += this_force.y();
      fort_forces(global_atom,2) += this_force.z();
    }
  }
  timers.forces.pause();

  timers.rmm.start();
  /* accumulate RMM results for this group */
  if (compute_rmm) {
    for (uint i = 0, ii = 0; i < total_functions_simple(); i++) {
      uint inc_i = small_function_type(i);
      for (uint k = 0; k < inc_i; k++, ii++) {
        uint big_i = local2global_func[i] + k;

        for (uint j = 0, jj = 0; j < total_functions_simple(); j++) {
          uint inc_j = small_function_type(j);
          for (uint l = 0; l < inc_j; l++, jj++) {
            uint big_j = local2global_func[j] + l;
            if (big_i > big_j) continue;

            uint big_index = (big_i * fortran_vars.m - (big_i * (big_i - 1)) / 2) + (big_j - big_i);
            fortran_vars.rmm_output(big_index) += rmm_output(ii, jj);
          }
        }
      }
    }
  }
  timers.rmm.pause();

  #if CPU_RECOMPUTE
  /* clear functions */
  function_values.deallocate();
  gradient_values.deallocate();
  hessian_values.deallocate();
  #endif
}
/*!
Read the "words" from the method section in the input file
via doinput() parsing, and store section information in private
variables isoses, resolution, and minmax.
Set up MO_matrix and Sample_point objects for wavefunction from input
*/
void Nodes_method::read(vector <string> words,
                       unsigned int & pos,
                       Program_options & options)
{
  pos=0;	//always start from first word
  doublevar Tres;
  vector <string> Torbs;
  vector <string> Tminmax;
  vector <string> orbtext;
  vector <string> Tdxyz;


  allocate(options.systemtext[0], sysprop);
  sysprop->generateSample(mywalker);

  allocate(options.twftext[0], sysprop, wfdata);
  wfdata->generateWavefunction(wf);

  mywalker->attachObserver(wf);
 
  pos=0;
  if(readsection(words,pos=0,Torbs,"CONTOURS")){
    //   error("Need CONTOURS in METHOD section");
  plots.Resize(Torbs.size());
  for(unsigned int i=0; i<Torbs.size(); i++){
        plots(i)=atoi(Torbs[i].c_str());
      }
  }
  else {
    cout <<"WARNING: All electrons are used for scanning!"<<endl;
    plots.Resize(mywalker->electronSize());
    for(int i=0; i<plots.GetSize(); i++){
      plots(i)=i+1;
      } 
  }
 
  pos=0;
  if(! readvalue(words,pos,Tres,"RESOLUTION"))
    error("Need RESOLUTION in METHOD section");
  resolution=Tres;


  pos=0;
  minmax.Resize(6);
  if(readsection(words,pos,Tminmax,"MINMAX")) { 
    if(Tminmax.size() != 6)
      error("MINMAX needs 6 values");
    for(unsigned int i=0; i<Tminmax.size(); i++)
    {
      minmax(i)=atof(Tminmax[i].c_str());
    }
  }
  else  { 
    minmax=0.0;
  
    int nions=sysprop->nIons();
    Array1 <doublevar> ionpos(3);
    for(int i=0; i< nions; i++) {
      sysprop->getIonPos(i,ionpos);
      for(int d=0; d< 3; d++) {
        if(ionpos(d) < minmax(2*d)) minmax(2*d) = ionpos(d);
        if(ionpos(d) > minmax(2*d+1)) minmax(2*d+1)=ionpos(d);
      }
    }

    for(int d=0; d< 3; d++) {
      minmax(2*d)-=4.0;
      minmax(2*d+1)+=4.0;
      cout << "minmax " << minmax(2*d) << " " << minmax(2*d+1) << endl;
    }
  } 
  
  
 

  // Makes the Nodes methods use the current implementation of Nodes
  if(readvalue(words, pos=0, readconfig, "READCONFIG")){
    Array1 <Config_save_point> config_pos;
    config_pos.Resize(0);
    if(readconfig!="") { 
      read_configurations(readconfig, config_pos);
    }
    if(config_pos.GetDim(0)<1)
      error("Could not read a single walker from config file");
    //take a first one
    config_pos(0).restorePos(mywalker);
  }
  else {
    mywalker->randomGuess();
    debug_write(cout, 0, " configs read ", 1,
                " configs randomly generated \n");
  }
  
  pos=0;
  doublemove=false;
  if( readsection(words,pos,Tdxyz,"DOUBLEMOVES")){
    doublemove=true;
    if(plots.GetSize()%2)
      error("Needs pairs of countours for doublemoves");
    unsigned int dummy=3*plots.GetSize()/2;
    if(Tdxyz.size()!=dummy)
      error("DOUBLEMOVES needs 3 x # of vectors values");
    dxyz.Resize(plots.GetSize()/2,3);
    for(int i=0; i<plots.GetSize()/2; i++){
      for (int j=0; j<3;j++)
        dxyz(i,j)=atof(Tdxyz[i*3+j].c_str());
    }
  }
}
void Nodes_method::run(Program_options & options, ostream & output)
{
  ofstream os; //for writing to *.plt files
  string pltfile; //name of plotfile being written
  string confile; //name of configuration of electrons to be  being written
  double max_value,min_value;
  int count;
  Array1 <doublevar> xyz(3), xyz2(3),
    resolution_array(3); //position of electron "in" MO
  Array1 <int> D_array1(3); //dummy array1
  Array2 <doublevar> oldpos(mywalker->electronSize(),3);
  Array1 <doublevar> tmp(3);
  D_array1=0; //sets all 3 components to 0. use as counter for gridpoints
  
  
  D_array1(0)=roundoff((minmax(1)-minmax(0))/resolution);
  D_array1(1)=roundoff((minmax(3)-minmax(2))/resolution);
  D_array1(2)=roundoff((minmax(5)-minmax(4))/resolution);

  resolution_array(0)=(minmax(1)-minmax(0))/(D_array1(0)-1);  
  resolution_array(1)=(minmax(3)-minmax(2))/(D_array1(1)-1);
  resolution_array(2)=(minmax(5)-minmax(4))/(D_array1(2)-1);

  Array2 <doublevar> grid(plots.GetSize(),D_array1(0)*D_array1(1)*D_array1(2));
  Wf_return wfvals(wf->nfunc(), 2); //where wfval fist index labels 
    //wf number ie. ground state
    // excited state and so on, and second label is for two values, sign and log(wf).

 //scan electron positions
  cout << "Using these electron positions:"<<endl;
  for(int i=0; i<mywalker->electronSize(); i++){
    mywalker->getElectronPos(i, tmp);
    cout.precision(5);
    cout.width(8);
    cout <<i+1<<" "<<tmp(0)<<" "<<tmp(1)<<" "<<tmp(2)<<endl;
    for (int d=0;d<3;d++)
      oldpos(i,d)=tmp(d);
    //    cout << "pos " << oldpos(i,0) << "   " << oldpos(i,1) << "   " << oldpos(i,2)
    //     << endl;
  }

  //generate .xyz file for gOpenMol to view coordinates
  pltfile=options.runid + ".xyz";
  os.open(pltfile.c_str());
  cout<<"writing to "<<pltfile<<endl;
  vector <string> atomlabels;
  sysprop->getAtomicLabels(atomlabels);
  os<<atomlabels.size()+mywalker->electronSize()<<endl;
  os<<endl;
  
  int spin_up=sysprop->nelectrons(0);
  //cout << "Up electrons "<<spin_up<<endl;

  
  for(unsigned int i=0; i<atomlabels.size(); i++){
    Array1 <doublevar> pos(3);
    mywalker->getIonPos(i, pos);
    os<<atomlabels[i] <<" "<< pos(0)
    <<" "<<pos(1)
    <<" "<< pos(2)<<endl;
  }
  for(int j=0; j<mywalker->electronSize(); j++){
    if (j<spin_up) os<<"Eu";
    else os<<"Ed";
        // mywalker->getElectronPos(j, pos);
       os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1) <<" "<< oldpos(j,2)<<endl;
  }
  os.close();
  

  if (!doublemove) {
    //calculate value of each molecular orbital at each grid point and store in an Array1
    // grid values with x=fastest running variable, and z=slowest

    cout<<"calculating "<<D_array1(0)*D_array1(1)*D_array1(2)
        <<" grid points"<<endl;
    cout<<"for "<< plots.GetDim(0) <<" 3D projections of wavefunction"<<endl;
    count=0;
    xyz(0)=minmax(0);
    xyz(1)=minmax(2);
    xyz(2)=minmax(4); //init elec probe to xmin ymin zmin
    //Array1 <doublevar> oldpos(3)

  
  
    for(int i=0; i<plots.GetSize(); i++){
      cout.width(3);
      cout <<"============================="<<plots(i)
           <<"=============================="
           <<endl;
      count=0;
      for(int xx=0; xx<D_array1(0);xx++){
	xyz(0)=minmax(0)+xx*resolution_array(0);  //move forward on x axis one resolution unit
	max_value=min_value=0.0;
	cout << "x ";
        cout.precision(5);
        cout.width(8);
        cout<< xyz(0);
	for(int yy=0; yy<D_array1(1);yy++){
          xyz(1)=minmax(2)+yy*resolution_array(1);  //move forward on y axis one resolution unit
	  for(int zz=0;zz<D_array1(2);zz++){
	    xyz(2)=minmax(4)+zz*resolution_array(2); //move forward on z axis one resolution unit
	    // mywalker->getElectronPos(plots(i), oldpos);
            mywalker->setElectronPos(plots(i)-1,xyz); //move elec#plots(i) to point specified by xyz
            wf->updateVal(wfdata, mywalker); //update wfdata
            wf->getVal(wfdata, 0, wfvals); //get wf value
            const doublevar cutoff=15;
            if(wfvals.amp(0,0)<cutoff) { 
              grid(i,count)=wfvals.sign(0)*exp(wfvals.amp(0,0));
            }
            else { //cut off the maximum value output so that there aren't overflow errors
              grid(i,count)=wfvals.sign(0)*exp(cutoff);
            }
            //grid(i,count)=exp(2.0*wfvals(0,1));//!square of wavefunction
            if (grid(i,count)>max_value) max_value=grid(i,count);
            if (grid(i,count)<min_value) min_value=grid(i,count);
            //  cout << "grid " << grid(i,count)<< " " << xyz(0) << endl;
	    count++; //index for cycling through grid points
          }
        }
        cout.setf(ios::scientific| ios:: showpos);
        cout <<", max. value "<<max_value<<", min. value "<<min_value<< endl;
        cout.unsetf(ios::scientific| ios:: showpos);
        
      }
      mywalker->setElectronPos(plots(i)-1, oldpos(plots(i)-1));
    }
  
  
    //Loop through and generate plot files for each orbital requested
    if(plots.GetSize()<=0)
      error("Number of requested plots is not a positive number");
    cout<<"saving data for "<<plots.GetSize()<<" 3D projections of wavefunction"<<endl;
    for(int i=0; i<plots.GetSize(); i++)
      {
        //output to file with orbital number in it
        char strbuff[40];
        sprintf(strbuff, "%d", plots(i));
        confile=pltfile = options.runid;
        confile += ".orb.";
        pltfile += ".orb.";
        pltfile += strbuff;
        confile += strbuff;
        pltfile += ".cube"; /*FIGURE OUT HOW TO CONVERT INT TO STRING*/
        confile += ".xyz";
        
        os.open(pltfile.c_str());
        cout<<"writing to "<<pltfile<<endl;

        os << "QWalk nodes output\n";
        os << "Wavefunction single scan with " <<   plots(i) <<" electron"<<endl;
        int natoms=sysprop->nIons();
        os << "  " << natoms+ mywalker->electronSize()-1 << "   " << minmax(0) << "   "
          << minmax(2) << "   " << minmax(4) << endl;
        os << D_array1(0) << "   " << resolution_array(0) << "  0.0000   0.0000" << endl;
        os << D_array1(1) << "   0.0000   " << resolution_array(1) << "  0.0000" << endl;
        os << D_array1(2) << "   0.0000    0.0000    " << resolution_array(2) << endl;
        Array1 <doublevar> pos(3);
        for(int at=0; at< natoms; at++) {
          mywalker->getIonPos(at,pos);
          os << "   " << mywalker->getIonCharge(at) << "   0.0000    " << pos(0) 
            <<"    " << pos(1) << "   " << pos(2) << endl;
        }
        for(int j=0; j<mywalker->electronSize(); j++){
          if (j!=plots(i)-1){
            if (j<spin_up) os<<"     3   0.0000    ";
            else os<<"     3     0.0000    ";
            os<< oldpos(j,0)<<"   "<<oldpos(j,1)<<"   "<< oldpos(j,2)<<endl;
          }
        }
        os.setf(ios::scientific);
        for(int j=0; j< D_array1(0)*D_array1(1)*D_array1(2); j++) {
          os <<setw(16)<<setprecision(8)<<grid(i,j);
          if(j%6 ==5) os << endl;
        }
        os << endl;
        os.unsetf(ios::scientific);
        os<<setprecision(6);
        os.close();

	
        /*
	  old plt file plots
        // http://www.csc.fi/gopenmol/developers/plt_format.phtml
        os<<"3 "; //rank=3 always
        os<<"2\n"; //dummy variable => "Orbital/density surface"
        //number of grid points for x, y, & z direction
        os <<D_array1(2)<<" "<<D_array1(1)<<" "<<D_array1(0)<<endl;
        os <<minmax(4)<<" "<<minmax(5)<<" "<<minmax(2)<<" "<<minmax(3)
           <<" "<<minmax(0)<<" "<<minmax(1)<<endl;
        
        for(int j=0; j<(D_array1(0)*D_array1(1)*D_array1(2)); j++)
          os<<grid(i,j)<<endl;
        os.close();
        
        os.open(confile.c_str());
        cout<<"writing to "<<confile<<endl;
        Array1 <doublevar> pos(3);
        sysprop->getAtomicLabels(atomlabels);
        os<<atomlabels.size()+ mywalker->electronSize()-1 <<endl;
        os << endl;
        for(unsigned int j=0; j<atomlabels.size();j++){
          mywalker->getIonPos(j, pos);
          os<<atomlabels[j] <<" "<< pos(0)
            <<" "<<pos(1)
            <<" "<< pos(2)<<endl;
        }
        for(int j=0; j<mywalker->electronSize(); j++){
          if (j!=plots(i)-1){
            if (j<spin_up) os<<"Eu";
            else os<<"Ed";
            // mywalker->getElectronPos(j, pos);
            os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1)
              <<" "<< oldpos(j,2)<<endl;
          }
        }
        os.close();   
	*/
	
      }
    
  }
  else {
    cout << "Using translation vector(s): "<<endl;
    for(int i=0;i<dxyz.GetDim(0);i++)    
      cout<<"( "<<dxyz(i,0)<<" , "<<dxyz(i,1)<<" , "<<dxyz(i,2)<<" )"<<endl;

    for(int i=0; i<plots.GetSize(); i=i+2){
      count=0;
      xyz(0)=minmax(0);
      xyz(1)=minmax(2);
      xyz(2)=minmax(4); //init elec probe to xmin ymin zmin
      //Array1 <doublevar> oldpos(3)
      cout.width(3);
      cout <<"============================="<<plots(i)<<" and "<<plots(i+1)
           <<"=============================="
           <<endl;
      for(int xx=0; xx<D_array1(0);xx++){
        max_value=min_value=0.0;
        xyz(0)=minmax(0)+xx*resolution_array(0); 
        xyz2(0)=xyz(0)+dxyz(i/2,0);  
        cout << "x ";
        cout.precision(5);
        cout.width(8);
        cout<< xyz(0);
        for(int yy=0; yy<D_array1(1);yy++){
          xyz(1)=minmax(2)+yy*resolution_array(1); 
          xyz2(1)=xyz(1)+dxyz(i/2,1);
          for(int zz=0;zz<D_array1(2);zz++){
            xyz(2)=minmax(4)+zz*resolution_array(2); 
            xyz2(2)=xyz(2)+dxyz(i/2,2);
            // mywalker->getElectronPos(plots(i), oldpos);
            mywalker->setElectronPos(plots(i)-1,xyz);//move elec#plots(i) 
            //to point specified by xyz
            mywalker->setElectronPos(plots(i+1)-1,xyz2);//move elec#plots(i) 
            //to point specified by xyz
            wf->updateVal(wfdata, mywalker); //update wfdata
            wf->getVal(wfdata, 0, wfvals); //get wf value
            grid(i,count)=wfvals.sign(0)*exp(wfvals.amp(0,0));
            //grid(i,count)=exp(2.0*wfvals(0,1));//!square of wavefunction
            //  cout << "grid " << grid(i,count)<< " " << xyz(0) << endl;
            if (grid(i,count)>max_value) max_value=grid(i,count);
            if (grid(i,count)<min_value) min_value=grid(i,count);
            
            count++; //index for cycling through grid points
          }
        }
        cout.setf(ios::scientific| ios:: showpos);
        cout <<", max. value "<<max_value<<", min. value "<<min_value<< endl;
        cout.unsetf(ios::scientific| ios:: showpos);
      }
      
      mywalker->setElectronPos(plots(i)-1, oldpos(plots(i)-1));
      mywalker->setElectronPos(plots(i+1)-1, oldpos(plots(i+1)-1)); 
    }
    
    //Loop through and generate plot files for each orbital requested
    if(plots.GetSize()<=0)
      error("Number of requested plots is not a positive number");
    cout<<"saving data for "<<plots.GetSize()<<" 3D projections of wavefunction"<<endl;
    for(int i=0; i<plots.GetSize(); i=i+2)
      {
        char strbuff2[40],strbuff[40];
        //output to file with orbital number in it
        sprintf(strbuff, "%d", plots(i));
        sprintf(strbuff2, "%d", plots(i+1));
        confile=pltfile = options.runid;
        confile += ".orb.";
        pltfile += ".orb.";
        pltfile += strbuff;
        confile += strbuff;
        pltfile += "with";
        confile += "with";
        pltfile += strbuff2;
        confile += strbuff2;
        
        pltfile += ".cube"; /*FIGURE OUT HOW TO CONVERT INT TO STRING*/
        confile += ".xyz";
        
        os.open(pltfile.c_str());
        cout<<"writing to "<<pltfile<<endl;
	os << "GOS nodes output\n";
	os << "Wave function double scan with "<<   plots(i) <<" & "<<plots(i+1)<<" electrons"<< endl;
        int natoms=sysprop->nIons();
        os << "  " << natoms + mywalker->electronSize()-2 << "   " << minmax(0) << "   "
           << minmax(2) << "   " << minmax(4) << endl;
        os << D_array1(0) << "   " << resolution_array(0) << "  0.0000   0.0000" << endl;
        os << D_array1(1) << "   0.0000   " << resolution_array(1) << "  0.0000" << endl;
        os << D_array1(2) << "   0.0000    0.0000    " << resolution_array(2) << endl;
        Array1 <doublevar> pos(3);
        for(int at=0; at< natoms; at++) {
          mywalker->getIonPos(at,pos);
          os << "   " << mywalker->getIonCharge(at) << "   0.0000    " << pos(0) 
             <<"    " << pos(1) << "   " << pos(2) << endl;
        }
        for(int j=0; j<mywalker->electronSize(); j++){
          if ((j!=plots(i)-1)&&(j!=plots(i+1)-1)){
            if (j<spin_up) os<<"    3    0.0000    ";
            else os<<"    3    0.0000   ";
            os<< oldpos(j,0)<<"    "<<oldpos(j,1)<<"    "<< oldpos(j,2)<<endl;
          }
        }
	os.setf(ios::scientific);
        for(int j=0; j< D_array1(0)*D_array1(1)*D_array1(2); j++) {
          os << setw(16) << setprecision(8) << grid(i,j);
          if(j%6 ==5) os << endl;
        }
        os << endl;
	os.unsetf(ios::scientific);
	os<<setprecision(6);
        os.close();

        /*
          old plot to plt file version
        // http://www.csc.fi/gopenmol/developers/plt_format.phtml
        os<<"3 "; //rank=3 always
        os<<"2\n"; //dummy variable => "Orbital/density surface"
        //number of grid points for x, y, & z direction
        os <<D_array1(2)<<" "<<D_array1(1)<<" "<<D_array1(0)<<endl;
        os <<minmax(4)<<" "<<minmax(5)<<" "<<minmax(2)<<" "<<minmax(3)
           <<" "<<minmax(0)<<" "<<minmax(1)<<endl;
        
        for(int j=0; j<(D_array1(0)*D_array1(1)*D_array1(2)); j++)
          os<<grid(i,j)<<endl;
        os.close();
        
        os.open(confile.c_str());
        cout<<"writing to "<<confile<<endl;
        Array1 <doublevar> pos(3);
        sysprop->getAtomicLabels(atomlabels);
        os<<atomlabels.size()+ mywalker->electronSize()-2 <<endl;
        os << endl;
        for(unsigned int j=0; j<atomlabels.size();j++){
          mywalker->getIonPos(j, pos);
          os<<atomlabels[j] <<" "<< pos(0)
            <<" "<<pos(1)
            <<" "<< pos(2)<<endl;
        }
        for(int j=0; j<mywalker->electronSize(); j++){
          if ((j!=plots(i)-1)&&(j!=plots(i+1)-1)){
            if (j<spin_up) os<<"Eu";
            else os<<"Ed";
            // mywalker->getElectronPos(j, pos);
            os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1)
              <<" "<< oldpos(j,2)<<endl;
          }
        }
        os.close();    
        */
    
      } 
  }
  cout <<"End of Nodes Method"<<endl;  
}
void akGeometryDeformer::DLBAntipodalitySkinningUniformScale(
    const btAlignedObjectArray<akMatrix4>* mpalette,
    const btAlignedObjectArray<akDualQuat>* dqpalette,
    const UTsize vtxCount,
    const float*     weights, const UTsize weightsStride,
    const UTuint8*   indices, const UTsize indicesStride,
    const akVector3* vtxSrc,  const UTsize vtxSrcStride,
    akVector3*       vtxDst,  const UTsize vtxDstStride,
    const akVector3* normSrc, const UTsize normSrcStride,
    akVector3*       normDst, const UTsize normDstStride)
{
    const btAlignedObjectArray<akMatrix4>& matrices = *mpalette;
    const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette;

    for(unsigned int i=0; i<vtxCount; i++)
    {
        // positions 1st pass for non rigid part of the transformation using matrices
        akMatrix4 mat(matrices[indices[0]] * weights[0]);
        if (weights[1]) mat += matrices[indices[1]] * weights[1];
        if (weights[2]) mat += matrices[indices[2]] * weights[2];
        if (weights[3]) mat += matrices[indices[3]] * weights[3];

        akVector3 tmpPos = (mat * akVector4(*vtxSrc, 1.f)).getXYZ();

        akDualQuat dq0 = dquats[indices[0]];
        akDualQuat dq1 = dquats[indices[1]];
        akDualQuat dq2 = dquats[indices[2]];
        akDualQuat dq3 = dquats[indices[3]];

        if( dot(dq0.n, dq1.n) < 0.0) dq1 *= -1.0;
        if( dot(dq0.n, dq2.n) < 0.0) dq2 *= -1.0;
        if( dot(dq0.n, dq3.n) < 0.0) dq3 *= -1.0;

        akDualQuat dq = dq0 * weights[0];
        if (weights[1]) dq += dq1 * weights[1];
        if (weights[2]) dq += dq2 * weights[2];
        if (weights[3]) dq += dq3 * weights[3];

        dq /= length(dq.n);

        akVector3 ndxyz(dq.n.getXYZ());
        akVector3 dxyz(dq.d.getXYZ());

        //position 2nd pass
        *vtxDst = tmpPos + 2.0 * cross( ndxyz, cross(ndxyz, tmpPos) + dq.n.getW() * tmpPos ) +
                  2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) );

        // normal 1rst pass
        akVector3 tmpNor = (mat * akVector4(*normSrc, 1.f)).getXYZ();


        // normal 2nd pass
        *normDst = tmpNor + 2.0 * cross( ndxyz, cross(ndxyz, tmpNor) + dq.n.getW() * tmpNor );
        *normDst = normalize(*normDst);

        akAdvancePointer(normSrc, normSrcStride);
        akAdvancePointer(normDst, normDstStride);
        akAdvancePointer(weights, weightsStride);
        akAdvancePointer(indices, indicesStride);
        akAdvancePointer(vtxSrc, vtxSrcStride);
        akAdvancePointer(vtxDst, vtxDstStride);
    }
}