void OblatePerfectEllipsoid::evalScalar(const coord::PosProlSph& pos,
    double* val, coord::GradProlSph* deriv, coord::HessProlSph* deriv2) const
{
    assert(&(pos.coordsys)==&coordSys);  // make sure we're not bullshited
    double absnu = fabs(pos.nu);
    double signu = pos.nu>=0 ? 1 : -1;
    double lmn = pos.lambda-absnu;
    if(absnu>coordSys.delta || pos.lambda<coordSys.delta)
        throw std::invalid_argument("Error in OblatePerfectEllipsoid: "
            "incorrect values of spheroidal coordinates");
    double Glambda, dGdlambda, d2Gdlambda2, Gnu, dGdnu, d2Gdnu2;
    // values and derivatives of G(lambda) and G(|nu|)
    evalDeriv(pos.lambda, &Glambda, &dGdlambda, &d2Gdlambda2);
    evalDeriv(absnu,      &Gnu,     &dGdnu,     &d2Gdnu2);
    double coef=(Glambda-Gnu)/pow_2(lmn);  // common subexpression
    if(val!=NULL) 
        *val = (absnu*Gnu - pos.lambda*Glambda) / lmn;
    if(deriv!=NULL) {
        deriv->dlambda =   coef*absnu      - dGdlambda*pos.lambda / lmn;
        deriv->dnu     = (-coef*pos.lambda + dGdnu*absnu          / lmn) * signu;
        deriv->dphi    = 0;
    }
    if(deriv2!=NULL) {
        deriv2->dlambda2   = (2*absnu     *(-coef + dGdlambda/lmn) - d2Gdlambda2*pos.lambda) / lmn;
        deriv2->dnu2       = (2*pos.lambda*(-coef + dGdnu    /lmn) + d2Gdnu2    *absnu     ) / lmn;
        deriv2->dlambdadnu = ((pos.lambda+absnu)*coef - (pos.lambda*dGdlambda + absnu*dGdnu) / lmn ) / lmn * signu;
    }
}
示例#2
0
// Find the local min/maxs to optimize the solution. These are guaranteed to be buying/selling points
// If performance needs to be improved could use second derivitive to determine which is which
// to shorten search.
pointHolder find_peaks( coefficient_struct equation , int n )
{
	// These will be zeros of the derivitive
	pointHolder theZeros = {0};
	theZeros.points = malloc( sizeof( point ) * START_NUM_POINTS );

	// Problem is only to consider 1 ... n, not starting at 0
	int i = 1;
	double deriv = evalDeriv( i , equation );
	double lastValue;

	// when this switches from negative to positive we found a zero.
	// If we just looked for zero we would miss all zeros.
	int wasPositive = deriv > 0 ;

	// always incorporate the edges into min/max analyis
	addPoint( &theZeros , i , equation );
	
	// linear search for zeros of the derivitive
	// drop the first term, it's already included
	// can't drop the lalst term because it could make the term before it change the
	// sign of the derivitive and thus drag in the previous term.
	for ( i=2 ; i<(n+1); i++ )
	{
		lastValue = deriv;
		deriv = evalDeriv( i , equation );
		// ie the answer to the derivitive changed signs
		if ( wasPositive != ( deriv > 0 ) )
		{
			// found a maxima or minima
			// can't tell which point is actually the max/min so save both

			// take the left side first (so the list is in order)
			addPoint( &theZeros , i-1 , equation );
			// take the right side
			addPoint( &theZeros , i , equation );
			
		}
		wasPositive = deriv > 0;
	}

	// need to add the end bound
	addPoint( &theZeros , n , equation );

	return theZeros;

}
double BasePotentialSphericallySymmetric::enclosedMass(const double radius) const
{
    if(radius==INFINITY)
        return totalMass();
    double dPhidr;
    evalDeriv(radius, NULL, &dPhidr);
    return pow_2(radius)*dPhidr;
}