void EinsplineSetBuilder::ReadBands_ESHDF(int spin, EinsplineSetExtended<double>* orbitalSet)
{
  update_token(__FILE__,__LINE__,"ReadBands_ESHDF:double");
  ReportEngine PRE("EinsplineSetBuilder","ReadBands_ESHDF(EinsplineSetExtended<double>*");
  vector<AtomicOrbital<double> > realOrbs(AtomicOrbitals.size());
  for (int iat=0; iat<realOrbs.size(); iat++)
  {
    AtomicOrbital<complex<double> > &corb (AtomicOrbitals[iat]);
    realOrbs[iat].set_pos  (corb.Pos);
    realOrbs[iat].set_lmax (corb.lMax);
    realOrbs[iat].set_cutoff (corb.CutoffRadius);
    realOrbs[iat].set_spline (corb.SplineRadius, corb.SplinePoints);
    realOrbs[iat].set_polynomial (corb.PolyRadius, corb.PolyOrder);
    realOrbs[iat].Lattice = corb.Lattice;
  }
  bool root = myComm->rank()==0;
  // bcast other stuff
  myComm->bcast (NumDistinctOrbitals);
  myComm->bcast (NumValenceOrbs);
  myComm->bcast (NumCoreOrbs);
  int N = NumDistinctOrbitals;
  orbitalSet->kPoints.resize(N);
  orbitalSet->MakeTwoCopies.resize(N);
  orbitalSet->StorageValueVector.resize(N);
  orbitalSet->BlendValueVector.resize(N);
  orbitalSet->StorageLaplVector.resize(N);
  orbitalSet->BlendLaplVector.resize(N);
  orbitalSet->StorageGradVector.resize(N);
  orbitalSet->BlendGradVector.resize(N);
  orbitalSet->StorageHessVector.resize(N);
  orbitalSet->StorageGradHessVector.resize(N);
  orbitalSet->phase.resize(N);
  orbitalSet->eikr.resize(N);
  orbitalSet->NumValenceOrbs = NumValenceOrbs;
  orbitalSet->NumCoreOrbs    = NumCoreOrbs;
  orbitalSet->FirstOrderSplines.resize(IonPos.size());
  // Read in k-points
  int numOrbs = orbitalSet->getOrbitalSetSize();
  int num = 0;
  vector<BandInfo>& SortBands(*FullBands[spin]);
  if (root)
  {
    for (int iorb=0; iorb<N; iorb++)
    {
      int ti = SortBands[iorb].TwistIndex;
      PosType twist  = TwistAngles[ti];
      orbitalSet->kPoints[iorb] = orbitalSet->PrimLattice.k_cart(twist);
      orbitalSet->MakeTwoCopies[iorb] =
        (num < (numOrbs-1)) && SortBands[iorb].MakeTwoCopies;
      num += orbitalSet->MakeTwoCopies[iorb] ? 2 : 1;
    }
    PosType twist0 = TwistAngles[SortBands[0].TwistIndex];
    for (int i=0; i<OHMMS_DIM; i++)
      if (std::fabs(std::fabs(twist0[i]) - 0.5) < 1.0e-8)
        orbitalSet->HalfG[i] = 1;
      else
        orbitalSet->HalfG[i] = 0;
    EinsplineSetBuilder::RotateBands_ESHDF(spin, orbitalSet);
  }
  myComm->bcast(orbitalSet->kPoints);
  myComm->bcast(orbitalSet->MakeTwoCopies);
  myComm->bcast(orbitalSet->HalfG);
  // First, check to see if we have already read this in
  H5OrbSet set(H5FileName, spin, N);
  bool havePsir=!ReadGvectors_ESHDF();
  app_log() << "MeshSize = (" << MeshSize[0] << ", "
            << MeshSize[1] << ", " << MeshSize[2] << ")\n";
  //int nx, ny, nz, bi, ti;
  int nx, ny, nz;
  nx=MeshSize[0];
  ny=MeshSize[1];
  nz=MeshSize[2];
  Ugrid x_grid, y_grid, z_grid;
  BCtype_d xBC, yBC, zBC;
  if (orbitalSet->HalfG[0])
  {
    xBC.lCode = ANTIPERIODIC;
    xBC.rCode = ANTIPERIODIC;
  }
  else
  {
    xBC.lCode = PERIODIC;
    xBC.rCode = PERIODIC;
  }
  if (orbitalSet->HalfG[1])
  {
    yBC.lCode = ANTIPERIODIC;
    yBC.rCode = ANTIPERIODIC;
  }
  else
  {
    yBC.lCode = PERIODIC;
    yBC.rCode = PERIODIC;
  }
  if (orbitalSet->HalfG[2])
  {
    zBC.lCode = ANTIPERIODIC;
    zBC.rCode = ANTIPERIODIC;
  }
  else
  {
    zBC.lCode = PERIODIC;
    zBC.rCode = PERIODIC;
  }
  x_grid.start = 0.0;
  x_grid.end = 1.0;
  x_grid.num = nx;
  y_grid.start = 0.0;
  y_grid.end = 1.0;
  y_grid.num = ny;
  z_grid.start = 0.0;
  z_grid.end = 1.0;
  z_grid.num = nz;
  // Create the multiUBspline object
  orbitalSet->MultiSpline =
    create_multi_UBspline_3d_d (x_grid, y_grid, z_grid, xBC, yBC, zBC, NumValenceOrbs);
  if (HaveOrbDerivs)
  {
    orbitalSet->FirstOrderSplines.resize(IonPos.size());
    for (int ion=0; ion<IonPos.size(); ion++)
      for (int dir=0; dir<OHMMS_DIM; dir++)
        orbitalSet->FirstOrderSplines[ion][dir] =
          create_multi_UBspline_3d_d (x_grid, y_grid, z_grid, xBC, yBC, zBC, NumValenceOrbs);
  }
  //////////////////////////////////////
  // Create the MuffinTin APW splines //
  //////////////////////////////////////
  orbitalSet->MuffinTins.resize(NumMuffinTins);
  for (int tin=0; tin<NumMuffinTins; tin++)
  {
    orbitalSet->MuffinTins[tin].Atom = tin;
    orbitalSet->MuffinTins[tin].set_center (MT_centers[tin]);
    orbitalSet->MuffinTins[tin].set_lattice(Lattice);
    orbitalSet->MuffinTins[tin].init_APW
    (MT_APW_rgrids[tin], MT_APW_lmax[tin],
     NumValenceOrbs);
  }
  for (int iat=0; iat<realOrbs.size(); iat++)
  {
    realOrbs[iat].set_num_bands(NumValenceOrbs);
    realOrbs[iat].allocate();
  }
  int isComplex;
  if (root)
  {
    HDFAttribIO<int> h_isComplex(isComplex);
    h_isComplex.read(H5FileID, "/electrons/psi_r_is_complex");
  }
  myComm->bcast(isComplex);
  bool isCore = bcastSortBands(spin,N,root);
  if(isCore)
  {
    APP_ABORT("Core states not supported by ES-HDF yet.");
  }
  //this is common
  Array<double,3> splineData(nx,ny,nz);
  if(havePsir)
  {
    if(isComplex)
    {
      app_log() << "   Reading complex psi_r and convert to real" << endl;
      Array<complex<double>,3> rawData;
      for(int iorb=0,ival=0; iorb<N; ++iorb, ++ival)
      {
        int ti=SortBands[iorb].TwistIndex;
        if(root)
        {
          ostringstream path;
          path << "/electrons/kpoint_" << SortBands[iorb].TwistIndex
               << "/spin_" << spin << "/state_" << SortBands[iorb].BandIndex << "/psi_r";
          HDFAttribIO<Array<complex<double>,3> >  h_splineData(rawData);
          h_splineData.read(H5FileID, path.str().c_str());
        }
        myComm->bcast(rawData);
        //multiply twist factor and project on the real
        fix_phase_c2r(rawData,splineData,TwistAngles[ti]);
        set_multi_UBspline_3d_d (orbitalSet->MultiSpline, ival, splineData.data());
      }
    }
    else
    {
      app_log() << "   Reading real psi_r" << endl;
      for(int iorb=0,ival=0; iorb<N; ++iorb, ++ival)
      {
        if(root)
        {
          ostringstream path;
          path << "/electrons/kpoint_" << SortBands[iorb].TwistIndex
               << "/spin_" << spin << "/state_" << SortBands[iorb].BandIndex << "/psi_r";
          HDFAttribIO<Array<double,3> >  h_splineData(splineData);
          h_splineData.read(H5FileID, path.str().c_str());
        }
        myComm->bcast(splineData);
        set_multi_UBspline_3d_d (orbitalSet->MultiSpline, ival, splineData.data());
      }
    }
  }
  else
  {
    Array<ComplexType,3> FFTbox;
    FFTbox.resize(MeshSize[0], MeshSize[1], MeshSize[2]);
    fftw_plan FFTplan = fftw_plan_dft_3d
                        (MeshSize[0], MeshSize[1], MeshSize[2],
                         reinterpret_cast<fftw_complex*>(FFTbox.data()),
                         reinterpret_cast<fftw_complex*>(FFTbox.data()),
                         +1, FFTW_ESTIMATE);
    for(int iorb=0,ival=0; iorb<N; ++iorb, ++ival)
    {
      Vector<complex<double> > cG;
      int ncg=0;
      int ti=SortBands[iorb].TwistIndex;
      if(root)
      {
        ostringstream path;
        path << "/electrons/kpoint_" << SortBands[iorb].TwistIndex
             << "/spin_" << spin << "/state_" << SortBands[iorb].BandIndex << "/psi_g";
        HDFAttribIO<Vector<complex<double> > >  h_cG(cG);
        h_cG.read (H5FileID, path.str().c_str());
        ncg=cG.size();
      }
      myComm->bcast(ncg);
      if(ncg != Gvecs[0].size())
      {
        APP_ABORT("Failed : ncg != Gvecs[0].size()");
      }
      if(!root)
        cG.resize(ncg);
      myComm->bcast(cG);
      unpack4fftw(cG,Gvecs[0],MeshSize,FFTbox);
      fftw_execute (FFTplan);
      fix_phase_rotate_c2r(FFTbox,splineData,TwistAngles[ti]);
      set_multi_UBspline_3d_d (orbitalSet->MultiSpline, ival, splineData.data());
    }
    fftw_destroy_plan(FFTplan);
  }
  for(int iorb=0,ival=0; iorb<N; ++iorb, ++ival)
  {
    // Read atomic orbital information
    for (int iat=0; iat<realOrbs.size(); iat++)
    {
      app_log() << "Reading orbital " << iat << " for band " << ival << endl;
      AtomicOrbital<double> &orb = realOrbs[iat];
      //AtomicOrbital<complex<double> > &orb = realOrbs[iat];
      Array<complex<double>,2> radial_spline(orb.SplinePoints,orb.Numlm),
            poly_coefs(orb.PolyOrder+1,orb.Numlm);
      int ti   = SortBands[iorb].TwistIndex;
      if (root)
      {
        int bi   = SortBands[iorb].BandIndex;
        ostringstream path;
        path << "/electrons/kpoint_" << ti << "/spin_" << spin << "/state_" << bi << "/";
        ostringstream spline_path, poly_path;
        spline_path << path.str() << "radial_spline_" << iat;
        poly_path   << path.str() << "poly_coefs_"    << iat;
        HDFAttribIO<Array<complex<double>,2> > h_radial_spline(radial_spline);
        HDFAttribIO<Array<complex<double>,2> > h_poly_coefs(poly_coefs);
        h_radial_spline.read(H5FileID, spline_path.str().c_str());
        h_poly_coefs.read   (H5FileID, poly_path.str().c_str());
      }
      myComm->bcast(radial_spline);
      myComm->bcast(poly_coefs);
      realOrbs[iat].set_band (ival, radial_spline, poly_coefs, TwistAngles[ti]);
    }
  }
  for(int iorb=0,ival=0; iorb<N; ++iorb, ++ival)
  {
    // Now read muffin tin data
    for (int tin=0; tin<NumMuffinTins; tin++)
    {
      // app_log() << "Reading data for muffin tin " << tin << endl;
      PosType twist, k;
      int lmax = MT_APW_lmax[tin];
      int numYlm = (lmax+1)*(lmax+1);
      Array<complex<double>,2>
      u_lm_r(numYlm, MT_APW_num_radial_points[tin]);
      Array<complex<double>,1> du_lm_dr (numYlm);
      int ti   = SortBands[iorb].TwistIndex;
      if (root)
      {
        int bi   = SortBands[iorb].BandIndex;
        twist = TwistAngles[ti];
        k = orbitalSet->PrimLattice.k_cart(twist);
        string uName  = MuffinTinPath (ti, bi,tin) + "u_lm_r";
        string duName = MuffinTinPath (ti, bi,tin) + "du_lm_dr";
        HDFAttribIO<Array<complex<double>,2> > h_u_lm_r(u_lm_r);
        HDFAttribIO<Array<complex<double>,1> > h_du_lm_dr(du_lm_dr);
        h_u_lm_r.read(H5FileID, uName.c_str());
        h_du_lm_dr.read(H5FileID, duName.c_str());
      }
      myComm->bcast(u_lm_r);
      myComm->bcast(du_lm_dr);
      myComm->bcast(k);
      double Z = (double)IonTypes(tin);
      OrbitalSet->MuffinTins[tin].set_APW (ival, k, u_lm_r, du_lm_dr, Z);
    }
  }
  //FIX HaveOrbDerivs after debugging
//	// Now read orbital derivatives if we have them
//	if (HaveOrbDerivs) {
//	  for (int ion=0; ion<IonPos.size(); ion++)
//	    for (int dim=0; dim<OHMMS_DIM; dim++) {
//	      if (root) {
//		int ti   = SortBands[iorb].TwistIndex;
//		int bi   = SortBands[iorb].BandIndex;
//
//		app_log() << "Reading orbital derivative for ion " << ion
//			  << " dim " << dim << " spin " << spin << " band "
//			  << bi << " kpoint " << ti << endl;
//		ostringstream path;
//		path << "/electrons/kpoint_" << ti << "/spin_" << spin << "/state_" << bi << "/"
//		     << "dpsi_" << ion << "_" << dim << "_r";
//		string psirName = path.str();
//		if (isComplex) {
//		  HDFAttribIO<Array<complex<double>,3> > h_rawData(rawData);
//		  h_rawData.read(H5FileID, psirName.c_str());
//		  if ((rawData.size(0) != nx) ||
//		      (rawData.size(1) != ny) ||
//		      (rawData.size(2) != nz)) {
//		    fprintf (stderr, "Error in EinsplineSetBuilder::ReadBands.\n");
//		    fprintf (stderr, "Extended orbitals should all have the same dimensions\n");
//		    abort();
//		  }
//#pragma omp parallel for
//		  for (int ix=0; ix<nx; ix++) {
//		  PosType ru;
//		    ru[0] = (RealType)ix / (RealType)nx;
//		    for (int iy=0; iy<ny; iy++) {
//		      ru[1] = (RealType)iy / (RealType)ny;
//		      for (int iz=0; iz<nz; iz++) {
//			ru[2] = (RealType)iz / (RealType)nz;
//			double phi = -2.0*M_PI*dot (ru, TwistAngles[ti]);
//			double s, c;
//			sincos(phi, &s, &c);
//			complex<double> phase(c,s);
//			complex<double> z = phase*rawData(ix,iy,iz);
//			splineData(ix,iy,iz) = z.real();
//		      }
//		    }
//		  }
//		}
//		else {
//		  HDFAttribIO<Array<double,3> >  h_splineData(splineData);
//		  h_splineData.read(H5FileID, psirName.c_str());
//		  if ((splineData.size(0) != nx) ||
//		      (splineData.size(1) != ny) ||
//		      (splineData.size(2) != nz)) {
//		    fprintf (stderr, "Error in EinsplineSetBuilder::ReadBands.\n");
//		    fprintf (stderr, "Extended orbitals should all have the same dimensions\n");
//		    abort();
//		  }
//		}
//	      }
//	      myComm->bcast(splineData);
//	      set_multi_UBspline_3d_d
//		(orbitalSet->FirstOrderSplines[ion][dim], ival, splineData.data());
//	    }
//	}
//
//
//
  orbitalSet->AtomicOrbitals = realOrbs;
  for (int i=0; i<orbitalSet->AtomicOrbitals.size(); i++)
    orbitalSet->AtomicOrbitals[i].registerTimers();
  //ExtendedMap_d[set] = orbitalSet->MultiSpline;
}