Ejemplo n.º 1
0
/// Calculate the dot product
/// @param v :: The other vector.
double GSLVector::dot(const GSLVector &v) const {
  if (size() != v.size()) {
    throw std::runtime_error("Vectors have different sizes in dot product.");
  }
  double res = 0.0;
  gsl_blas_ddot(gsl(), v.gsl(), &res);
  return res;
}
Ejemplo n.º 2
0
/// Set the matrix to be diagonal.
/// @param d :: Values on the diagonal.
void GSLMatrix::diag(const GSLVector &d) {
  const auto n = d.size();
  resize(n, n);
  zero();
  for (size_t i = 0; i < n; ++i) {
    set(i, i, d.get(i));
  }
}
Ejemplo n.º 3
0
/**
 * Copy the parameter values to a GSLVector.
 * @param params :: A vector to copy the parameters to
 */
void CostFuncLeastSquares::getParameters(GSLVector &params) const {
  if (params.size() != nParams()) {
    params.resize(nParams());
  }
  for (size_t i = 0; i < nParams(); ++i) {
    params.set(i, getParameter(i));
  }
}
Ejemplo n.º 4
0
/**
 * Copy the parameter values from a GSLVector.
 * @param params :: A vector to copy the parameters from
 */
void CostFuncLeastSquares::setParameters(const GSLVector &params) {
  if (nParams() != params.size()) {
    throw std::runtime_error(
        "Parameter vector has wrong size in CostFuncLeastSquares.");
  }
  for (size_t i = 0; i < nParams(); ++i) {
    setParameter(i, params.get(i));
  }
  m_function->applyTies();
}
Ejemplo n.º 5
0
/// Calculate the eigensystem of a symmetric matrix
/// @param eigenValues :: Output variable that receives the eigenvalues of this
/// matrix.
/// @param eigenVectors :: Output variable that receives the eigenvectors of
/// this matrix.
void GSLMatrix::eigenSystem(GSLVector &eigenValues, GSLMatrix &eigenVectors) {
  size_t n = size1();
  if (n != size2()) {
    throw std::runtime_error("Matrix eigenSystem: the matrix must be square.");
  }
  eigenValues.resize(n);
  eigenVectors.resize(n, n);
  auto workspace = gsl_eigen_symmv_alloc(n);
  gsl_eigen_symmv(gsl(), eigenValues.gsl(), eigenVectors.gsl(), workspace);
  gsl_eigen_symmv_free(workspace);
}
Ejemplo n.º 6
0
/**
 * Improve the solution by using obtained functions as a basis for diagonalization.
 *
 * @param hamiltonian :: The Hamiltonian.
 * @param basis :: The basis functions.
 * @param n :: The size of the basis to use.
 * @param eigv :: Output eigenvalues.
 * @param eigf :: Output eigenvectors (functions). This method creates a new ChebfunVector instance and returns it.
 */
