text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include <limits>
#include <string>
#include "tudat/basics/testMacros.h"
#include "tudat/astro/basic_astro/orbitalElementConversions.h"
#include "tudat/astro/basic_astro/unitConversions.h"

#include <boost/test/unit_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/lambda/lambda.hpp>

#include "tudat/astro/basic_astro/sphericalStateConversions.h"
#include "tudat/interface/spice/spiceInterface.h"
#include "tudat/astro/ephemerides/keplerEphemeris.h"
#include "tudat/astro/relativity/metric.h"
#include "tudat/astro/orbit_determination/acceleration_partials/numericalAccelerationPartial.h"
#include "tudat/astro/orbit_determination/estimatable_parameters/gravitationalParameter.h"
#include "tudat/simulation/estimation_setup/createTorquePartials.h"
#include "tudat/simulation/environment_setup/createBodies.h"
#include "tudat/simulation/propagation_setup/createTorqueModel.h"
#include "tudat/simulation/estimation_setup/createEstimatableParameters.h"
#include "tudat/simulation/environment_setup/defaultBodies.h"

namespace tudat
{

namespace unit_tests
{

using namespace tudat::relativity;
using namespace tudat::gravitation;
using namespace tudat::aerodynamics;
using namespace tudat::ephemerides;
using namespace tudat::simulation_setup;
using namespace tudat::orbital_element_conversions;
using namespace tudat::unit_conversions;
using namespace tudat::orbit_determination;
using namespace tudat::acceleration_partials;
using namespace tudat::spice_interface;
using namespace tudat::orbit_determination;
using namespace tudat::estimatable_parameters;
using namespace tudat::electromagnetism;
using namespace tudat::basic_astrodynamics;

BOOST_AUTO_TEST_SUITE( test_torque_partials )

//! Test if partial derivatives of degree 2 torque are correctly implemented
BOOST_AUTO_TEST_CASE( testSecondDegreeGravitationalTorquePartials )
{
    // Load spice kernels.
    spice_interface::loadStandardSpiceKernels( );

    // Create bodies
    SystemOfBodies bodies = SystemOfBodies( "Mars", "ECLIPJ2000" );
    bodies.createEmptyBody( "Mars", false );
    bodies.at( "Mars" )->setEphemeris( std::make_shared< ephemerides::ConstantEphemeris >(
                                         [ = ]( ){ return Eigen::Vector6d::Zero( ); } ) );
    bodies.at( "Mars" )->setGravityFieldModel(
                std::make_shared< gravitation::GravityFieldModel >(
                    spice_interface::getBodyGravitationalParameter( "Mars" ) ) );
    bodies.createEmptyBody( "Phobos" );
    std::shared_ptr< Body > phobos = bodies.at( "Phobos" );
    std::shared_ptr< Body > mars = bodies.at( "Mars" );

    // Set inertia tensor
    Eigen::Matrix3d phobosInertiaTensor = Eigen::Matrix3d::Zero( );
    phobosInertiaTensor( 0, 0 ) = 0.3615;
    phobosInertiaTensor( 1, 1 ) = 0.4265;
    phobosInertiaTensor( 2, 2 ) = 0.5024;

    phobosInertiaTensor *= ( 11.27E3 * 11.27E3 * 1.0659E16 );
    bodies.at( "Phobos" )->setBodyInertiaTensor(
                phobosInertiaTensor, ( 0.3615 + 0.4265 + 0.5024 ) / 3.0 );

    // Create gravity field
    double phobosGravitationalParameter = 1.0659E16 * physical_constants::GRAVITATIONAL_CONSTANT;
    double phobosReferenceRadius = 11.27E3;

    Eigen::MatrixXd phobosCosineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 ),
            phobosSineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 );
    double phobosScaledMeanMomentOfInertia;
    gravitation::getDegreeTwoSphericalHarmonicCoefficients(
                phobosInertiaTensor, phobosGravitationalParameter, phobosReferenceRadius, true,
                phobosCosineGravityFieldCoefficients, phobosSineGravityFieldCoefficients, phobosScaledMeanMomentOfInertia );
    bodies.at( "Phobos" )->setGravityFieldModel(
                std::make_shared< gravitation::SphericalHarmonicsGravityField >(
                    phobosGravitationalParameter, phobosReferenceRadius, phobosCosineGravityFieldCoefficients,
                    phobosSineGravityFieldCoefficients, "Phobos_Fixed",
                    std::bind( &Body::setBodyInertiaTensorFromGravityFieldAndExistingMeanMoment, bodies.at( "Phobos" ), true ) ) );

    Eigen::Quaterniond noRotationQuaternion = Eigen::Quaterniond( Eigen::Matrix3d::Identity( ) );
    Eigen::Matrix< double, 7, 1 > unitRotationState = Eigen::Matrix< double, 7, 1 >::Zero( );
    unitRotationState( 0 ) = noRotationQuaternion.w( );
    unitRotationState( 1 ) = noRotationQuaternion.x( );
    unitRotationState( 2 ) = noRotationQuaternion.y( );
    unitRotationState( 3 ) = noRotationQuaternion.z( );

    // Set rotation and ephemeris models
    std::map< double, Eigen::Matrix< double, 7, 1 > > dummyRotationMap;
    dummyRotationMap[ -1.0E100 ] = unitRotationState;
    dummyRotationMap[ 1.0E100 ] = unitRotationState;
    std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::Matrix< double, 7, 1 > > > dummyInterpolator =
            std::make_shared< interpolators::LinearInterpolator< double, Eigen::Matrix< double, 7, 1 > > >( dummyRotationMap );
    bodies.at( "Phobos" )->setRotationalEphemeris( std::make_shared< TabulatedRotationalEphemeris< double, double > >(
                                                     dummyInterpolator, "ECLIPJ2000", "Phobos_Fixed" ) );

    Eigen::Vector6d phobosKeplerElements = Eigen::Vector6d::Zero( );
    double phobosSemiMajorAxis = 9376.0E3;
    phobosKeplerElements( 0 ) = phobosSemiMajorAxis;
    bodies.at( "Phobos" )->setEphemeris( std::make_shared< ephemerides::KeplerEphemeris >(
                                           phobosKeplerElements, 0.0, spice_interface::getBodyGravitationalParameter( "Mars" ),
                                           "Mars", "ECLIPJ2000" ) );

    // Update Phobos and Mars to current state
    double testTime = 1000.0;
    phobos->setStateFromEphemeris( testTime );
    mars->setStateFromEphemeris( testTime );

    // Set new Phobos rotational state
    Eigen::Vector7d phobosRotationalState = Eigen::Vector7d::Zero( );
    phobosRotationalState.segment( 0, 4 ) = tudat::linear_algebra::convertQuaternionToVectorFormat(
                Eigen::Quaterniond( Eigen::AngleAxisd( 0.4343, Eigen::Vector3d::UnitZ( ) ) *
                                    Eigen::AngleAxisd( 2.4354, Eigen::Vector3d::UnitX( ) ) *
                                    Eigen::AngleAxisd( 1.2434, Eigen::Vector3d::UnitY( ) ) ) );
    phobos->setCurrentRotationalStateToLocalFrame( phobosRotationalState );

    // Create torque due to mars on phobos.
    std::shared_ptr< SecondDegreeGravitationalTorqueModel > gravitationalTorque =
            createSecondDegreeGravitationalTorqueModel( bodies.at( "Phobos" ), bodies.at( "Mars" ), "Phobos", "Mars" );

    // Create torque partial.
    std::shared_ptr< TorquePartial > torquePartial =
            createAnalyticalTorquePartial( gravitationalTorque, std::make_pair( "Phobos", phobos ),
                                           std::make_pair( "Mars", mars ) );

