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; } }
// 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; }