@@ -3885,24 +3885,61 @@ namespace BasisClasses
3885
3885
3886
3886
// Sanity check
3887
3887
//
3888
+ if (tfinal == tinit) {
3889
+ throw std::runtime_error
3890
+ (" BasisClasses::IntegrateOrbits: tinit cannot be equal to tfinal" );
3891
+ }
3892
+
3893
+ if (h < 0.0 and tfinal > tinit) {
3894
+ throw std::runtime_error
3895
+ (" BasisClasses::IntegrateOrbits: tfinal must be smaller than tinit "
3896
+ " when step size is negative" );
3897
+ }
3898
+
3899
+ if (h > 0.0 and tfinal < tinit) {
3900
+ throw std::runtime_error
3901
+ (" BasisClasses::IntegrateOrbits: tfinal must be larger than "
3902
+ " tinit when step size is positive" );
3903
+ }
3904
+
3888
3905
if ( (tfinal - tinit)/h >
3889
3906
static_cast <double >(std::numeric_limits<int >::max ()) )
3890
3907
{
3891
- std::cout << " BasicFactor ::IntegrateOrbits: step size is too small or "
3892
- << " time interval is too large.\n " ;
3908
+ std::cout << " BasisClasses ::IntegrateOrbits: step size is too small or "
3909
+ << " time interval is too large." << std::endl ;
3893
3910
// Return empty data
3894
3911
//
3895
3912
return {Eigen::VectorXd (), Eigen::Tensor<float , 3 >()};
3896
3913
}
3897
3914
3898
3915
// Number of steps
3899
3916
//
3900
- int numT = floor ( (tfinal - tinit)/h );
3917
+ int numT = std::ceil ( (tfinal - tinit)/h + 0.5 );
3918
+
3919
+ // Want both end points in the output at minimum
3920
+ //
3921
+ numT = std::max (2 , numT);
3901
3922
3902
- // Compute output step
3923
+ // Number of output steps
3903
3924
//
3904
- nout = std::min<int >(numT, nout);
3905
- double H = (tfinal - tinit)/nout;
3925
+ int stride = 1 ; // Default stride
3926
+ if (nout>0 ) { // User has specified output count...
3927
+ nout = std::max (2 , nout);
3928
+ stride = std::ceil (static_cast <double >(numT)/static_cast <double >(nout));
3929
+ numT = (nout-1 ) * stride + 1 ;
3930
+ } else { // Otherwise, use the default output number
3931
+ nout = numT; // with the default stride
3932
+ }
3933
+
3934
+ // Compute the interval-matching step
3935
+ //
3936
+ h = (tfinal - tinit)/(numT-1 );
3937
+
3938
+ // DEBUG
3939
+ if (false )
3940
+ std::cout << " BasisClasses::IntegrateOrbits: choosing nout=" << nout
3941
+ << " numT=" << numT << " h=" << h << " stride=" << stride
3942
+ << std::endl;
3906
3943
3907
3944
// Return data
3908
3945
//
@@ -3912,10 +3949,10 @@ namespace BasisClasses
3912
3949
ret.resize (rows, 6 , nout);
3913
3950
}
3914
3951
catch (const std::bad_alloc& e) {
3915
- std::cout << " BasicFactor ::IntegrateOrbits: memory allocation failed: "
3952
+ std::cout << " BasisClasses ::IntegrateOrbits: memory allocation failed: "
3916
3953
<< e.what () << std::endl
3917
3954
<< " Your requested number of orbits and time steps requires "
3918
- << floor (8 .0 *rows*6 *nout/1e9 )+1 << " GB free memory"
3955
+ << std:: floor (4 .0 *rows*6 *nout/1e9 )+1 << " GB free memory"
3919
3956
<< std::endl;
3920
3957
3921
3958
// Return empty data
@@ -3927,27 +3964,37 @@ namespace BasisClasses
3927
3964
//
3928
3965
Eigen::VectorXd times (nout);
3929
3966
3930
- // Do the work
3967
+ // Assign the initial point
3931
3968
//
3932
3969
times (0 ) = tinit;
3933
3970
for (int n=0 ; n<rows; n++)
3934
3971
for (int k=0 ; k<6 ; k++) ret (n, k, 0 ) = ps (n, k);
3935
3972
3973
+ // Sign of h
3974
+ int sgn = (0 < h) - (h < 0 );
3975
+
3976
+ // Set the counters
3936
3977
double tnow = tinit;
3937
- for (int s=1 , cnt=1 ; s<numT; s++) {
3978
+ int s = 0 , cnt = 1 ;
3979
+
3980
+ // Do the integration using stride for output
3981
+ while (s++ < numT) {
3982
+ if ( (tfinal - tnow)*sgn < h*sgn) h = tfinal - tnow;
3938
3983
std::tie (tnow, ps) = OneStep (tnow, h, ps, accel, bfe, F);
3939
- if (tnow >= H*cnt-h* 1.0e-8 ) {
3984
+ if (cnt < nout and s % stride == 0 ) {
3940
3985
times (cnt) = tnow;
3941
3986
for (int n=0 ; n<rows; n++)
3942
3987
for (int k=0 ; k<6 ; k++) ret (n, k, cnt) = ps (n, k);
3943
3988
cnt += 1 ;
3944
3989
}
3945
3990
}
3946
3991
3992
+ // Corrects round off at end point
3993
+ //
3947
3994
times (nout-1 ) = tnow;
3948
3995
for (int n=0 ; n<rows; n++)
3949
3996
for (int k=0 ; k<6 ; k++) ret (n, k, nout-1 ) = ps (n, k);
3950
-
3997
+
3951
3998
return {times, ret};
3952
3999
}
3953
4000
0 commit comments