    // Create parameter objects
    std::vector< std::shared_ptr< EstimatableParameterSettings > > parameterNames;
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Mars", gravitational_parameter) );
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Phobos", mean_moment_of_inertia ) );
    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 0, 3, 3, "Phobos", spherical_harmonics_cosine_coefficient_block ) );
    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 1, 3, 3, "Phobos", spherical_harmonics_sine_coefficient_block ) );
    std::shared_ptr< EstimatableParameterSet< double > > parameterSet =
            createParametersToEstimate( parameterNames, bodies );

    std::shared_ptr< EstimatableParameter< double > > marsGravitationalParameterParameter =
            parameterSet->getEstimatedDoubleParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< double > > phobosMeanMomentOfInertia =
            parameterSet->getEstimatedDoubleParameters( ).at( 1 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosCosineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosSineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 1 );

    // Calculate analytical partials.
    torquePartial->update( testTime );

    Eigen::MatrixXd partialWrtPhobosOrientation = Eigen::MatrixXd::Zero( 3, 4 );
    torquePartial->wrtOrientationOfAcceleratedBody( partialWrtPhobosOrientation.block( 0, 0, 3, 4 ) );

    Eigen::MatrixXd partialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratedBody( partialWrtPhobosRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );

    Eigen::MatrixXd partialWrtMarsOrientation = Eigen::MatrixXd::Zero( 3, 4  );
    torquePartial->wrtOrientationOfAcceleratingBody( partialWrtMarsOrientation.block( 0, 0, 3, 4 ) );

    Eigen::MatrixXd partialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratingBody( partialWrtMarsRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );

    Eigen::MatrixXd partialWrtPhobosState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtPhobosState.block( 0, 0, 3, 6 ), std::make_pair( "Phobos", "" ), propagators::translational_state );
    Eigen::MatrixXd partialWrtMarsState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtMarsState.block( 0, 0, 3, 6 ), std::make_pair( "Mars", "" ), propagators::translational_state );

    Eigen::Vector3d partialWrtMarsGravitationalParameter = torquePartial->wrtParameter(
                marsGravitationalParameterParameter );
    Eigen::Vector3d partialWrtMeanMomentOfInertia = torquePartial->wrtParameter(
                phobosMeanMomentOfInertia );

    Eigen::MatrixXd partialWrtPhobosCosineCoefficients = torquePartial->wrtParameter(
                phobosCosineCoefficientsParameter );
    Eigen::MatrixXd partialWrtPhobosSineCoefficients = torquePartial->wrtParameter(
                phobosSineCoefficientsParameter );

    // Declare numerical partials.
    Eigen::Matrix3d testPartialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix< double, 3, 4 > testPartialWrtMarsOrientation = Eigen::Matrix< double, 3, 4 >::Zero( );
    Eigen::Matrix3d testPartialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );

    Eigen::Matrix3d testPartialWrtMarsPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtMarsVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosVelocity = Eigen::Matrix3d::Zero( );

    // Define perturbations in orientation for numerical partial/
    Eigen::Vector4d orientationPerturbation;
    orientationPerturbation << 1.0E-9, 1.0E-9, 1.0E-9, 1.0E-9;
    Eigen::Vector3d rotationalVelocityPerturbation;
    rotationalVelocityPerturbation <<  1.0E-6, 1.0E-6, 1.0E-6;

    // Create state access/modification functions for bodies.
    std::function< void( Eigen::Vector7d ) > phobosRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector7d ) > marsRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, mars, std::placeholders::_1 );

    // Calculate numerical partials wrt rotational state.
    std::vector< Eigen::Vector4d > appliedQuaternionPerturbation;
    Eigen::MatrixXd torqueDeviations = calculateTorqueDeviationDueToOrientationChange(
                phobosRotationalStateSetFunction, gravitationalTorque, phobos->getRotationalStateVector( ), orientationPerturbation,
                appliedQuaternionPerturbation );

    testPartialWrtPhobosRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                phobosRotationalStateSetFunction, gravitationalTorque, phobos->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );
    testPartialWrtMarsOrientation =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, gravitationalTorque, mars->getRotationalStateVector( ), orientationPerturbation, 0, 4 );
    testPartialWrtMarsRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, gravitationalTorque, mars->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );

    std::function< void( Eigen::Vector6d ) > phobosStateSetFunction =
            std::bind( &Body::setState,  phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector6d ) > marsStateSetFunction =
            std::bind( &Body::setState, mars, std::placeholders::_1 );

    Eigen::Vector3d positionPerturbation;
    positionPerturbation << 1.0, 1.0, 100.0;
    Eigen::Vector3d velocityPerturbation;
    velocityPerturbation << 1.0E-3, 1.0E-3, 1.0E-3;

    // Calculate numerical partials wrt translational state.
    testPartialWrtMarsPosition = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, gravitationalTorque, mars->getState( ), positionPerturbation, 0 );
    testPartialWrtMarsVelocity = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, gravitationalTorque, mars->getState( ), velocityPerturbation, 3 );
    testPartialWrtPhobosPosition = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, gravitationalTorque, phobos->getState( ), positionPerturbation, 0 );
    testPartialWrtPhobosVelocity = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, gravitationalTorque, phobos->getState( ), velocityPerturbation, 3 );

    // Calculate numerical partials wrt parameters
    Eigen::Vector3d testPartialWrtMarsGravitationalParameter = calculateTorqueWrtParameterPartials(
                marsGravitationalParameterParameter, gravitationalTorque, 1.0E12 );
    Eigen::Vector3d testPartialWrtMeanMomentOfInertia = calculateTorqueWrtParameterPartials(
                phobosMeanMomentOfInertia, gravitationalTorque, 1.0E-1 );
    std::function< void( ) > updateFunction = &emptyFunction;
            //boost::bind( &Body::setBodyInertiaTensorFromGravityFieldAndExistingMeanMoment, bodies.at( "Phobos" ), true );
    Eigen::MatrixXd testPartialWrtPhobosCosineCoefficients = calculateTorqueWrtParameterPartials(
                phobosCosineCoefficientsParameter, gravitationalTorque,
                Eigen::VectorXd::Constant( phobosCosineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );
    Eigen::MatrixXd testPartialWrtPhobosSineCoefficients = calculateTorqueWrtParameterPartials(
                phobosSineCoefficientsParameter, gravitationalTorque,
                Eigen::VectorXd::Constant( phobosSineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );

    // Compare numerical and analytical results.
    for( int index = 1; index < 4; index++ )
    {
        Eigen::Vector3d numericalChangeInTorque = torqueDeviations.block( 0, index - 1, 3, 1 );
        Eigen::Vector3d analyticalChangeInTorque =
                partialWrtPhobosOrientation.block( 0, 0, 3, 1 ) * appliedQuaternionPerturbation[ index ]( 0 ) +
                partialWrtPhobosOrientation.block( 0, index, 3, 1 ) * appliedQuaternionPerturbation[ index ]( index );

        TUDAT_CHECK_MATRIX_CLOSE_FRACTION( numericalChangeInTorque,
                                           analyticalChangeInTorque, 1.0E-6 );
    }

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosRotationalVelocity,
                                       partialWrtPhobosRotationalVelocity, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsOrientation,
                                       partialWrtMarsOrientation, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsRotationalVelocity,
                                       partialWrtMarsRotationalVelocity, std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 0, 3, 3 ),
                                        testPartialWrtPhobosPosition, 1.0E-8 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 0, 3, 3 ),
                                        testPartialWrtMarsPosition, 1.0E-8 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 3, 3, 3 ),
                                        testPartialWrtPhobosVelocity, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 3, 3, 3 ),
                                        testPartialWrtMarsVelocity, std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsGravitationalParameter,
                                       partialWrtMarsGravitationalParameter, 1.0E-6 );

    // Check derivative of z-component w.r.t. C20 separately: value is slightly non-zero due to rounding error
    BOOST_CHECK_SMALL( std::fabs( testPartialWrtPhobosCosineCoefficients( 2, 2 ) ), 1.0E6 );
    testPartialWrtPhobosCosineCoefficients( 2, 2 ) = 0.0;

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosCosineCoefficients,
                                       partialWrtPhobosCosineCoefficients, 1.0E-9 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosSineCoefficients,
                                       partialWrtPhobosSineCoefficients, 1.0E-9 );

    for( int i = 0; i < 3; i++ )
    {
        BOOST_CHECK_SMALL( std::fabs( partialWrtMeanMomentOfInertia( i, 0 ) - testPartialWrtMeanMomentOfInertia( i, 0 ) ), 1.0E1 );
    }
}

