Example #1
0
  // Compute and log the measured periods of the moons.
  void LogPeriods(Ephemeris<KSP> const& ephemeris) {
    auto const position = [this, &ephemeris](
        not_null<MassiveBody const*> body, Instant const& t) {
      return ephemeris.trajectory(body)->EvaluatePosition(t, nullptr);
    };
    auto const barycentre = [this, &position](Instant const& t) {
      BarycentreCalculator<Position<KSP>, Mass> result;
      for (auto const body : jool_system_) {
        result.Add(position(body, t), body->mass());
      }
      return result.Get();
    };
    auto const barycentric_position =
        [this, &barycentre, &ephemeris, &position](
        not_null<MassiveBody const*> body,
        Instant const& t) {
      return position(body, t) - barycentre(t);
    };

    for (auto const moon : {laythe_, vall_, tylo_}) {
      auto const moon_y =
          [this, &barycentric_position, moon](Instant const& t) {
        return barycentric_position(moon, t).coordinates().y;
      };

      LOG(INFO) << (moon == laythe_ ? "Laythe" : moon == vall_ ? "Vall"
                                                               : "Tylo");

      Sign const s0(moon_y(game_epoch_));
      Instant t0 = game_epoch_;
      Time const Δt = 45 * Minute;
      while (Sign(moon_y(t0)) == s0) {
        t0 += Δt;
      }
      // The moon crosses the xz plane between t0 and t0 - Δt.
      Instant t1 = t0;
      int const orbits = moon == laythe_ ? 8 : moon == vall_ ? 4 : 2;
      for (int i = 0; i < orbits; ++i) {
        while (Sign(moon_y(t1)) != s0) {
          t1 += Δt;
        }
        // The crossing of the xz plane halfway through the orbit occurs between
        // t1 and t1 - Δt.
        while (Sign(moon_y(t1)) == s0) {
          t1 += Δt;
        }
        // The |i|th orbit ends between t1 and t1 - Δt.
      }
      Time const actual_period =
          (Bisect(moon_y, t1 - Δt, t1) - Bisect(moon_y, t0 - Δt, t0)) / orbits;
      Time const expected_period = (2 * π * Radian) /
                                   *elements_[moon].mean_motion;
      LOG(INFO) << "actual period   : " << actual_period;
      LOG(INFO) << "expected period : " << expected_period;
      LOG(INFO) << "error           : "
                << RelativeError(expected_period, actual_period);
    }
  }
