示例#1
0
std::vector<std::complex<double> >
PolyBase::calcRoots(const double epsilon)
  /**
    Calculate all the roots of the polynominal.
    Uses the GSL which uses a Hessian reduction of the 
    characteristic compainion matrix.
    \f[ A= \left( -a_{m-1}/a_m -a_{m-2}/a_m ... -a_0/a_m \right) \f]
    where the matrix component below A is the Indenty.
    However, GSL requires that the input coefficient is a_m == 1,
    hence the call to this->compress().
    @param epsilon :: tolerance factor (-ve to use default) 
    @return roots (not sorted/uniqued)
  */
{
  compress(epsilon);
  std::vector<std::complex<double> > Out(iDegree);
  // Zero State:
  if (iDegree==0)
    return Out;
  
  // x+a_0 =0 
  if (iDegree==1)
    {
      Out[0]=std::complex<double>(-afCoeff[0]);
      return Out;
    }
  // x^2+a_1 x+c = 0
  if (iDegree==2)
    {
      solveQuadratic(Out[0],Out[1]);
      return Out;
    }

  // x^3+a_2 x^2+ a_1 x+c=0
  if (iDegree==2)
    {
      solveCubic(Out[0],Out[1],Out[2]);
      return Out;
    }
  // THERE IS A QUARTIC / QUINTIC Solution availiable but...
  // WS contains the the hessian matrix if required (eigenvalues/vectors)
  //
  gsl_poly_complex_workspace* WS
    (gsl_poly_complex_workspace_alloc(iDegree+1));
  double* RZ=new double[2*(iDegree+1)];
  gsl_poly_complex_solve(&afCoeff.front(),iDegree+1, WS, RZ);
  for(int i=0;i<iDegree;i++)
    Out[i]=std::complex<double>(RZ[2*i],RZ[2*i+1]);
  gsl_poly_complex_workspace_free (WS);
  delete [] RZ;
  return Out;
}
void
redlichKwong(	const CriticalParameters& inCP,

				double inT,			//	Temperature (K)
				double inP,			//	Pressure (bar)

				double* outZ,		//	Compressibility Factor
				//double* outState,
				double* outVol,		//	Molar volume (m^3/mol)
				double* outPhi,		//	Fugacity coefficient
				double* outHdep,	//	Enthalpy departure function
				double* outSdep)	//	Entropy departure function
{
	//	Calculate a and b parameters (depend only on critical parameters)…
	
	double a = 0.42748 * kR * kR * std::pow(inCP.mTc, 2.5) / (inCP.mPc * 1.0e5);
	double b = 0.08664 * kR * inCP.mTc / (inCP.mPc * 1.0e5);
	double kappa = 0.0;
	
	//	Calculate coefficients in the cubic equation of state…
	//
	//	coeffs: (C0,C1,C2,A,B);
	
	double A = a * inP * 1.0e5/ (std::sqrt(inT) * std::pow(kR * inT, 2));
	double B = b * inP * 1e5 / (kR * inT);
	double C2 = -1.0;
	double C1 = A - B - B * B;
	double C0 = -A * B;
	
	//	Solve the cubic equation for Z0 - Z2, D…
	
	double Z0;
	double Z1;
	double Z2;
	double D;
	solveCubic(C0, C1, C2, &Z0, &Z1, &Z2, &D);
	
	//	Determine the fugacity coefficient of first root and departure functions…
	//
	//	calcdepfns(coeffs[3],	coeffs[4],	paramsab[0],	Z[0]);
	//	calcdepfns(A,			B,			kappa,			Z)
	
	calcDepartureFunctions(inT, A, B, kappa, Z0, outPhi, outHdep, outSdep);
}
tuple solveCubicWrapper( double a, double b, double c, double d )
{
	double x[3];
	int s = solveCubic( a, b, c, d, x );
	switch( s )
	{
		case 0 :
			return tuple();
		case 1 :
			return make_tuple( x[0] );
		case 2 :
			return make_tuple( x[0], x[1] );
		case 3 :
			return make_tuple( x[0], x[1], x[2] );
		default :
			PyErr_SetString( PyExc_ArithmeticError, "Infinite solutions." );
			throw_error_already_set();
			return tuple(); // should never get here
	}
}
bool CubicSpline::intersects(const CubicSpline &rt, VectorF ignoreAxis) const
{
#if 1
    vector<VectorF> path1 = getSplinePoints(*this);
    vector<VectorF> path2 = getSplinePoints(rt);
    for(size_t i = 1; i < path1.size(); i++)
    {
        for(size_t j = 1; j < path2.size(); j++)
        {
            if(linesIntersect(path1[i - 1], path1[i], path2[j - 1], path2[j], 0))
                return true;
        }
    }
    return false;
#else
    const int splitCount = 50; // number of line segments to split spline into
    ignoreAxis = normalize(ignoreAxis);

    for(int segmentNumber = 0; segmentNumber < splitCount; segmentNumber++)
    {
        float startT = (float)(segmentNumber) / splitCount;
        float endT = (float)(segmentNumber + 1) / splitCount;
        VectorF startP = rt.evaluate(startT);
        startP -= ignoreAxis * dot(ignoreAxis, startP); // move to plane normal to ignoreAxis
        VectorF endP = rt.evaluate(endT);
        endP -= ignoreAxis * dot(ignoreAxis, endP); // move to plane normal to ignoreAxis
        VectorF delta = endP - startP;

        if(absSquared(delta) < eps * eps) // if delta is too small
        {
            continue;
        }

        // solve dot(evaluate(t), cross(ignoreAxis, delta)) == 0 and it intersects if dot(evaluate(t) - startP, delta) / dot(delta, delta) is in [0, 1] and t is in [0, 1]
        VectorF normal = cross(ignoreAxis, delta);
        float cubic = dot(getCubic(), normal);
        float quadratic = dot(getQuadratic(), normal);
        float linear = dot(getLinear(), normal);
        float constant = dot(getConstant(), normal);
        float intersections[3];
        int intersectionCount = solveCubic(constant, linear, quadratic, cubic, intersections);

        for(int i = 0; i < intersectionCount; i++)
        {
            float t = intersections[i];

            if(t < 0 || t > 1)
            {
                continue;
            }

            float v = dot(evaluate(t) - startP, delta) / dot(delta, delta);

            if(v < 0 || v > 1)
            {
                continue;
            }

            return true;
        }
    }

    return false;
#endif
}
int PolynomialSolver::solveQuartic(float c[5], float s[4])
{
  float	coeffs[4],
        z, u, v, sub,
        A, B, C, D,
        sq_A, p, q, r;
  int i, num;

  // normalize the equation:x ^ 4 + Ax ^ 3 + Bx ^ 2 + Cx + D = 0
  A = c[3] / c[4];
  B = c[2] / c[4];
  C = c[1] / c[4];
  D = c[0] / c[4];

  // subsitute x = y - A / 4 to eliminate the cubic term: x^4 + px^2 + qx + r = 0
  sq_A = A * A;
  p = -3.0f / 8.0f * sq_A + B;
  q = 1.0f / 8.0f * sq_A * A - 1.0f / 2.0f * A * B + C;
  r = -3.0f / 256.0f * sq_A * sq_A + 1.0f / 16.0f * sq_A * B - 1.0f / 4.0f * A * C + D;

  if(isZero(r))
  {
    // no absolute term:y(y ^ 3 + py + q) = 0
    coeffs[0] = q;
    coeffs[1] = p;
    coeffs[2] = 0.0;
    coeffs[3] = 1.0;

    num = solveCubic(coeffs, s);
    s[num++] = 0;
  }
  else
  {
    // solve the resolvent cubic...
    coeffs[0] = 1.0f / 2.0f * r * p - 1.0f / 8.0f * q * q;
    coeffs[1] = -r;
    coeffs[2] = -1.0f / 2.0f * p;
    coeffs[3] = 1.0f;
    (void) solveCubic(coeffs, s);

    // ...and take the one real solution...
    z = s[0];

    // ...to build two quadratic equations
    u = z * z - r;
    v = 2.0f * z - p;

    if(isZero(u))
      u = 0.0;
    else if(u > 0.0f)
      u = std::sqrt(u);
    else
      return 0;

    if(isZero(v))
      v = 0;
    else if(v > 0.0f)
      v = std::sqrt(v);
    else
      return 0;

    coeffs[0] = z - u;
    coeffs[1] = q < 0 ? -v : v;
    coeffs[2] = 1.0f;

    num = solveQuadric(coeffs, s);

    coeffs[0] = z + u;
    coeffs[1] = q < 0 ? v : -v;
    coeffs[2] = 1.0f;

    num += solveQuadric(coeffs, s + num);
  }

  // resubstitute
  sub = 1.0f / 4 * A;
  for(i = 0; i < num; i++)
    s[i] -= sub;

return num;
}
示例#6
0
int solveQuartic(float c[5], float s[4])
{
	float  coeffs[4];
	float  z, u, v, sub;
	float  A, B, C, D;
	float  sq_A, p, q, r;
	int     i, num;

	/* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */

	A = c[ 3 ] / c[ 4 ];
	B = c[ 2 ] / c[ 4 ];
	C = c[ 1 ] / c[ 4 ];
	D = c[ 0 ] / c[ 4 ];

	/*  substitute x = y - A/4 to eliminate cubic term:
	x^4 + px^2 + qx + r = 0 */

	sq_A = A * A;
	p = - 3.0/8 * sq_A + B;
	q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
	r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;

	if (IS_ZERO(r)) 
	{
		/* no absolute term: y(y^3 + py + q) = 0 */

		coeffs[ 0 ] = q;
		coeffs[ 1 ] = p;
		coeffs[ 2 ] = 0;
		coeffs[ 3 ] = 1;

		num = solveCubic(coeffs, s);

		s[ num++ ] = 0;
	}
	else {
		/* solve the resolvent cubic ... */

		coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
		coeffs[ 1 ] = - r;
		coeffs[ 2 ] = - 1.0/2 * p;
		coeffs[ 3 ] = 1;

		(void) solveCubic(coeffs, s);

		/* ... and take the one real solution ... */

		z = s[ 0 ];

		/* ... to build two quadric equations */

		u = z * z - r;
		v = 2 * z - p;

		if (IS_ZERO(u))
			u = 0;
		else if (u > 0)
			u = sqrt(u);
		else
			return 0;

		if (IS_ZERO(v))
			v = 0;
		else if (v > 0)
			v = sqrt(v);
		else
			return 0;

		coeffs[ 0 ] = z - u;
		coeffs[ 1 ] = q < 0 ? -v : v;
		coeffs[ 2 ] = 1;

		num = solveQuadric(coeffs, s);

		coeffs[ 0 ]= z + u;
		coeffs[ 1 ] = q < 0 ? v : -v;
		coeffs[ 2 ] = 1;

		num += solveQuadric(coeffs, s + num);
	}

	/* resubstitute */

	sub = 1.0/4 * A;

	for (i = 0; i < num; ++i)
		s[ i ] -= sub;

	return num;
}