BOOST_AUTO_TEST_CASE( testInertialTorquePartials )
{
    // Load spice kernels.
    spice_interface::loadStandardSpiceKernels( );

    // Create bodies
    SystemOfBodies bodies = SystemOfBodies( "Mars", "ECLIPJ2000" );
    bodies.createEmptyBody( "Mars", false );
    bodies.at( "Mars" )->setEphemeris( std::make_shared< ephemerides::ConstantEphemeris >(
                                         [ = ]( ){ return Eigen::Vector6d::Zero( ); } ) );
    bodies.at( "Mars" )->setGravityFieldModel(
                std::make_shared< gravitation::GravityFieldModel >(
                    spice_interface::getBodyGravitationalParameter( "Mars" ) ) );
    bodies.createEmptyBody( "Phobos" );
    std::shared_ptr< Body > phobos = bodies.at( "Phobos" );
    std::shared_ptr< Body > mars = bodies.at( "Mars" );

    // Set inertia tensor
    Eigen::Matrix3d phobosInertiaTensor = Eigen::Matrix3d::Zero( );
    phobosInertiaTensor( 0, 0 ) = 0.3615;
    phobosInertiaTensor( 1, 1 ) = 0.4265;
    phobosInertiaTensor( 2, 2 ) = 0.5024;

    phobosInertiaTensor *= ( 11.27E3 * 11.27E3 * 1.0659E16 );
    bodies.at( "Phobos" )->setBodyInertiaTensor(
                phobosInertiaTensor, ( 0.3615 + 0.4265 + 0.5024 ) / 3.0 );

    // Create gravity field
    double phobosGravitationalParameter = 1.0659E16 * physical_constants::GRAVITATIONAL_CONSTANT;
    double phobosReferenceRadius = 11.27E3;

    Eigen::MatrixXd phobosCosineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 ),
            phobosSineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 );
    double phobosScaledMeanMomentOfInertia;
    gravitation::getDegreeTwoSphericalHarmonicCoefficients(
                phobosInertiaTensor, phobosGravitationalParameter, phobosReferenceRadius, true,
                phobosCosineGravityFieldCoefficients, phobosSineGravityFieldCoefficients, phobosScaledMeanMomentOfInertia );

    bodies.at( "Phobos" )->setGravityFieldModel(
                std::make_shared< gravitation::SphericalHarmonicsGravityField >(
                    phobosGravitationalParameter, phobosReferenceRadius, phobosCosineGravityFieldCoefficients,
                    phobosSineGravityFieldCoefficients, "Phobos_Fixed" ) );

    Eigen::Quaterniond noRotationQuaternion = Eigen::Quaterniond( Eigen::Matrix3d::Identity( ) );
    Eigen::Matrix< double, 7, 1 > unitRotationState = Eigen::Matrix< double, 7, 1 >::Zero( );
    unitRotationState( 0 ) = noRotationQuaternion.w( );
    unitRotationState( 1 ) = noRotationQuaternion.x( );
    unitRotationState( 2 ) = noRotationQuaternion.y( );
    unitRotationState( 3 ) = noRotationQuaternion.z( );
    unitRotationState( 4 ) = 1.0E-5;
    unitRotationState( 5 ) = 2.0E-5;
    unitRotationState( 6 ) = -3.2E-5;

    // Set rotation and ephemeris models
    std::map< double, Eigen::Matrix< double, 7, 1 > > dummyRotationMap;
    dummyRotationMap[ -1.0E100 ] = unitRotationState;
    dummyRotationMap[ 1.0E100 ] = unitRotationState;
    std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::Matrix< double, 7, 1 > > > dummyInterpolator =
            std::make_shared< interpolators::LinearInterpolator< double, Eigen::Matrix< double, 7, 1 > > >( dummyRotationMap );
    bodies.at( "Phobos" )->setRotationalEphemeris( std::make_shared< TabulatedRotationalEphemeris< double, double > >(
                                                     dummyInterpolator, "ECLIPJ2000", "Phobos_Fixed" ) );

    Eigen::Vector6d phobosKeplerElements = Eigen::Vector6d::Zero( );
    double phobosSemiMajorAxis = 9376.0E3;
    phobosKeplerElements( 0 ) = phobosSemiMajorAxis;
    bodies.at( "Phobos" )->setEphemeris( std::make_shared< ephemerides::KeplerEphemeris >(
                                           phobosKeplerElements, 0.0, spice_interface::getBodyGravitationalParameter( "Mars" ),
                                           "Mars", "ECLIPJ2000" ) );

    // Update Phobos and Mars to current state
    double testTime = 1000.0;
    phobos->setStateFromEphemeris( testTime );
    mars->setStateFromEphemeris( testTime );

    // Set new Phobos rotational state
    Eigen::Vector7d phobosRotationalState = Eigen::Vector7d::Zero( );
    phobosRotationalState.segment( 0, 4 ) = tudat::linear_algebra::convertQuaternionToVectorFormat(
                Eigen::Quaterniond( Eigen::AngleAxisd( 0.4343, Eigen::Vector3d::UnitZ( ) ) *
                                    Eigen::AngleAxisd( 2.4354, Eigen::Vector3d::UnitX( ) ) *
                                    Eigen::AngleAxisd( 1.2434, Eigen::Vector3d::UnitY( ) ) ) );
    phobosRotationalState( 4 ) = 1.0E-5;
    phobosRotationalState( 5 ) = 2.0E-5;
    phobosRotationalState( 6 ) = -3.2E-5;
    phobos->setCurrentRotationalStateToLocalFrame( phobosRotationalState );

    // Create torque due to mars on phobos.
    std::shared_ptr< InertialTorqueModel > inertialTorqueModel =
            createInertialTorqueModel( bodies.at( "Phobos" ), "Phobos" );
    inertialTorqueModel->updateMembers( 0.0 );

    SingleBodyTorqueModelMap torqueList;
    torqueList[ "Phobos" ].push_back( inertialTorqueModel );

    // Create shared_ptr partial.
    std::shared_ptr< TorquePartial > torquePartial =
            createAnalyticalTorquePartial( inertialTorqueModel, std::make_pair( "Phobos", phobos ),
                                           std::make_pair( "Phobos", phobos ) );

    // Create parameter objects.
    std::vector< std::shared_ptr< EstimatableParameterSettings > > parameterNames;
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Phobos", gravitational_parameter) );
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Phobos", mean_moment_of_inertia ) );

    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 0, 3, 3, "Phobos", spherical_harmonics_cosine_coefficient_block ) );
    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 1, 3, 3, "Phobos", spherical_harmonics_sine_coefficient_block ) );

    std::shared_ptr< EstimatableParameterSet< double > > parameterSet =
            createParametersToEstimate( parameterNames, bodies );

    std::shared_ptr< EstimatableParameter< double > > phobosGravitationalParameterParameter =
            parameterSet->getEstimatedDoubleParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< double > > meanMomentOfInertiaParameter =
            parameterSet->getEstimatedDoubleParameters( ).at( 1 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosCosineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosSineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 1 );

    // Calculate analytical partials.
    torquePartial->update( testTime );

    Eigen::MatrixXd partialWrtPhobosOrientation = Eigen::MatrixXd::Zero( 3, 4 );
    torquePartial->wrtOrientationOfAcceleratedBody( partialWrtPhobosOrientation.block( 0, 0, 3, 4 ) );
    Eigen::MatrixXd partialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratedBody( partialWrtPhobosRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );
    Eigen::MatrixXd partialWrtMarsOrientation = Eigen::MatrixXd::Zero( 3, 4  );
    torquePartial->wrtOrientationOfAcceleratingBody( partialWrtMarsOrientation.block( 0, 0, 3, 4 ) );
    Eigen::MatrixXd partialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratingBody( partialWrtMarsRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );

    Eigen::MatrixXd partialWrtPhobosState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtPhobosState.block( 0, 0, 3, 6 ), std::make_pair( "Phobos", "" ), propagators::translational_state );
    Eigen::MatrixXd partialWrtMarsState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtMarsState.block( 0, 0, 3, 6 ), std::make_pair( "Mars", "" ), propagators::translational_state );

    Eigen::Vector3d partialWrtPhobosGravitationalParameter = torquePartial->wrtParameter(
                phobosGravitationalParameterParameter );
    Eigen::Vector3d partialWrtMeanMomentOfInertia = torquePartial->wrtParameter(
                meanMomentOfInertiaParameter );

    Eigen::MatrixXd partialWrtPhobosCosineCoefficients = torquePartial->wrtParameter(
                phobosCosineCoefficientsParameter );
    Eigen::MatrixXd partialWrtPhobosSineCoefficients = torquePartial->wrtParameter(
                phobosSineCoefficientsParameter );

    // Declare numerical partials.
    Eigen::Matrix3d testPartialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix< double, 3, 4 > testPartialWrtMarsOrientation = Eigen::Matrix< double, 3, 4 >::Zero( );
    Eigen::Matrix3d testPartialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );

    Eigen::Matrix3d testPartialWrtMarsPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtMarsVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosVelocity = Eigen::Matrix3d::Zero( );

    // Declare perturbations in orientation for numerical partial
    Eigen::Vector4d orientationPerturbation;
    orientationPerturbation << 1.0E-9, 1.0E-9, 1.0E-9, 1.0E-9;
    Eigen::Vector3d rotationalVelocityPerturbation;
    rotationalVelocityPerturbation <<  1.0E-6, 1.0E-6, 1.0E-6;

    // Create state access/modification functions for bodies.
    std::function< void( Eigen::Vector7d ) > phobosRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector7d ) > marsRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, mars, std::placeholders::_1 );

    // Calculate numerical partials.
    std::vector< Eigen::Vector4d > appliedQuaternionPerturbation;
    Eigen::MatrixXd torqueDeviations = calculateTorqueDeviationDueToOrientationChange(
                phobosRotationalStateSetFunction, inertialTorqueModel, phobos->getRotationalStateVector( ), orientationPerturbation,
                appliedQuaternionPerturbation );

    testPartialWrtPhobosRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                phobosRotationalStateSetFunction, inertialTorqueModel, phobos->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );
    testPartialWrtMarsOrientation =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, inertialTorqueModel, mars->getRotationalStateVector( ), orientationPerturbation, 0, 4 );
    testPartialWrtMarsRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, inertialTorqueModel, mars->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );

    std::function< void( Eigen::Vector6d ) > phobosStateSetFunction =
            std::bind( &Body::setState,  phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector6d ) > marsStateSetFunction =
            std::bind( &Body::setState, mars, std::placeholders::_1 );

    Eigen::Vector3d positionPerturbation;
    positionPerturbation << 1.0, 1.0, 100.0;
    Eigen::Vector3d velocityPerturbation;
    velocityPerturbation << 1.0E-3, 1.0E-3, 1.0E-3;

    // Calculate numerical partials.
    testPartialWrtMarsPosition = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, inertialTorqueModel, mars->getState( ), positionPerturbation, 0 );
    testPartialWrtMarsVelocity = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, inertialTorqueModel, mars->getState( ), velocityPerturbation, 3 );
    testPartialWrtPhobosPosition = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, inertialTorqueModel, phobos->getState( ), positionPerturbation, 0 );
    testPartialWrtPhobosVelocity = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, inertialTorqueModel, phobos->getState( ), velocityPerturbation, 3 );

    std::function< void( ) > updateFunction = //&emptyFunction;
            std::bind( &Body::setBodyInertiaTensorFromGravityFieldAndExistingMeanMoment, bodies.at( "Phobos" ), true );
    Eigen::Vector3d testPartialWrtPhobosGravitationalParameter = calculateTorqueWrtParameterPartials(
                phobosGravitationalParameterParameter, inertialTorqueModel, 1.0E8, updateFunction );
    Eigen::MatrixXd testPartialWrtMeanMomentOfInertia = calculateTorqueWrtParameterPartials(
                meanMomentOfInertiaParameter, inertialTorqueModel, 1.0E-1, updateFunction );
    Eigen::MatrixXd testPartialWrtPhobosCosineCoefficients = calculateTorqueWrtParameterPartials(
                phobosCosineCoefficientsParameter, inertialTorqueModel,
                Eigen::VectorXd::Constant( phobosCosineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );
    Eigen::MatrixXd testPartialWrtPhobosSineCoefficients = calculateTorqueWrtParameterPartials(
                phobosSineCoefficientsParameter, inertialTorqueModel,
                Eigen::VectorXd::Constant( phobosSineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );

    //    // Compare numerical and analytical results.
    for( int index = 1; index < 4; index++ )
    {
        Eigen::Vector3d numericalChangeInTorque = torqueDeviations.block( 0, index - 1, 3, 1 );
        Eigen::Vector3d analyticalChangeInTorque =
                partialWrtPhobosOrientation.block( 0, 0, 3, 1 ) * appliedQuaternionPerturbation[ index ]( 0 ) +
                partialWrtPhobosOrientation.block( 0, index, 3, 1 ) * appliedQuaternionPerturbation[ index ]( index );

        TUDAT_CHECK_MATRIX_CLOSE_FRACTION( numericalChangeInTorque,
                                           analyticalChangeInTorque, std::numeric_limits< double >::epsilon( ) );
    }

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosRotationalVelocity,
                                       partialWrtPhobosRotationalVelocity, 1.0E-10 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsOrientation,
                                       partialWrtMarsOrientation, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsRotationalVelocity,
                                       partialWrtMarsRotationalVelocity, std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 0, 3, 3 ),
                                        testPartialWrtPhobosPosition, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 0, 3, 3 ),
                                        testPartialWrtMarsPosition, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 3, 3, 3 ),
                                        testPartialWrtPhobosVelocity, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 3, 3, 3 ),
                                        testPartialWrtMarsVelocity, std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosGravitationalParameter,
                                       partialWrtPhobosGravitationalParameter, 1.0E-6 );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosCosineCoefficients.block( 0, 0, 3, 2 ),
                                       Eigen::MatrixXd::Zero( 3, 2 ), std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosCosineCoefficients.block( 0, 5, 3, 4 ),
                                       Eigen::MatrixXd::Zero( 3, 4 ), std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosSineCoefficients.block( 0, 0, 3, 1 ),
                                       Eigen::MatrixXd::Zero( 3, 1 ), std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosSineCoefficients.block( 0, 3, 3, 3 ),
                                       Eigen::MatrixXd::Zero( 3, 3 ), std::numeric_limits< double >::epsilon( ) );

    // Check derivative of z-component w.r.t. C20 separately: value is slightly non-zero due to rounding error
    BOOST_CHECK_SMALL( std::fabs( testPartialWrtPhobosCosineCoefficients( 2, 2 ) ), 1.0E5 );
    testPartialWrtPhobosCosineCoefficients( 2, 2 ) = 0.0;

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosCosineCoefficients,
                                       partialWrtPhobosCosineCoefficients, 1.0E-9 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosSineCoefficients,
                                       partialWrtPhobosSineCoefficients, 1.0E-9 );

    for( int i = 0; i < 3; i++ )
    {
        BOOST_CHECK_SMALL( std::fabs( partialWrtMeanMomentOfInertia( i, 0 ) - testPartialWrtMeanMomentOfInertia( i, 0 ) ), 1.0E1 );
    }
}

class EffectiveTorqueModel: public basic_astrodynamics::TorqueModel
{
public:
    EffectiveTorqueModel(
            const std::function< Eigen::Matrix3d( ) > inertiaTensorFunction,
            const SingleBodyTorqueModelMap& torqueList ):
        inertiaTensorFunction_( inertiaTensorFunction ), torqueList_( torqueList ){ }

    Eigen::Vector3d getTorque( )
    {
        return effectiveTorque_;
    }

    void updateMembers( const double currentTime )
    {
        Eigen::Vector3d totalTorque = Eigen::Vector3d::Zero( );
        for( auto it = torqueList_.begin( ); it != torqueList_.end( ); it++ )
        {
            for( unsigned int i = 0; i < it->second.size( ); i++ )
            {
                totalTorque += it->second.at( i )->getTorque( );
            }
        }

        effectiveTorque_ = inertiaTensorFunction_( ).inverse( ) * totalTorque;
    }

private:

    std::function< Eigen::Matrix3d( ) > inertiaTensorFunction_;

    SingleBodyTorqueModelMap torqueList_;

    Eigen::Vector3d effectiveTorque_;
};

BOOST_AUTO_TEST_CASE( testConstantTorquePartials )
{
    // Load spice kernels.
    spice_interface::loadStandardSpiceKernels( );

    SystemOfBodies bodies = SystemOfBodies( "Mars", "ECLIPJ2000" );
    bodies.createEmptyBody( "Mars", false );
    bodies.at( "Mars" )->setEphemeris( std::make_shared< ephemerides::ConstantEphemeris >(
                                         [ = ]( ){ return Eigen::Vector6d::Zero( ); } ) );
    bodies.at( "Mars" )->setGravityFieldModel(
                std::make_shared< gravitation::GravityFieldModel >(
                    spice_interface::getBodyGravitationalParameter( "Mars" ) ) );
    bodies.createEmptyBody( "Phobos" );

    Eigen::Matrix3d phobosInertiaTensor = Eigen::Matrix3d::Zero( );
    phobosInertiaTensor( 0, 0 ) = 0.3615;
    phobosInertiaTensor( 1, 1 ) = 0.4265;
    phobosInertiaTensor( 2, 2 ) = 0.5024;

    phobosInertiaTensor *= ( 11.27E3 * 11.27E3 * 1.0659E16 );
    bodies.at( "Phobos" )->setBodyInertiaTensor(
                phobosInertiaTensor, ( 0.3615 + 0.4265 + 0.5024 ) / 3.0 );

    double phobosGravitationalParameter = 1.0659E16 * physical_constants::GRAVITATIONAL_CONSTANT;
    double phobosReferenceRadius = 11.27E3;

    Eigen::MatrixXd phobosCosineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 ),
            phobosSineGravityFieldCoefficients = Eigen::MatrixXd::Zero( 6, 6 );
    double phobosScaledMeanMomentOfInertia;
    gravitation::getDegreeTwoSphericalHarmonicCoefficients(
                phobosInertiaTensor, phobosGravitationalParameter, phobosReferenceRadius, true,
                phobosCosineGravityFieldCoefficients, phobosSineGravityFieldCoefficients, phobosScaledMeanMomentOfInertia );

    bodies.at( "Phobos" )->setGravityFieldModel(
                std::make_shared< gravitation::SphericalHarmonicsGravityField >(
                    phobosGravitationalParameter, phobosReferenceRadius, phobosCosineGravityFieldCoefficients,
                    phobosSineGravityFieldCoefficients, "Phobos_Fixed",
                    std::bind( &Body::setBodyInertiaTensorFromGravityFieldAndExistingMeanMoment, bodies.at( "Phobos" ), true ) ) );

    Eigen::Quaterniond noRotationQuaternion = Eigen::Quaterniond( Eigen::Matrix3d::Identity( ) );
    Eigen::Matrix< double, 7, 1 > unitRotationState = Eigen::Matrix< double, 7, 1 >::Zero( );
    unitRotationState( 0 ) = noRotationQuaternion.w( );
    unitRotationState( 1 ) = noRotationQuaternion.x( );
    unitRotationState( 2 ) = noRotationQuaternion.y( );
    unitRotationState( 3 ) = noRotationQuaternion.z( );
    unitRotationState( 4 ) = 1.0E-5;
    unitRotationState( 5 ) = 2.0E-5;
    unitRotationState( 6 ) = -3.2E-5;

    std::map< double, Eigen::Matrix< double, 7, 1 > > dummyRotationMap;
    dummyRotationMap[ -1.0E100 ] = unitRotationState;
    dummyRotationMap[ 1.0E100 ] = unitRotationState;

    std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::Matrix< double, 7, 1 > > > dummyInterpolator =
            std::make_shared< interpolators::LinearInterpolator< double, Eigen::Matrix< double, 7, 1 > > >( dummyRotationMap );
    bodies.at( "Phobos" )->setRotationalEphemeris( std::make_shared< TabulatedRotationalEphemeris< double, double > >(
                                                     dummyInterpolator, "ECLIPJ2000", "Phobos_Fixed" ) );

    Eigen::Vector6d phobosKeplerElements = Eigen::Vector6d::Zero( );
    double phobosSemiMajorAxis = 9376.0E3;
    phobosKeplerElements( 0 ) = phobosSemiMajorAxis;

    bodies.at( "Phobos" )->setEphemeris( std::make_shared< ephemerides::KeplerEphemeris >(
                                           phobosKeplerElements, 0.0, spice_interface::getBodyGravitationalParameter( "Mars" ),
                                           "Mars", "ECLIPJ2000" ) );

    // Create empty bodies, phobos and mars.
    std::shared_ptr< Body > phobos = bodies.at( "Phobos" );
    std::shared_ptr< Body > mars = bodies.at( "Mars" );

    double testTime = 1000.0;
    phobos->setStateFromEphemeris( testTime );

    Eigen::Vector7d phobosRotationalState = Eigen::Vector7d::Zero( );
    phobosRotationalState.segment( 0, 4 ) = tudat::linear_algebra::convertQuaternionToVectorFormat(
                Eigen::Quaterniond( Eigen::AngleAxisd( 0.4343, Eigen::Vector3d::UnitZ( ) ) *
                                    Eigen::AngleAxisd( 2.4354, Eigen::Vector3d::UnitX( ) ) *
                                    Eigen::AngleAxisd( 1.2434, Eigen::Vector3d::UnitY( ) ) ) );
    phobosRotationalState( 4 ) = 1.0E-5;
    phobosRotationalState( 5 ) = 2.0E-5;
    phobosRotationalState( 6 ) = -3.2E-5;

    phobos->setCurrentRotationalStateToLocalFrame( phobosRotationalState );

    mars->setStateFromEphemeris( testTime );
    //    mars->setCurrentRotationalStateToLocalFrameFromEphemeris( 0.0 );

    // Create acceleration due to mars on phobos.
    std::shared_ptr< SecondDegreeGravitationalTorqueModel > gravitationalTorque =
            createSecondDegreeGravitationalTorqueModel( bodies.at( "Phobos" ), bodies.at( "Mars" ), "Phobos", "Mars" );
    std::shared_ptr< InertialTorqueModel > inertialTorqueModel =
            createInertialTorqueModel( bodies.at( "Phobos" ), "Phobos" );
    gravitationalTorque->updateMembers( 0.0 );
    inertialTorqueModel->updateMembers( 0.0 );

    SingleBodyTorqueModelMap torqueList;
    torqueList[ "Mars" ].push_back( gravitationalTorque );
    torqueList[ "Phobos" ].push_back( inertialTorqueModel );

    std::shared_ptr< EffectiveTorqueModel > effectiveTorqueModel =
            std::make_shared< EffectiveTorqueModel >(
                std::bind( &Body::getBodyInertiaTensor, bodies.at( "Phobos" ) ), torqueList );
    effectiveTorqueModel->updateMembers( 0.0 );

    // Create central gravity partial.
    std::shared_ptr< TorquePartial > torquePartial =
            createConstantTorqueRotationalDynamicsPartial(
                std::make_pair( "Phobos", bodies.at( "Phobos" ) ), torqueList );

    // Create gravitational parameter object.
    std::vector< std::shared_ptr< EstimatableParameterSettings > > parameterNames;
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Phobos", gravitational_parameter) );
    parameterNames.push_back( std::make_shared< EstimatableParameterSettings >( "Phobos", mean_moment_of_inertia ) );

    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 0, 3, 3, "Phobos", spherical_harmonics_cosine_coefficient_block ) );
    parameterNames.push_back( std::make_shared< SphericalHarmonicEstimatableParameterSettings >(
                                  1, 1, 3, 3, "Phobos", spherical_harmonics_sine_coefficient_block ) );

    std::shared_ptr< EstimatableParameterSet< double > > parameterSet =
            createParametersToEstimate( parameterNames, bodies );

    std::shared_ptr< EstimatableParameter< double > > phobosGravitationalParameterParameter =
            parameterSet->getEstimatedDoubleParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< double > > meanMomentOfInertiaParameter =
            parameterSet->getEstimatedDoubleParameters( ).at( 1 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosCosineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 0 );
    std::shared_ptr< EstimatableParameter< Eigen::VectorXd > > phobosSineCoefficientsParameter =
            parameterSet->getEstimatedVectorParameters( ).at( 1 );

    // Calculate analytical partials.
    torquePartial->update( testTime );

    Eigen::MatrixXd partialWrtPhobosOrientation = Eigen::MatrixXd::Zero( 3, 4 );
    torquePartial->wrtOrientationOfAcceleratedBody( partialWrtPhobosOrientation.block( 0, 0, 3, 4 ) );
    Eigen::MatrixXd partialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratedBody( partialWrtPhobosRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );
    Eigen::MatrixXd partialWrtMarsOrientation = Eigen::MatrixXd::Zero( 3, 4  );
    torquePartial->wrtOrientationOfAcceleratingBody( partialWrtMarsOrientation.block( 0, 0, 3, 4 ) );
    Eigen::MatrixXd partialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );
    torquePartial->wrtRotationalVelocityOfAcceleratingBody( partialWrtMarsRotationalVelocity.block( 0, 0, 3, 3 ), 1, 0, 0 );

    Eigen::MatrixXd partialWrtPhobosState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtPhobosState.block( 0, 0, 3, 6 ), std::make_pair( "Phobos", "" ), propagators::translational_state );
    Eigen::MatrixXd partialWrtMarsState = Eigen::MatrixXd::Zero( 3, 6 );
    torquePartial->wrtNonRotationalStateOfAdditionalBody(
                partialWrtMarsState.block( 0, 0, 3, 6 ), std::make_pair( "Mars", "" ), propagators::translational_state );

    Eigen::Vector3d partialWrtPhobosGravitationalParameter = torquePartial->wrtParameter(
                phobosGravitationalParameterParameter );
    Eigen::Vector3d partialWrtMeanMomentOfInertia = torquePartial->wrtParameter(
                meanMomentOfInertiaParameter );

    Eigen::MatrixXd partialWrtPhobosCosineCoefficients = torquePartial->wrtParameter(
                phobosCosineCoefficientsParameter );
    Eigen::MatrixXd partialWrtPhobosSineCoefficients = torquePartial->wrtParameter(
                phobosSineCoefficientsParameter );

    // Declare numerical partials.
    Eigen::Matrix3d testPartialWrtPhobosRotationalVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix< double, 3, 4 > testPartialWrtMarsOrientation = Eigen::Matrix< double, 3, 4 >::Zero( );
    Eigen::Matrix3d testPartialWrtMarsRotationalVelocity = Eigen::Matrix3d::Zero( );

    Eigen::Matrix3d testPartialWrtMarsPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtMarsVelocity = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosPosition = Eigen::Matrix3d::Zero( );
    Eigen::Matrix3d testPartialWrtPhobosVelocity = Eigen::Matrix3d::Zero( );

    // Declare perturbations in orientation for numerical partial/
    Eigen::Vector4d orientationPerturbation;
    orientationPerturbation << 1.0E-9, 1.0E-9, 1.0E-9, 1.0E-9;
    Eigen::Vector3d rotationalVelocityPerturbation;
    rotationalVelocityPerturbation <<  1.0E-6, 1.0E-6, 1.0E-6;

    // Create state access/modification functions for bodies.
    std::function< void( Eigen::Vector7d ) > phobosRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector7d ) > marsRotationalStateSetFunction =
            std::bind( &Body::setCurrentRotationalStateToLocalFrame, mars, std::placeholders::_1 );

    //    // Calculate numerical partials.
    std::vector< Eigen::Vector4d > appliedQuaternionPerturbation;
    Eigen::MatrixXd torqueDeviations = calculateTorqueDeviationDueToOrientationChange(
                phobosRotationalStateSetFunction, effectiveTorqueModel, phobos->getRotationalStateVector( ), orientationPerturbation,
                appliedQuaternionPerturbation );

    testPartialWrtPhobosRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                phobosRotationalStateSetFunction, effectiveTorqueModel, phobos->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );
    testPartialWrtMarsOrientation =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, effectiveTorqueModel, mars->getRotationalStateVector( ), orientationPerturbation, 0, 4 );
    testPartialWrtMarsRotationalVelocity =  calculateTorqueWrtRotationalStatePartials(
                marsRotationalStateSetFunction, effectiveTorqueModel, mars->getRotationalStateVector( ), rotationalVelocityPerturbation, 4, 3 );

    std::function< void( Eigen::Vector6d ) > phobosStateSetFunction =
            std::bind( &Body::setState,  phobos, std::placeholders::_1 );
    std::function< void( Eigen::Vector6d ) > marsStateSetFunction =
            std::bind( &Body::setState, mars, std::placeholders::_1 );

    Eigen::Vector3d positionPerturbation;
    positionPerturbation << 1.0, 1.0, 100.0;
    Eigen::Vector3d velocityPerturbation;
    velocityPerturbation << 1.0E-3, 1.0E-3, 1.0E-3;

    // Calculate numerical partials.
    testPartialWrtMarsPosition = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, effectiveTorqueModel, mars->getState( ), positionPerturbation, 0 );
    testPartialWrtMarsVelocity = calculateTorqueWrtTranslationalStatePartials(
                marsStateSetFunction, effectiveTorqueModel, mars->getState( ), velocityPerturbation, 3 );
    testPartialWrtPhobosPosition = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, effectiveTorqueModel, phobos->getState( ), positionPerturbation, 0 );
    testPartialWrtPhobosVelocity = calculateTorqueWrtTranslationalStatePartials(
                phobosStateSetFunction, effectiveTorqueModel, phobos->getState( ), velocityPerturbation, 3 );

    std::function< void( ) > updateFunction = &emptyFunction;
           // std::bind( &Body::setBodyInertiaTensorFromGravityFieldAndExistingMeanMoment, bodies.at( "Phobos" ), true );
    Eigen::Vector3d testPartialWrtPhobosGravitationalParameter = calculateTorqueWrtParameterPartials(
                phobosGravitationalParameterParameter, effectiveTorqueModel, 1.0E2, updateFunction );
    Eigen::MatrixXd testPartialWrtMeanMomentOfInertia = calculateTorqueWrtParameterPartials(
                meanMomentOfInertiaParameter, effectiveTorqueModel, 1.0E-4, updateFunction );
    Eigen::MatrixXd testPartialWrtPhobosCosineCoefficients = calculateTorqueWrtParameterPartials(
                phobosCosineCoefficientsParameter, effectiveTorqueModel,
                Eigen::VectorXd::Constant( phobosCosineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );
    Eigen::MatrixXd testPartialWrtPhobosSineCoefficients = calculateTorqueWrtParameterPartials(
                phobosSineCoefficientsParameter, effectiveTorqueModel,
                Eigen::VectorXd::Constant( phobosSineCoefficientsParameter->getParameterSize( ), 1.0E-6 ), updateFunction );

    //    // Compare numerical and analytical results.
    for( int index = 1; index < 4; index++ )
    {
        Eigen::Vector3d numericalChangeInTorque = torqueDeviations.block( 0, index - 1, 3, 1 );
        Eigen::Vector3d analyticalChangeInTorque =
                partialWrtPhobosOrientation.block( 0, 0, 3, 1 ) * appliedQuaternionPerturbation[ index ]( 0 ) +
                partialWrtPhobosOrientation.block( 0, index, 3, 1 ) * appliedQuaternionPerturbation[ index ]( index );

        TUDAT_CHECK_MATRIX_CLOSE_FRACTION( numericalChangeInTorque,
                                           analyticalChangeInTorque, std::numeric_limits< double >::epsilon( ) );
    }

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtPhobosRotationalVelocity,
                                       partialWrtPhobosRotationalVelocity, 1.0E-10 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsOrientation,
                                       partialWrtMarsOrientation, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( testPartialWrtMarsRotationalVelocity,
                                       partialWrtMarsRotationalVelocity, std::numeric_limits< double >::epsilon( ) );

    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 0, 3, 3 ),
                                        testPartialWrtPhobosPosition, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 0, 3, 3 ),
                                        testPartialWrtMarsPosition, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtPhobosState.block( 0, 3, 3, 3 ),
                                        testPartialWrtPhobosVelocity, std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION(  partialWrtMarsState.block( 0, 3, 3, 3 ),
                                        testPartialWrtMarsVelocity, std::numeric_limits< double >::epsilon( ) );

    Eigen::Vector3d sclaedPartialWrtPhobosGravitationalParameter = phobosInertiaTensor * testPartialWrtPhobosGravitationalParameter;
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( sclaedPartialWrtPhobosGravitationalParameter,
                                       partialWrtPhobosGravitationalParameter, 1.0E-6 );

    Eigen::Vector3d scaledPartialWrtMeanMomentOfInertia = phobosInertiaTensor * testPartialWrtMeanMomentOfInertia;
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( scaledPartialWrtMeanMomentOfInertia,
                                       partialWrtMeanMomentOfInertia, 1.0E-6 );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosCosineCoefficients.block( 0, 0, 3, 2 ),
                                       Eigen::MatrixXd::Zero( 3, 2 ), std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosCosineCoefficients.block( 0, 5, 3, 4 ),
                                       Eigen::MatrixXd::Zero( 3, 4 ), std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosSineCoefficients.block( 0, 0, 3, 1 ),
                                       Eigen::MatrixXd::Zero( 3, 1 ), std::numeric_limits< double >::epsilon( ) );
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( partialWrtPhobosSineCoefficients.block( 0, 3, 3, 3 ),
                                       Eigen::MatrixXd::Zero( 3, 3 ), std::numeric_limits< double >::epsilon( ) );

    // Check derivative of z-component w.r.t. C20 separately: value is slightly non-zero due to rounding error
    Eigen::MatrixXd scaledPartialWrtPhobosCosineCoefficients = phobosInertiaTensor * testPartialWrtPhobosCosineCoefficients;
    BOOST_CHECK_SMALL( std::fabs( scaledPartialWrtPhobosCosineCoefficients( 2, 4 ) ), 1.0E5 );
    scaledPartialWrtPhobosCosineCoefficients( 2, 4 ) = 0.0;
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( scaledPartialWrtPhobosCosineCoefficients, partialWrtPhobosCosineCoefficients, 1.0E-9 );

    Eigen::MatrixXd scaledPartialWrtPhobosSineCoefficients = phobosInertiaTensor * testPartialWrtPhobosSineCoefficients;
    TUDAT_CHECK_MATRIX_CLOSE_FRACTION( scaledPartialWrtPhobosSineCoefficients, partialWrtPhobosSineCoefficients, 1.0E-9 );

}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests

} // namespace tudat