void Schrodinger1D::improve(ChebOperator *hamiltonian, ChebfunVector *basis, GSLVector &eigv, ChebfunVector **eigf) const
{
    size_t n = basis->size();

    GSLMatrix H(n,n);

    for(size_t i = 0; i < n; ++i)
    {
        const chebfun &f1 = basis->cfun(i).cfun(0).getUnscaled();
        chebfun d1(f1);
        hamiltonian->apply(f1, d1);
        chebfun dd = d1;
        dd *= f1;
        double me = dd.integr();
        H.set( i, i, me );
        //std::cerr << "e=" << me << std::endl;
        for(size_t j = i+1; j < n; ++j)
        {
            const chebfun &f2 = basis->cfun(j).cfun(0).getUnscaled();
            chebfun d2(f2);
            hamiltonian->apply(f2, d2);
            d2 *= f1;
            double me = d2.integr();
            //std::cerr << "o=" << me << std::endl;
            H.set( i, j, me );
            H.set( j, i, me );
        }
    }
    //std::cerr << H << std::endl;
    GSLVector en;
    GSLMatrix v;
    H.diag(en,v);
    std::vector<size_t> indx;
    getSortedIndex( en, indx );

    if ( indx.empty() )
    {
        throw std::runtime_error("Schrodinger1D failed to find solution.");
    }

    eigv.resize( indx.size() );
    *eigf = new ChebfunVector;
    ChebfunVector &funs = **eigf;
    funs.fromLinearCombinations( *basis, v );
    funs.sort( indx );
    for(size_t i = 0; i < indx.size(); ++i)
    {
        std::cerr << i << ' ' << en[indx[i]] << std::endl;
        eigv.set( i, en[indx[i]] );
    }
}
Ejemplo n.º 7
0
/// Matrix by vector multiplication
/// @param v :: A vector to multiply by. Must have the same size as size2().
/// @returns A vector - the result of the multiplication. Size of the returned
/// vector equals size1().
/// @throws std::invalid_argument if the input vector has a wrong size.
/// @throws std::runtime_error if the underlying GSL routine fails.
GSLVector GSLMatrix::operator*(const GSLVector &v) const {
  if (v.size() != size2()) {
    throw std::invalid_argument(
        "Matrix by vector multiplication: wrong size of vector.");
  }
  GSLVector res(size1());
  auto status =
      gsl_blas_dgemv(CblasNoTrans, 1.0, gsl(), v.gsl(), 0.0, res.gsl());
  if (status != GSL_SUCCESS) {
    std::string message = "Failed to multiply matrix by a vector.\n"
                          "Error message returned by the GSL:\n" +
                          std::string(gsl_strerror(status));
    throw std::runtime_error(message);
  }
  return res;
}
Ejemplo n.º 8
0
/// Solve system of linear equations M*x == rhs, M is this matrix
/// This matrix is destroyed.
/// @param rhs :: The right-hand-side vector
/// @param x :: The solution vector
void GSLMatrix::solve(const GSLVector &rhs, GSLVector &x) {
  if (size1() != size2()) {
    throw std::runtime_error(
        "System of linear equations: the matrix must be square.");
  }
  size_t n = size1();
  if (rhs.size() != n) {
    throw std::runtime_error(
        "System of linear equations: right-hand side vector has wrong size.");
  }
  x.resize(n);
  int s;
  gsl_permutation *p = gsl_permutation_alloc(n);
  gsl_linalg_LU_decomp(gsl(), p, &s); // matrix is modified at this moment
  gsl_linalg_LU_solve(gsl(), p, rhs.gsl(), x.gsl());
  gsl_permutation_free(p);
}
Ejemplo n.º 9
0
    /**
     * Recalculate the B-spline knots
     */
    void BSpline::resetKnots()
    {
        bool isUniform = getAttribute("Uniform").asBool();

        std::vector<double> breakPoints;
        if ( isUniform )
        {
            // create uniform knots in the interval [StartX, EndX]
            double startX = getAttribute("StartX").asDouble();
            double endX = getAttribute("EndX").asDouble();
            gsl_bspline_knots_uniform( startX, endX, m_bsplineWorkspace.get() );
            getGSLBreakPoints( breakPoints );
            storeAttributeValue( "BreakPoints", Attribute(breakPoints) );
        }
        else
        {
            // set the break points from BreakPoints vector attribute, update other attributes
            breakPoints = getAttribute( "BreakPoints" ).asVector();
            // check that points are in ascending order
            double prev = breakPoints[0];
            for(size_t i = 1; i < breakPoints.size(); ++i)
            {
                double next = breakPoints[i];
                if ( next <= prev )
                {
                    throw std::invalid_argument("BreakPoints must be in ascending order.");
                }
                prev = next;
            }
            int nbreaks = getAttribute( "NBreak" ).asInt();
            // if number of break points change do necessary updates
            if ( static_cast<size_t>(nbreaks) != breakPoints.size() )
            {
                storeAttributeValue("NBreak", Attribute(static_cast<int>(breakPoints.size())) );
                resetGSLObjects();
                resetParameters();
            }
            GSLVector bp = breakPoints;
            gsl_bspline_knots( bp.gsl(), m_bsplineWorkspace.get() );
            storeAttributeValue( "StartX", Attribute(breakPoints.front()) );
            storeAttributeValue( "EndX", Attribute(breakPoints.back()) );
        }
    }
Ejemplo n.º 10
0
/// Solve system of linear equations M*x == rhs, M is this matrix
/// This matrix is destroyed.
/// @param rhs :: The right-hand-side vector
/// @param x :: The solution vector
/// @throws std::invalid_argument if the input vectors have wrong sizes.
/// @throws std::runtime_error if the GSL fails to solve the equations.
void GSLMatrix::solve(const GSLVector &rhs, GSLVector &x) {
  if (size1() != size2()) {
    throw std::invalid_argument(
        "System of linear equations: the matrix must be square.");
  }
  size_t n = size1();
  if (rhs.size() != n) {
    throw std::invalid_argument(
        "System of linear equations: right-hand side vector has wrong size.");
  }
  x.resize(n);
  int s;
  gsl_permutation *p = gsl_permutation_alloc(n);
  gsl_linalg_LU_decomp(gsl(), p, &s); // matrix is modified at this moment
  int res = gsl_linalg_LU_solve(gsl(), p, rhs.gsl(), x.gsl());
  gsl_permutation_free(p);
  if (res != GSL_SUCCESS) {
    std::string message = "Failed to solve system of linear equations.\n"
                          "Error message returned by the GSL:\n" +
                          std::string(gsl_strerror(res));
    throw std::runtime_error(message);
  }
}
Ejemplo n.º 11
0
/**
 * Sort a vector in ascending order of positive values. It means that a negative value is
 * always "greater" than any positive value. It's for moving negatives to the back.
 *
 * The vector isn't actually changed by this method. Instead a vector of indices is created
 * which records the sort order.
 *
 * @param v :: A vector to sort.
 * @param indx :: The output sorted indices. v[ indx[i] ] gives i-th element in the sorted vector.
 */