//----------------------------------------------------------------------
box observer::SIVIA(box& X0,box& Psecours)	{
        int NbissectMax = N_Bissect_0;
	if (phase==0) NbissectMax=N_Bissect_0;
	if (phase==1) NbissectMax=N_Bissect_k;
	int Nbissect=0;
	Psecours = box(4);Psecours[1] = 5;Psecours[2] = 5;Psecours[3] = 0;Psecours[4] = 0;
	vector<box> Result;
	list<box> L;
	L.push_back(X0);
	box P;
	//Form1->R1.image->Refresh();
	while (!L.empty())	{
		P=L.front();
		//Form1->R1.DrawCadre(P,clBlue,psSolid,1,2,1);
		L.pop_front();
		bool sortie=false;
		while (!sortie)	{
			box Pold(P);
			Contract(P);
			if (P.IsEmpty()) sortie=true;
			if (decrease(Pold,P)<0.05) sortie=true;
		}
		if (!P.IsEmpty())	{
			if (Nbissect>NbissectMax)	{
				//Form1->R1.DrawBox(P,clRed,clRed,bsSolid,1,2);
				//Form1->R2.image->Refresh();
				Result.push_back(P);
			}
			else	{
				box P1,P2;
				Bisect(P,P1,P2);
                                Psecours=P;
				Nbissect++;
				L.push_back(P1);
				L.push_back(P2);
			}
		}
	}
	box R=Union(Result);
	//Form1->R1.DrawCadre(R,clGreen,psSolid,1,2,1);
	L.clear();

	return R;
}
// Solving Δt * Δt == n.
TEST_F(RootFindersTest, SquareRoots) {
  Instant const t_0;
  Instant const t_max = t_0 + 10 * Second;
  Length const n_max = Pow<2>(t_max - t_0) * SIUnit<Acceleration>();
  for (Length n = 1 * Metre; n < n_max; n += 1 * Metre) {
    int evaluations = 0;
    auto const equation = [t_0, n, &evaluations](Instant const& t) {
      ++evaluations;
      return Pow<2>(t - t_0) * SIUnit<Acceleration>() - n;
    };
    EXPECT_THAT(Bisect(equation, t_0, t_max) - t_0,
                AlmostEquals(Sqrt(n / SIUnit<Acceleration>()), 0, 1));
    if (n == 25 * Metre) {
      EXPECT_EQ(3, evaluations);
    } else {
      EXPECT_THAT(evaluations, AllOf(Ge(49), Le(58)));
    }
  }
}
Example #4
0
std::unique_ptr<bsp_tree_node> GenerateTreeRecursion(std::vector<pcs_polygon> &polygons, std::vector<int>&contained)
{
	PCS_Model::BSP_CUR_DEPTH++;
	if(PCS_Model::BSP_MAX_DEPTH < PCS_Model::BSP_CUR_DEPTH)
		PCS_Model::BSP_MAX_DEPTH = PCS_Model::BSP_CUR_DEPTH;
	if (PCS_Model::BSP_CUR_DEPTH > 500)
	{
		PCS_Model::BSP_COMPILE_ERROR = true;
		return std::unique_ptr<bsp_tree_node>((bsp_tree_node*)NULL); //WHOA wtf infinite recursion!
	}
	std::unique_ptr<bsp_tree_node> node(new bsp_tree_node);
	MakeBound(node->bound_max, node->bound_min, contained, polygons);
	if (contained.size() == 1)
	{
		//we're a polygon.. w00t
		node->Type = POLY;
		node->poly_num = contained;
	}
	else
	{
		// we're a sortnorm
		vector3d cmax = polygons[contained[0]].centeroid;
		vector3d cmin = polygons[contained[0]].centeroid;
		for (std::vector<int>::iterator it = contained.begin() + 1; it < contained.end(); ++it) {
			ExpandBoundingBoxes(cmax, cmin, polygons[*it].centeroid);
		}
		std::vector<int> front, back;
		if (!Bisect(cmax, cmin, node->point, node->normal, polygons, contained, front, back)) {
			node->Type = POLY;
			node->poly_num = contained;
		} else {
			node->Type = SPLIT;
			node->front = GenerateTreeRecursion(polygons, front);
			node->back = GenerateTreeRecursion(polygons, back);
		}
	}
	PCS_Model::BSP_CUR_DEPTH--;
	return node;
}
Example #5
0
//===========================================================================
int CheckBorders(int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri)
{
	int border;
	int i, j, k0, k1, N;
	float angle[3];
	TRI *Tri;

	N = NumNodesUsed[0];
	Tri = *pTri;
	for(i=0; i<NumTris[0]; i++)
	{
		EdgeOnSide(Tri[i].v,&k0,&border);
		if(border < 0) continue;
		CalcAngles(Node, Tri[i].v, angle);
		k1 = (k0+1) % 3;
		if((angle[k0] < SLIVER_ANGLE) || (angle[k1] < SLIVER_ANGLE))
		{
			j = Bisect(Node, border, Tri[i].v[k0], Tri[i].v[k1]);
			if(j >= 0)
			{
				if(!Node[j].used)    // Shouldn't be used, but...
				{
					NumNodesUsed[0]++;
					Node[j].used++;
				}
			}
		}
	}
	if(NumNodesUsed[0] > N)
	{
		free(*pTri);
		tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY");
		Tri = *pTri;
	}
	return (NumNodesUsed[0] - N);
}
Example #6
0
double TTDigest::GetQuantile(const double& Q) const {
	double Left = Min;
	double Right = Max;

	if (TotalSum == 0.0) { return -1.0; }
	if (Q <= 0) { return Min; }
	if (Q >= 1) { return Max; }
	if (Last == 0) { return Mean[0]; }

	// calculate boundaries, pick centroid via binary search
	double QSum = Q * TotalSum;

	int N1 = Last + 1;
	int N0 = 0;
	int I = Bisect(MergeMean, QSum, N0, N1);

	if (I > 0) {
		Left = Boundary(I-1, I, Mean, Weight);
	}
	if (I < Last) {
		Right = Boundary(I, I+1, Mean, Weight);
	}
	return Left + (Right - Left) * (QSum - (MergeMean[I-1])) / Weight[I];
};
inline void
NestedDissectionRecursion
( const Graph& graph, 
  const vector<Int>& perm,
        Separator& sep, 
        NodeInfo& node,
        Int off, 
  const BisectCtrl& ctrl )
{
    DEBUG_CSE
    const Int numSources = graph.NumSources();
    const Int* offsetBuf = graph.LockedOffsetBuffer();
    const Int* sourceBuf = graph.LockedSourceBuffer();
    const Int* targetBuf = graph.LockedTargetBuffer();
    if( numSources <= ctrl.cutoff )
    {
        // Filter out the graph of the diagonal block
        Int numValidEdges = 0;
        const Int numEdges = graph.NumEdges();
        for( Int e=0; e<numEdges; ++e )
            if( targetBuf[e] < numSources )
                ++numValidEdges;
        vector<Int> subOffsets(numSources+1), subTargets(Max(numValidEdges,1));
        Int sourceOff = 0;
        Int validCounter = 0;
        Int prevSource = -1;
        for( Int e=0; e<numEdges; ++e )
        {
            const Int source = sourceBuf[e]; 
            const Int target = targetBuf[e];
            while( source != prevSource )
            {
                subOffsets[sourceOff++] = validCounter;
                ++prevSource;
            }
            if( target < numSources )
                subTargets[validCounter++] = target;
        }
        while( sourceOff <= numSources )
        { subOffsets[sourceOff++] = validCounter; }

        // Technically, SuiteSparse expects column-major storage, but since
        // the matrix is structurally symmetric, it's okay to pass in the 
        // row-major representation
        vector<Int> amdPerm;
        AMDOrder( subOffsets, subTargets, amdPerm );

        // Compute the symbolic factorization of this leaf node using the
        // reordering just computed
        node.LOffsets.resize( numSources+1 );
        node.LParents.resize( numSources );
        vector<Int> LNnz( numSources ), Flag( numSources ), 
                    amdPermInv( numSources );
        suite_sparse::ldl::Symbolic 
        ( numSources, subOffsets.data(), subTargets.data(), 
          node.LOffsets.data(), node.LParents.data(), LNnz.data(),
          Flag.data(), amdPerm.data(), amdPermInv.data() );

        // Fill in this node of the local separator tree
        sep.off = off;
        sep.inds.resize( numSources );
        for( Int i=0; i<numSources; ++i )
            sep.inds[i] = perm[amdPerm[i]];
        // TODO: Replace with better deletion mechanism
        SwapClear( sep.children );

        // Fill in this node of the local elimination tree
        node.size = numSources;
        node.off = off;
        // TODO: Replace with better deletion mechanism
        SwapClear( node.children );
        set<Int> lowerStruct;
        for( Int s=0; s<node.size; ++s )
        {
            const Int edgeOff = offsetBuf[s];
            const Int numConn = offsetBuf[s+1] - edgeOff;
            for( Int t=0; t<numConn; ++t )
            {
                const Int target = targetBuf[edgeOff+t];
                if( target >= numSources )
                    lowerStruct.insert( off+target );
            }
        }
        CopySTL( lowerStruct, node.origLowerStruct );
    }
    else
    {
        DEBUG_ONLY(
          if( !IsSymmetric(graph) )
          {
              Print( graph, "graph" );
              LogicError("Graph was not symmetric");
          }
        )

        // Partition the graph and construct the inverse map
        Graph leftChild, rightChild;
        vector<Int> map;
        const Int sepSize = Bisect( graph, leftChild, rightChild, map, ctrl );
        vector<Int> invMap( numSources );
        for( Int s=0; s<numSources; ++s )
            invMap[map[s]] = s;

        DEBUG_ONLY(
          if( !IsSymmetric(leftChild) )
          {
              Print( graph, "graph" );
              Print( leftChild, "leftChild" );
              LogicError("Left child was not symmetric");
          }
        )
inline void
NestedDissectionRecursion
( const DistGraph& graph, 
  const DistMap& perm,
        DistSeparator& sep, 
        DistNodeInfo& node,
        Int off, 
  const BisectCtrl& ctrl )
{
    DEBUG_ONLY(CSE cse("ldl::NestedDissectionRecursion"))
    mpi::Comm comm = graph.Comm();
    const int commSize = mpi::Size(comm);

    mpi::Dup( comm, sep.comm );
    mpi::Dup( comm, node.comm );

    if( commSize > 1 )
    {
        const Int numLocalSources = graph.NumLocalSources();
        const Int firstLocalSource = graph.FirstLocalSource();
        const Int* offsetBuf = graph.LockedOffsetBuffer();
        const Int* targetBuf = graph.LockedTargetBuffer();

        // Partition the graph and construct the inverse map
        DistGraph child;
        bool childIsOnLeft;
        DistMap map;
        const Int sepSize = Bisect( graph, child, map, childIsOnLeft, ctrl );
        const Int numSources = graph.NumSources();
        const Int childSize = child.NumSources();
        const Int leftChildSize = 
            ( childIsOnLeft ? childSize : numSources-sepSize-childSize );

        DistMap invMap;
        InvertMap( map, invMap );

        // Mostly fill this node of the DistSeparatorTree
        // (we will finish computing the separator indices at the end)
        sep.off = off + (numSources-sepSize);
        sep.inds.resize( sepSize );
        for( Int s=0; s<sepSize; ++s )
            sep.inds[s] = s + (numSources-sepSize);
        invMap.Translate( sep.inds );

        // Fill in this node of the DistNode
        node.size = sepSize;
        node.off = sep.off;

        set<Int> localLowerStruct;
        for( Int s=0; s<sepSize; ++s )
        {
            const Int source = sep.inds[s];
            if( source >= firstLocalSource && 
                source < firstLocalSource+numLocalSources )
            {
                const Int localSource = source - firstLocalSource;
                const Int edgeOff = offsetBuf[localSource];
                const Int numConn = offsetBuf[localSource+1] - edgeOff;
                for( Int t=0; t<numConn; ++t )
                {
                    const Int target = targetBuf[edgeOff+t];
                    if( target >= numSources )
                        localLowerStruct.insert( off+target );
                }
            }
        }
        const int numLocalConnected = localLowerStruct.size();
        vector<int> localConnectedSizes( commSize );
        mpi::AllGather
        ( &numLocalConnected, 1, localConnectedSizes.data(), 1, comm );
        vector<Int> localConnectedVec;
        CopySTL( localLowerStruct, localConnectedVec );
        vector<int> localConnectedOffs;
        const int sumOfLocalConnectedSizes = 
            Scan( localConnectedSizes, localConnectedOffs );
        vector<Int> localConnections( sumOfLocalConnectedSizes );
        mpi::AllGather
        ( localConnectedVec.data(), numLocalConnected,
          localConnections.data(), 
          localConnectedSizes.data(), localConnectedOffs.data(), comm );
        set<Int> lowerStruct
        ( localConnections.begin(), localConnections.end() );
        CopySTL( lowerStruct, node.origLowerStruct );

        // Finish computing the separator indices
        perm.Translate( sep.inds );

        // Construct map from child indices to the original ordering
        DistMap newPerm( child.NumSources(), child.Comm() );
        const Int localChildSize = child.NumLocalSources();
        const Int firstLocalChildSource = child.FirstLocalSource();
        auto& newPermLoc = newPerm.Map();
        if( childIsOnLeft )
            for( Int s=0; s<localChildSize; ++s )
                newPermLoc[s] = s+firstLocalChildSource;
        else
            for( Int s=0; s<localChildSize; ++s )
                newPermLoc[s] = s+firstLocalChildSource+leftChildSize;
        invMap.Extend( newPerm );
        perm.Extend( newPerm );

        // Recurse
        const Int childOff = ( childIsOnLeft ? off : off+leftChildSize );
        sep.child = new DistSeparator(&sep);
        node.child = new DistNodeInfo(&node);
        node.child->onLeft = childIsOnLeft;
        NestedDissectionRecursion
        ( child, newPerm, *sep.child, *node.child, childOff, ctrl );
    }
    else
    {
        Graph seqGraph( graph );

        sep.duplicate = new Separator(&sep);
        node.duplicate = new NodeInfo(&node);

        NestedDissectionRecursion
        ( seqGraph, perm.Map(), *sep.duplicate, *node.duplicate, off, ctrl );

        // Pull information up from the duplicates
        sep.off = sep.duplicate->off;
        sep.inds = sep.duplicate->inds;
        node.size = node.duplicate->size;
        node.off = node.duplicate->off;
        node.origLowerStruct = node.duplicate->origLowerStruct;
    }
}
Example #9
0
void Ephemeris<Frame>::ComputeApsides(not_null<MassiveBody const*> const body1,
                                      not_null<MassiveBody const*> const body2,
                                      DiscreteTrajectory<Frame>& apoapsides1,
                                      DiscreteTrajectory<Frame>& periapsides1,
                                      DiscreteTrajectory<Frame>& apoapsides2,
                                      DiscreteTrajectory<Frame>& periapsides2) {
  not_null<ContinuousTrajectory<Frame> const*> const body1_trajectory =
      trajectory(body1);
  not_null<ContinuousTrajectory<Frame> const*> const body2_trajectory =
      trajectory(body2);
  typename ContinuousTrajectory<Frame>::Hint hint1;
  typename ContinuousTrajectory<Frame>::Hint hint2;

  // Computes the derivative of the squared distance between |body1| and |body2|
  // at time |t|.
  auto const evaluate_square_distance_derivative =
      [body1_trajectory, body2_trajectory, &hint1, &hint2](
          Instant const& t) -> Variation<Square<Length>> {
    DegreesOfFreedom<Frame> const body1_degrees_of_freedom =
        body1_trajectory->EvaluateDegreesOfFreedom(t, &hint1);
    DegreesOfFreedom<Frame> const body2_degrees_of_freedom =
        body2_trajectory->EvaluateDegreesOfFreedom(t, &hint2);
    RelativeDegreesOfFreedom<Frame> const relative =
        body1_degrees_of_freedom - body2_degrees_of_freedom;
    return 2.0 * InnerProduct(relative.displacement(), relative.velocity());
  };

  std::experimental::optional<Instant> previous_time;
  std::experimental::optional<Variation<Square<Length>>>
      previous_squared_distance_derivative;

  for (Instant time = t_min(); time <= t_max(); time += parameters_.step()) {
    Variation<Square<Length>> const squared_distance_derivative =
        evaluate_square_distance_derivative(time);
    if (previous_squared_distance_derivative &&
        Sign(squared_distance_derivative) !=
            Sign(*previous_squared_distance_derivative)) {
      CHECK(previous_time);

      // The derivative of |squared_distance| changed sign.  Find its zero by
      // bisection, this is the time of the apsis.  Then compute the apsis and
      // append it to one of the output trajectories.
      Instant const apsis_time = Bisect(evaluate_square_distance_derivative,
                                        *previous_time,
                                        time);
      DegreesOfFreedom<Frame> const apsis1_degrees_of_freedom =
          body1_trajectory->EvaluateDegreesOfFreedom(apsis_time, &hint1);
      DegreesOfFreedom<Frame> const apsis2_degrees_of_freedom =
          body2_trajectory->EvaluateDegreesOfFreedom(apsis_time, &hint2);
      if (Sign(squared_distance_derivative).Negative()) {
        apoapsides1.Append(apsis_time, apsis1_degrees_of_freedom);
        apoapsides2.Append(apsis_time, apsis2_degrees_of_freedom);
      } else {
        periapsides1.Append(apsis_time, apsis1_degrees_of_freedom);
        periapsides2.Append(apsis_time, apsis2_degrees_of_freedom);
      }
    }

    previous_time = time;
    previous_squared_distance_derivative = squared_distance_derivative;
  }
}