redpajama_set_name: RedPajamaGithub


text:
Q: Get following sibling on android using Appium driver.findElementByXPath("//android.widget.TextView[@text='a1492']/../following-sibling::android.view.ViewGroup").click();

This does not work. Am I missing anything?

A: @text is looking for an attribute text. If you're actually after the text content, it's [text()='a1492'].

A: You can try below, this will solve your problem:
driver.findElementByXPath("//android.view.ViewGroup[preceding-sibling::android.view.ViewGroup/*[@text='a1492']]").click();

redpajama_set_name: RedPajamaStackExchange


text:
Exposure Evaluation
CartIcon
Close featured products sub-menu
Congratulations, you qualify for free shipping!
You're $25.00 away from free standard shipping.
Ali Forney Center Pilot PPE Program
KleenWraps is excited to announce its first pilot program to provide in-need and at-risk organizations with much needed PPE. Our first partnership is with the Ali Forney Center (AFC), the nation's largest LGBTQ homeless youth shelter and services organization based in New York City.
AFC, founded in 2002, is named in memory of a gender-nonconforming teen, Ali Forney (they/their/them), who fled their home at the age of 13. Without a supportive family to turn to, Ali was placed into the foster care system where they were beaten and abused, left homeless, Ali was murdered in 1997—one of several victims in a series of LGBTQ-bias crimes in upper Manhattan in the late 1990s. AFC founder, Carl Siciliano, named the organization in Ali's honor, having met and worked with the teen at Manhattan shelter.
AFC's focus is to provide safe and loving care to the LGBTQ teens and young adults it serves, ranging from ages 16 to 25. In addition to providing medical checkups, serving more than 2,000 meals a year, group therapy and case management at its 24-hour Harlem drop in shelter, AFC has a network of 16 residences in Manhattan and Brooklyn with approximately 58 beds for LGBTQ identifying youth.
As part of our pilot program with AFC, KleenWraps will donate 80 of its Wide Wraps for youth in AFC's transitional residences program. Residents will be able to use the KleenWraps as tools to help protect themselves and their community as they get around New York to carry out day-to-day activities of employment and education. Thanks to the facilities and level of care at AFC, residents will be able to launder and reuse their KleenWraps, cutting down on the environmental impact of single-use PPE.
KleenWraps will continue to identify in-need and at-risk organizations to provide the necessary PPE to prevent pathogen spread.
For more information on AFC, please visit, www.aliforneycenter.org
Get the latest from KleenWraps.
By signing up for the newsletter, you agree to our Privacy Policy and Cookie Policy.
Narrow Wraps
Wide Wraps
Handlebar Tubes
Lifestyle Set
Commuter Set
Fitness Set
Ultimate Set
KleenWraps Mask
KleenWraps
© 2022 KleenWraps. All rights reserved.
Shipping & taxes calculated at checkout. Discounts cannot be applied on Express Checkout.