void Schrodinger1D::getSortedIndex(const GSLVector &v, std::vector<size_t> &indx) const
{
    indx.resize(v.size());
    {
      size_t i = 0;
      std::generate(indx.begin(), indx.end(), [&i]()->size_t{++i;return i-1;});
    }

    std::sort(indx.begin(), indx.end(), [&v](size_t x1,size_t x2)->bool{
      const double& d1 = v[x1];
      const double& d2 = v[x2];
      if ( d1 < 0 && d2 >= 0 ) return false;
      if ( d2 < 0 && d1 >= 0 ) return true;
      if ( d1 < 0 && d2 < 0 ) return d2 < d1;
      return d1 < d2;
    });

}
Ejemplo n.º 12
0
/// Execute algorithm.
void Schrodinger1D::exec()
{
  double startX = get("StartX");
  double endX = get("EndX");

  if (endX <= startX)
  {
    throw std::invalid_argument("StartX must be <= EndX");
  }

  IFunction_sptr VPot = getClass("VPot");
  chebfun vpot( 0, startX, endX );
  vpot.bestFit( *VPot );

  size_t nBasis = vpot.n() + 1;
  std::cerr << "n=" << nBasis << std::endl;
  //if (n < 3)
  {
    nBasis = 200;
    vpot.resize( nBasis );
  }

  const double beta = get("Beta");

  auto kinet = new ChebCompositeOperator;
  kinet->addRight( new ChebTimes(-beta) );
  kinet->addRight( new ChebDiff2 );
  auto hamiltonian = new ChebPlus;
  hamiltonian->add('+', kinet );
  hamiltonian->add('+', new ChebTimes(VPot) );

  GSLMatrix L;
  hamiltonian->createMatrix( vpot.getBase(), L );

  GSLVector d;
  GSLMatrix v;
  L.diag( d, v );

  std::vector<double> norms = vpot.baseNorm();
  assert(norms.size() == L.size1());
  assert(norms.size() == L.size2());

  for(size_t i = 0; i < norms.size(); ++i)
  {
      double factor = 1.0 / norms[i];
      for(size_t j = i; j < norms.size(); ++j)
      {
          v.multiplyBy(i,j,factor);
      }
  }

//  eigenvectors orthogonality check
//  GSLMatrix v1 = v;
//  GSLMatrix tst;
//  tst = Tr(v1) * v;
//  std::cerr << tst << std::endl;

  std::vector<size_t> indx(L.size1());
  getSortedIndex( d, indx );

  auto eigenvalues = API::TableWorkspace_ptr(dynamic_cast<API::TableWorkspace*>(
    API::WorkspaceFactory::instance().create("TableWorkspace"))
    );
  eigenvalues->setRowCount(nBasis);
  setProperty("Eigenvalues", eigenvalues);

  eigenvalues->addColumn("double","N");
  auto nColumn = static_cast<API::TableColumn<double>*>(eigenvalues->getColumn("N").get());
  nColumn->asNumeric()->setPlotRole(API::NumericColumn::X);
  auto& nc = nColumn->data();

  eigenvalues->addDoubleColumn("Energy");
  auto eColumn = static_cast<API::TableColumn<double>*>(eigenvalues->getColumn("Energy").get());
  eColumn->asNumeric()->setPlotRole(API::NumericColumn::Y);
  auto& ec = eigenvalues->getDoubleData("Energy");

  boost::scoped_ptr<ChebfunVector> eigenvectors(new ChebfunVector);

  chebfun fun0(nBasis,startX,endX);
  ChebFunction_sptr theSum(new ChebFunction(fun0));

  // collect indices of spurious eigenvalues to move them to the back
  std::vector<size_t> spurious;
  // index for good eigenvalues
  size_t n = 0;
  for(size_t j = 0; j < nBasis; ++j)
  {
    size_t i = indx[j];
    chebfun fun(fun0);
    fun.setP(v,i);

    // check eigenvalues for spurious ones
    chebfun dfun(fun);
    dfun.square();
    double norm = dfun.integr();

    // I am not sure that it's a solid condition
    if ( norm < 0.999999 )
    {
        // bad eigenvalue
        spurious.push_back(j);
    }
    else
    {
        nc[n] = double(n);
        ec[n] = d[i];
        eigenvectors->add(ChebFunction_sptr(new ChebFunction(fun)));

        // test sum of functions squares
        *theSum += dfun;

//        chebfun dfun(fun);
//        hamiltonian->apply(fun,dfun);
//        dfun *= fun;
//        std::cerr << "ener["<<n<<"]=" << ec[n] << ' ' << norm << ' ' << dfun.integr() << std::endl;
        ++n;
    }
  }

  GSLVector eigv;
  ChebfunVector *eigf = NULL;
  improve(hamiltonian, eigenvectors.get(), eigv, &eigf);

  eigenvalues->setRowCount( eigv.size() );
  for(size_t i = 0; i < eigv.size(); ++i)
  {
      nc[i] = double(i);
      ec[i] = eigv[i];
  }

  eigf->add(theSum);
  setProperty("Eigenvectors",ChebfunVector_sptr(eigf));

  //makeQuadrature(eigf);

}
Ejemplo n.º 13
0
 GSLVector::GSLVector(const GSLVector& v)
 {
   m_vector = gsl_vector_alloc(v.size());
   gsl_vector_memcpy(m_vector, v.gsl());
 }