redpajama_set_name: RedPajamaCommonCrawl


Conferences should explicitly make the conference rules clear, i.e. either open or Chatham House Rules. My guess is that in most scenario's, especially larger conferences like ISMB, open is the only route, so microblogging is going to happen, either on Twitter, or using tools like CoverIt. What makes FF so amazing is (a) the group nature, and (b) the interactivity.
Shirley, thanks so much for writing this! I am passing it on to Lynne Friedmann of the National Association of Science Writers (we're both members, but she's an officer) for our annual conferences….


text:
//snippet-sourcedescription:[S3Cors.java demonstrates how to manage cross-origin resource sharing (CORS) for an Amazon Simple Storage Service (Amazon S3) bucket.]
//snippet-keyword:[AWS SDK for Java v2]
//snippet-service:[Amazon S3]

package com.example.s3;

// snippet-start:[s3.java2.cors.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import java.util.ArrayList;
import java.util.List;
import software.amazon.awssdk.services.s3.model.GetBucketCorsRequest;
import software.amazon.awssdk.services.s3.model.GetBucketCorsResponse;
import software.amazon.awssdk.services.s3.model.DeleteBucketCorsRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.CORSRule;
import software.amazon.awssdk.services.s3.model.CORSConfiguration;
import software.amazon.awssdk.services.s3.model.PutBucketCorsRequest;
// snippet-end:[s3.java2.cors.import]

/**
 * Before running this Java V2 code example, set up your development environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */

public class S3Cors {

    public static void main (String[] args) {

        final String usage = "\n" +
            "Usage:\n" +
            "    <bucketName> <accountId> \n\n" +
            "Where:\n" +
            "    bucketName - The Amazon S3 bucket to upload an object into.\n" +
            "    accountId - The id of the account that owns the Amazon S3 bucket.\n" ;

        if (args.length != 2) {
            System.out.println(usage);
            System.exit(1);
        }

        String bucketName = args[0];
        String accountId = args[1];
        ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
        Region region = Region.US_EAST_1;
        S3Client s3 = S3Client.builder()
            .region(region)
            .credentialsProvider(credentialsProvider)
            .build();

       setCorsInformation(s3, bucketName, accountId);
       getBucketCorsInformation(s3, bucketName, accountId);
       deleteBucketCorsInformation(s3, bucketName, accountId);
       s3.close();
    }

    // snippet-start:[s3.java2.cors.main]
    public static void deleteBucketCorsInformation(S3Client s3, String bucketName, String accountId) {
        try {
            DeleteBucketCorsRequest bucketCorsRequest = DeleteBucketCorsRequest.builder()
                .bucket(bucketName)
                .expectedBucketOwner(accountId)
                .build();

            s3.deleteBucketCors(bucketCorsRequest) ;

        } catch (S3Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }

    public static void getBucketCorsInformation(S3Client s3, String bucketName, String accountId) {

        try {
            GetBucketCorsRequest bucketCorsRequest = GetBucketCorsRequest.builder()
                .bucket(bucketName)
                .expectedBucketOwner(accountId)
                .build();

            GetBucketCorsResponse corsResponse = s3.getBucketCors(bucketCorsRequest);
            List<CORSRule> corsRules = corsResponse.corsRules();
            for (CORSRule rule: corsRules) {
                System.out.println("allowOrigins: "+rule.allowedOrigins());
                System.out.println("AllowedMethod: "+rule.allowedMethods());
            }

        } catch (S3Exception e) {

            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }

    public static void setCorsInformation(S3Client s3, String bucketName, String accountId) {

        List<String> allowMethods = new ArrayList<>();
        allowMethods.add("PUT");
        allowMethods.add("POST");
        allowMethods.add("DELETE");

        List<String> allowOrigins = new ArrayList<>();
        allowOrigins.add("http://example.com");
        try {
            // Define CORS rules.
            CORSRule corsRule = CORSRule.builder()
                .allowedMethods(allowMethods)
                .allowedOrigins(allowOrigins)
                .build();

            List<CORSRule> corsRules = new ArrayList<>();
            corsRules.add(corsRule);
            CORSConfiguration configuration = CORSConfiguration.builder()
                .corsRules(corsRules)
                .build();

            PutBucketCorsRequest putBucketCorsRequest = PutBucketCorsRequest.builder()
                .bucket(bucketName)
                .corsConfiguration(configuration)
                .expectedBucketOwner(accountId)
                .build();

            s3.putBucketCors(putBucketCorsRequest);

        } catch (S3Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
    // snippet-end:[s3.java2.cors.main]
}


We're sorry to inform you that we will not be able to change your repayment date.
Are there any penalties for paying off my ZestMoney EMI early?
No. You can repay all or some of your outstanding balance at any time without penalty. The amount you repay will depend on the date of the month. Please call our helpline at 9343422556, and we will help you sort it out.


text:
Mon 1st December, 2014
Campaigners have urged the Government to abandon plans to introduce plain packaging of tobacco.
The smokers' group Forest which runs the Hands Off Our Packs campaign says the UK must learn from Australia where standardised packaging was introduced on 1st December 2012. New evidence, says Forest, suggests plain packaging will not reduce the number of teenagers who smoke. Instead of declining since the introduction of plain packaging, youth smoking rates have gone up.
According to the Australian Institute for Health and Welfare, youth smoking rates have increased by 36% in the period 2010-2013. [1] Plain packaging has had no impact on adults either. Monthly figures for the adult (18+) smoking rate are consistent with the long-term decline of smoking in Australia. Far from accelerating that decline, the trend for the year 2013 shows a 1.8% annual increase. [2]
Plain packaging is also fuelling the black market. In Australia in 2012 illicit tobacco stood at 11.5% of tobacco consumption. By mid-2014 it reached an unprecedented 14.3% share of the market, an increase of nearly 25%. [3]
Simon Clark, director of Forest, said: "Plain packaging hasn't worked. Youth smoking rates in Australia have gone up since it was introduced and illicit trade has soared. If alarm bells aren't ringing in Westminster they should be.
"Standardised packaging would be a huge risk with no beneficial effect. We urge the Government to learn from Australia's experience and abandon this ill-conceived and potentially costly measure."
[1] Australian Institute for Health and Welfare
[2] Roy Morgan Research. RMR is Australia's longest-established market research company with a strong reputation for reliability and accuracy. They are used and trusted by the Australian government (including Australia's Institute for Health and Welfare) and a wide range of businesses.
[3] KPMG Illicit tobacco in Australia, 2014 HY report, October 2014
[4] Official Australian Government figures show that the number of 12-17 year olds smoking every day has increased from 2.5 out of 100 (2010) to 3.4 out of 100 (2013) – National Drugs Strategy Household Survey. Plain packaging was introduced on 1st December 2012.
See also: Plain packaging – what happened next? (Institute of Economic Affairs)


But in reality, there are no words to adequately capture the beauty of this little gem, with its splendid panoramic position and its unspoiled, medieval Tuscan village structure, set apart from the usual tourist circuit and the chaos of modern life. Rigomagno is a small village where everything is cared for with attention, where even today one can have an authentic Tuscan experience in the colours of its streets, in the rush of water in the old, village washing troughs, in the taste of its oil, which is of such renown that Rigomagno is also known as the "Hill of Olives", or of its "ciambellino", a traditional sweet that's celebrated in the "Village Festival of the Ciambellino" and that is strictly homemade by the village women, who pass the recipe on from generation to generation.
and other, more ancient sounds, virtually lost today... .such as the tolling of village bells that still signal the passing of time.


Two of our authors, Tracey and Andrew Boynton, are in the news.
Purchase the Printed Book and receive the eBook today for only $1.
Why wait? Purchase the softcover book and the eBook and you'll get the eBook today. We'll send you the print book in the mail.
Buy all three historical biographies (What Really Happened in Ancient Times, What Really Happened During the Middle Ages and What Really Happened in Colonial Times) for only $35.00 - Save over 25%.
If you love history like I love history, then you will really enjoy this book. As the third book in the What Really Happened series, it delivers what you would expect – inspiring biographies, beautiful illustrations and great maps. Not only are the stories historically accurate, but they are lively and entertaining as well. Read this book aloud to your family and you will better understand this exciting time in history.
This is a MARVELOUS resource. I really appreciate all your hard work putting this together. May the Lord richly bless you for your kindness to the homeschool community!!!!!
Intrigued? Would you like to read one of the biographies from What Really Happened in Colonial Times with no obligation what so ever? Click on the button below to receive your free sample biography on one of the historical figures listed above. You will not be asked to enter credit card information as this is our free gift to you.


text:
<?php declare(strict_types=1);

namespace Demontpx\UtilBundle\Twig;

use Demontpx\UtilBundle\Intl\SimpleDateFormatter;
use PHPUnit\Framework\TestCase;
use Twig\TwigFilter;

class DateShortExtensionTest extends TestCase
{
    private SimpleDateFormatter $formatter;
    private DateShortExtension $extension;

    protected function setUp(): void
    {
        $this->formatter = new SimpleDateFormatter('en');
        $this->extension = new DateShortExtension($this->formatter);
    }

    /**
     * @dataProvider getDateShortData
     */
    public function testDateShort(string $expected, \DateTime $date)
    {
        $this->assertEquals($expected, $this->extension->dateShort($date));
    }

    public function getDateShortData()
    {
        $dayMonthData = ['Jan 1', new \DateTime('january 1')];
        if (date('m-d') == '01-01') {
            $dayMonthData = ['Jan 2', new \DateTime('january 2')];
        }

        return [
            ['9:59 PM', new \DateTime('21:59')],
            ['12:01 AM', new \DateTime('0:01')],
            $dayMonthData,
            ['9/23/13', new \DateTime('2013-09-23')],
        ];
    }

    /**
     * @dataProvider getDateShortHoverData
     */
    public function testDateShortHover(string $expected, \DateTime $date)
    {
        $this->assertStringStartsWith('<span title="' . $expected . '">', $this->extension->dateShortHover($date));
    }

    public function getDateShortHoverData()
    {
        return [
            ['Sunday, November 9, 2014, 7:58 PM', new \DateTime('2014-11-09 19:58:20')],
        ];
    }

    public function testGetFilters()
    {
        /** @var TwigFilter[] $filterList */
        $filterList = $this->extension->getFilters();

        $this->assertEquals('date_short', $filterList[0]->getName());
        $this->assertEquals([$this->extension, 'dateShort'], $filterList[0]->getCallable());

        $this->assertEquals('date_short_hover', $filterList[1]->getName());
        $this->assertEquals([$this->extension, 'dateShortHover'], $filterList[1]->getCallable());
    }
}


Potato salad can take many forms. It can be the cubed variety often found at American barbecues, the chunky variations served alongside German cuisine (potato salad is said to have originated in Germany), or even Gado Gado, which is a satay-laden Indonesian dish that technically could also be considered a potato salad.
It can be served warm or cold, as a side or as a main, but it usually consists of steamed potatoes and some sort of creamy and/or fatty element, often but not strictly mayonnaise. The rest can be left up to cook discretion and imagination. Which is why I felt compelled to present this less-than-conventional as my recipe for the week.
It may not neatly fall into any one cultural niche, but it took influence from Russian potato salads, which often contain a briny element (like pickles which I swapped for olives) and a meat (like diced ham which was substituted by small chunks of TVP). It features shredded as opposed to cubed potatoes–Not just because I prefer this texture but, frankly, because it makes this dish easier to cook. Meaning my Russian-inspired shredded potato salad can be whipped up in a matter of 30 minutes or less. Serve it alongside a veggie burger or perhaps some vegan meatballs and you've got yourself a well-balanced meal.
1. Use a cheese grater to shred potatoes, then add to saucepan and set on high heat.
2. Add TVP, 1.5 cups of water, salt and pepper and bring to a boil.
3. Once boiling, reduce heat and stir continuously until potatoes are soft, which should take about 15 minutes (If needed, add a bit more water to prevent sticking).
4. Transfer potatoes into bowl and let cool.
5. Slice olives in half and set aside.
6. Once potatoes have cooled, stir through mayonnaise and olives, then add breadcrumbs and serve once more.
7. Serve at room temperature or reheat if desired.


Roger, a good friend and an ethical individual, was at a business conference last week with a co-worker, Sam, who decided to take a few of his subordinates out for an evening of entertainment – entertainment not sanctioned by the company. The next day, as Sam was preparing to submit his receipts for his expense report, Roger noticed that he was submitting the receipts for his prior night's activities. More importantly, Roger noticed that Sam's description on the receipts was inaccurate. Sam flat-out lied on his expense report.
Roger wondered what would be the ethical thing to do. On one hand he could ignore what he saw and just let it pass, rationalizing that it was not his business. Or, he could confront Sam and encourage him to reconsider his choice, suggesting that following the ethics policy of his company would create better consequences. Or, lastly, Roger could comply with the company's guidelines and report the ethical lapse.
If you chose the third option – the one that is expected as part of compliance with most organizational ethics guidelines – you would be labeled a "whistleblower." Who wants to be called that? Snitch, tattletale and other negative words from childhood come to mind when someone is called a whistleblower. Yet, if your company or association is committed to creating a culture of ethical behavior, the term "whistleblower" is the number one key to ethical success.
How Can That Be? Statistics indicate that 42% of the time someone "tipping off" an employer about an ethical lapse or potential fraud is the number one way companies maintain ethics and prevent fraud. Amazing as it may seem, internal staff is the best police system for maintaining ethical behavior.
Most are amazed that it is that high; all too often we want to look the other way, or are afraid to confront those committing ethical blunders. It's easy to understand the hesitancy; many of us are afraid to rock the boat. Often, what we fail to realize is that the person committing an ethical blunder is putting the company in danger. So, how do we create a culture of ethical actions?
1. Recognize That Unethical Choices Never Start Large. The "Unethical Continuum" is a natural progression of what many call a "slippery slope" of human action. This progression allows small infractions to go unnoticed or unreported until the day people or companies are in the midst of a full-fledged ethics disaster. Sam didn't "intend" to act unethically; he felt that he was doing the right thing by treating his subordinates to something beyond the norm at the company function. His challenge was figuring out who would be responsible for the expense. The challenge with his ethical choice was a common problem: Rationalization.
2. Understand the Three Components of Human Behavior that Lead to Ethical Lapses. When a human makes a choice, any choice, there are typically three components that come together that allow a choice to be made and move forward: (1) need, (2) opportunity and (3) rationalization. While, as employers we have little control of an individual's need, we do have some level of control over opportunity to make ethical choices and how one might rationalize behavior.
3. Be Clear About what Ethical Behavior Looks Like. Large companies have clearly drafted ethics and compliance policies that employees are expected to understand and follow. The smaller the company, the less likely there will be a clearly written ethics policy. But large or small, the challenge for all companies is communication about what is acceptable and unacceptable. Creating an ethics policy and training it effectively are keys to exposing rationalization and improving ethical behavior within an organization.
4. Train, Train, Train! Let's be honest: most ethics training is boring! It centers on the rules and never gets to the heart of what motivates human behavior. And, frankly, if we don't understand what starts folks on that slippery slope downward into the unethical realm, then we miss the opportunity to change behavior before it is too late. Effective training should move beyond just what's included in the ethics and compliance policy and cover (a) why people make unethical choices (b) what can be done to prevent unethical choices and (c) what motivates our behavior. Telling someone what to do is far less effective than helping them see the value in consistently making ethical choices.
5. Encourage Accountability. What keeps people between the ethical lines is shared accountability. We are our brother's keeper. If one is to be kept within the ethical lines then we must not only have the road signs (ethics policy), but the practical means to correct behavior. As stated earlier, 42% of the time ethical blunders are reported by co-workers or those who witness the issue. And while "whistleblower" carries a negative connotation, the reality is someone who cares enough to call "foul" to unethical actions is the most valuable ethics asset and organization has.
When in Doubt, Do the Right Thing! Ethical missteps are all the same; they will eventually lead to a negative outcome. Little infractions that go undetected or unreported often lead to larger infractions until "unethical" becomes "illegal". Perhaps we should reframe or replace the word "whistleblower" with "ethical partner". One thing is certain: ethical choices are empowered choices and that is certainly one critical component of business success.


This archtop guitar, Esther, is built with different species of woods that our traditional model and it makes a big difference.
A massive maple table, a massive walnut back gives it a different tone and additional sound versatility.
Esther sounds are warm and velvety.
Two humbuckers on the table enrich the sound possibilities of the instrument.
It is equipped with our original "sabolovic" tailpiece, pickups on the table with their carved wooden rings, an adjustable tune'o'matic bridge.
Pickup: Jazz & Rock Benedetti with Vol & 2 Tone.
Listen to: 'In a sentimental mood' played by Sidney Rodrigues.


text:
.. _tutorial_install:

birdhouse installation
=======================

.. contents::
    :local:
    :depth: 2

.. warning:: This section is outdated ...

Birdhouse consists of several components like Malleefowl_ and Emu_. Each of them can be installed individually.
The installation is done using the Python-based build system :term:`Buildout`.
Most of the dependencies are maintained in the :term:`Anaconda Python distribution`.
For convenience, each birdhouse component has a :ref:`Makefile <bootstrap:makefile>`
to ease the installation so you don't need to know how to call the Buildout build tool.

.. _requirements:

Requirements
------------

Birdhouse uses :term:`Anaconda Python distribution` for most of the dependencies. If Anaconda is not already installed, it will be installed during the installation process. Anaconda has packages for Linux, MacOSX and Windows. But not all packages used by birdhouse are already available in the default package channel of Anaconda. The missing packages are supplied by birdhouse on :term:`Binstar`. But we currently maintain only packages for Linux 64-bit and partly for MacOSX.

So the short answer to the requirements is: **you need a Linux 64-bit installation**.

Birdhouse is currently used on Ubuntu 14.04 and CentOS 6.x. It should also work on Debian, LinuxMint and Fedora.

Birdhouse also installs a few system packages using `apt-get` on Debian based distributions and `yum` on RedHat/CentOS based distributions. For this you need a user account with `sudo` permissions. Installing system packages can be done in a separate step. So your installation user does not need any special permissions. All installed files will go into a birdhouse Anaconda environment in the home folder of the installation user.

Installing from source
----------------------

The installation of birdhouse components from source is done with some few commands. Here is an example for the Emu WPS service:

.. code-block:: sh

    $ git clone https://github.com/bird-house/emu.git
    $ cd emu
    $ make clean install
    $ make start
    $ firefox http://localhost:8094/wps

All the birdhouse components follow the same installation pattern. If you want to see all the options of the `Makefile` then type:

.. code-block:: sh

    $ make help

You will find more information about these options in the :ref:`Makefile documentation <bootstrap:makefile>`.

Read the documention of each birdhouse component for the details of the installation and how to configure the components. The :ref:`birdhouse bootstrap documentation <bootstrap:introduction>` gives some :ref:`examples <bootstrap:examples>` of the different ways of making the installation.

On the WPS client side we have:

* `Phoenix`_: a Pyramid web application.
* `Birdy`_: a simple WPS command line tool.

On the WPS server side we have:

* `Malleefowl`_: provides base WPS services to access data.
* `Flyingpigeon`_: provides WPS services for the climate impact community.
* `Hummingbird`_: provides WPS services for CDO and climate metadata checks.
* `Emu`_: just some WPS processes for testing.

Nginx, gunicorn and supervisor
------------------------------

Birdhouse sets up a :term:`PyWPS` server (and also the Phoenix web application) using :term:`Buildout`. We use the :term:`Gunicorn` HTTP application server (similar to Tomcat for Java servlet applications ) to run these web applications with the :term:`WSGI` interface. In front of the Gunicorn application server, we use the :term:`Nginx` HTTP server (similar to the Apache web server). All these web services are started/stopped and monitored by a :term:`Supervisor` service.

See the following image for how this looks like:

.. image:: _images/WsgiApp.png

When installing a birdhouse WPS service, you don't need to care about this setup. This is all done by Buildout and using some extensions provided by birdhouse.

The Makefile of a birdhouse application has convenience targets to start/stop a WPS service controlled by the Supervisor and to check the status:

.. code-block:: sh

    $ make start    # start wps service
    $ make stop     # stop wps service
    $ make status   # show status of wps service
    Supervisor status ...
    /home/pingu/.conda/envs/birdhouse/bin/supervisorctl status
    emu                              RUNNING   pid 25698, uptime 0:00:02
    malleefowl                       RUNNING   pid 25702, uptime 0:00:02
    mongodb                          RUNNING   pid 25691, uptime 0:00:02
    nginx                            RUNNING   pid 25699, uptime 0:00:02
    phoenix                          RUNNING   pid 25694, uptime 0:00:02
    pycsw                            RUNNING   pid 25700, uptime 0:00:02
    tomcat                           RUNNING   pid 25693, uptime 0:00:02

You can also use the Supervisor monitor web service which by default is available on port http://localhost:9001/. The Supervisor monitor app looks like in the following screenshot.

.. image:: _images/supervisor-monitor.png

.. _docker:

Using birdhouse with Docker
---------------------------

An alternative way to install and deploy birdhouse Web Processing Services is by using :term:`Docker`.
The birdhouse WPS servers are available as a Docker image on `Docker Hub <https://hub.docker.com/r/birdhouse/>`_.
See an example on how to use them with the :ref:`Emu WPS Docker image <emu:tutorial>`.


text:
"Bengal Tiger": My FT Review
Here's my FT review of "Bengal Tiger at the Baghdad Zoo," on Broadway with Robin Williams. Full review also after the jump.
The arrival on Broadway of Rajiv Joseph's Bengal Tiger at the
Baghdad Zoo provides at least three reasons for rejoicing. Its subject,
the war in Iraq, has been relegated to off-Broadway or, more often, to
off-off-Broadway; to explore the tragedy at the heart of theatreland is, at the very least, a strong reminder that the conflict's costs, as Joseph makes clear, persist long after the bodies are buried.
Further good news: unlike the brutal realism of many films about Iraq, Bengal Tiger's conception turns on the poetry of embodied metaphor. Two soldiers are ordered to guard the Baghdad zoo in 2003, and when one of them has a hand bitten off by a caged tiger, the other kills the beast. The tiger's magical spirit haunts the characters for much of the story.
A third hurrah: Robin Williams is back on Broadway, not in a comic
one-man show, his preferred mode when there, but in a proper play. He is the titular character (yes, the tiger) if not, perhaps disappointingly for the legions who have paid Broadway prices to see him act, the character with the most stage time.
If there are three cheers for its conception, this production, directed by Moisés Kaufman, also deserves at least one for execution: the two-hour evening is never dull. This is owing not to the story of the two soldiers – one of whom, portrayed by Brad Fleischer, succumbs to stress, while the other, portrayed by the generally sensitive actor Glenn Davis with atypical bluntness, returns to Iraq with a bionic hand – but to that of Musa, an Iraqi translator for the US military who used to be a topiarist in the Hussein family's gardens.
Far more than Williams's tiger, who wanders the stage cursing God and uttering philosophical banalities about carnage, Musa allows the playwright to explore the theme of the artist – of civilisation – bulldozed by the tanks of war. Alone among the ensemble, who enact their struggles against the backdrop of Derek McLane's giant-topiary set, Arian Moayed, as Musa, manages to suggest the layers of a tormented inner life.
Suicide, Robin Williams, New Movie
"Fences": My FT Review
Robin And Lauren Shared A Stage
"Life Of Pi" Movie: What I Thought


We're still waiting for our stuff to arrive by truck from Pittsburgh. These are mostly boat things and personal items, plus our bikes. And yes, we have too much stuff to fit on this boat without sinking it, but we had no idea when we started our search what kind of boat we'd end up with and what we'd need to outfit it for long-distance cruising.
Without our big load of possessions we moved onto the boat with just what we've been traveling with: a few changes of clothing, our computers, some books, the compact eating-on-the-road kit we've used for four months, a guitar, and of course Izzy and the full cat equipment package.
By the time we moved everything aboard and wandered around looking for the best places to stash things, it looked like we'd just about filled this thing up. The whole effect was enhanced by the fact that Danielle and Roger had apparently stocked the pantry with an eye toward another lap around the world. We think we can live off the food they left for months! What's even better is that the foods are from many of the countries they visited on their trip, so rooting through the cupboard is like reading a travelogue. There's honey from Australia, peas from Greece, tuna from Turkey. Good thing, too, since buying the boat put us on a beans and rice diet for a couple of months while our bank account recovers, and all these exotic goodies will keep us from dying of culinary boredom, not to mention remind us of the places we'll see on our own journey.
There's a bottle of drinking water with a label in a language we don't recognize. Can anyone tell us what it is?
I'll go out on a boom and say that the language is Thai. I've excluded Malaysian and Laotian because they both look dissimilar enough to what's printed on the bottle. Could be Cambodian, though. But based on pure, unfounded speculation that more boats sail and linger on the much longer Thai coastline than Cambodian coastline, I'll wager the bottle comes from Thailand.
Btw, been following your adventures from the start, and want to say "Way to go!" So happy for you that you've found your new home!
Ah, thanks, Tom. That makes sense that it would be Thailand. And thanks for the good wishes. We worked hard to get to this point and we can hardly believe we finally did it!
Marce, we have that collapsible pet crate for you if you have room and/or need for it. I look forward to your next visit and will enjoy reading of your journey in the meantime.
Have fun & stay safe!!!!


Now available on Steam from Piece of Cake Studios, Hacktag is co-op stealth game that features both solo and two-player modes.
The game is set in 2029 in a parallel world populated by cute, anthropomorphic animals and features two-player asymmetrical gameplay. One player is an Agent in the field while the other is a virtually-infiltrated Hacker. Hired as mercenaries by competing corporations, the two players work together to carry out espionage missions via online or local co-op. In single player mode, one player switches between the two roles.
Hacktag was first released on Steam Early Access in June 2017 and has been continually refined and expanded in keeping with community feedback. The game is now available as a full Steam game for $19.99, with a 25% launch week discount.


text:
Deadly Encounters
Release Date: 18th September 2000
17 illus.
Edition: New Edition
Two Victorian Sensations
Richard D. Altick
An evocative retelling ot two sensational crimes that rocked Victorian London.
In July 1861 London newspapers excitedly reported two violent crimes, both the stuff of sensational fiction. One involved a retired army major, his beautiful mistress and her illegitimate child, blackmail and murder. In the other, a French nobleman was accused of trying to kill his son in order to claim the young man's inheritance. The press covered both cases with thoroughness and enthusiasm, narrating events in a style worthy of a popular novelist, and including lengthy passages of testimony. Not only did they report rumor as well as what seemed to be fact, they speculated about the credibility of witnesses, assessed character, and decided guilt. The public was enthralled.
Richard D. Altick demonstrates that these two cases, as they were presented in the British press, set the tone for the Victorian "age of sensation." The fascination with crime, passion, and suspense has a long history, but it was in the 1860s that this fascination became the vogue in England. Altick shows that these crimes provided literary prototypes and authenticated extraordinary passion and incident in fiction with the "shock of actuality." While most sensational melodramas and novels were by lesser writers, authors of the stature of Dickens, Thackeray, George Eliot, Trollope, Hardy, and Wilkie Collins were also influenced by the spirit of the age and incorporated sensational elements in their work.
Richard D. Altick is Regents Professor of English, Emeritus, at Ohio State University. He is the author of many other books, among them Victorian Studies in Scarlet; Victorian People and Ideas; The Shows of London, A Panoramic History, 1600-1862; and Paintings from Books: Art and Literature in Britain 1760-1900.
"Altick's book vividly preserves an important and fascinating element of daily Victorian life. As such, it is the best sort of historical scholarship: the kind that puts us in close touch with a lost world and with people very much like ourselves."—Smithsonian
"An engaging study in historical sociology."—Washington Post


Act as a personable and helpful first contact for the users and partners, taking care to foster a positive customer relationship in every contact.
Assist in providing training and familiarizing new users with the product.
Assist in, and sometimes lead, the writing of product documentation.
Assist in setting up, and sometimes delivering, product demonstrations.
Assist in maintaining regular contacts with users to elicit feedback and encourage growth in the use of the product.
Provide detailed instructions on how to reproduce issues.
Monitor and analyze system performance and assist the development team with the resolution of performance issues.
Our client is the leading Dynamics NAV Partner in Eastern Canada and are offering a junior accountant/ ERP professional the opportunity to train into Dynamics NAV.
This is an amazing opportunity for an ambitious candidate who is looking to mark their stamp on a continuously growing and expanding Microsoft Partner. With extensive training on offer this is a fantastic opportunity for a junior ERP professional to continue to expand their skills or an accountant looking to move into more of an applications focused position.


TORRINGTON: I guess the only way you could describe it is scary. Really scary.
The Torrington High School baseball team is pounding out runs like they grow on that preverbal tree. Like they don't want to stop until their opposition cries uncle or develops a mercy rule.
Their latest victim, the Seymour Wildcats, came into Fuessenich Park with a 1-3 mark, left at 1-4 and will be happy not see the big ballpark for another year.
Running down balls in the gap or looking over the fence for a lost ball off a Raider bat is something the first three visitors to enter the "Jewell of Litchfield County" have gotten far too familiar with.
Three games, 39 runs, three straight wins.
21 hits and 19 runs on Wednesday, five of the hits and eight RBI's off the bat of just one player, sophomore Dom Sabia.
Every starter had a t least one hit, four had multiple hit games, two with multiple RBI days.
Their 19-5 final held a boat load of good things in it. Did I just state the obvious?
But yes, after beating Holy Cross on Monday by a 12-8 final, the home standing Raiders did fix a problem.
Let's go to where the problem started for the Wildcats on "Hump Day" first though.
Seymour actually held a 2-1 lead entering the bottom of the third before the wheels not only fell off the bus, nobody could find the remainder of the bus as well.
Nate Manchester (4-5, 4 runs, 4 RBI's) started things off with the first of four consecutive doubles. Seemed the Raiders preferred starting at second this day, they banged out a total of eight on the day.
Two-baggers by Jason Vinisko, Sabia and Ben Bonvicini got the ball rolling, the ball was the size of a small mountain by the time it stopped rolling, nine runs later.
Manchester would score twice in the frame and drive in three with a bases loaded triple in his second time around the merry-go-round.
After blasting their way to a now 10-2 lead after three, Torrington gave three right back to the Wildcats and the lead was within reach at 10-5.
On Monday, the Crusaders scored six runs over the last three innings after the home team had what you would have thought was a big lead.
Their head coach gathered the team after the big inning and implored them to not let down and although they did give up the trio of runs in the fourth, the door was shut after that.
It's a pick your poison for teams that take the diamond against the Raiders at this point. There are no automatic outs.
As for Sabia, high expectations came with the sophomore who is devoting all his energy to the diamond and on Wednesday, you saw how it has paid off.
After two doubles and a single got the easy part of the cycle out of the way, Sabia launched a long triple that scored a pair of runs in the fifth and himself scored on an error on a bobbled relay from the left center field fence.
In the sixth with the bases loaded, Sabia completed that unique baseball puzzle with a towering grand slam of the left center field fence.
It's clear this second year player is something else.
It's clear the offense is the story for the Raiders who started 2014 with a 0-3 mark and have quickly gotten themselves off to a fast start.
The Raiders head out on the road on Friday and Saturday to take on Kennedy and Derby, respectively before coming home to play Crosby on Monday. None of those teams have posted wins as of yet meaning Torrington could really race out to a great start if they take care of business.