Implementing a Physical Units Library for C++
Total Page:16
File Type:pdf, Size:1020Kb
Implementing a Physical Units Library for C++ Mateusz Pusz April 12, 2019 Famous motivating example The Mars Climate Orbiter • Robotic space probe launched by NASA on December 11, 1998 ACCU 2019 | Implementing a Physical Units Library for C++ 3 The Mars Climate Orbiter • Robotic space probe launched by NASA on December 11, 1998 • Project costs: $327.6 million – spacecra development: $193.1 million – launching it: $91.7 million – mission operations: $42.8 million ACCU 2019 | Implementing a Physical Units Library for C++ 3 The Mars Climate Orbiter • Robotic space probe launched by NASA on December 11, 1998 • Project costs: $327.6 million – spacecra development: $193.1 million – launching it: $91.7 million – mission operations: $42.8 million • Mars Climate Orbiter began the planned orbital insertion maneuver on September 23, 1999 at 09:00:46 UTC ACCU 2019 | Implementing a Physical Units Library for C++ 3 The Mars Climate Orbiter • Space probe went out of radio contact when it passed behind Mars at 09:04:52 UTC, 49 seconds earlier than expected • Communication was never reestablished • The spacecra disintegrated due to atmospheric stresses ACCU 2019 | Implementing a Physical Units Library for C++ 6 What went wrong? ACCU 2019 | Implementing a Physical Units Library for C++ 7 What went wrong? • The primary cause of this discrepancy was that – one piece of ground soware supplied by Lockheed Martin produced results in a United States customary unit, contrary to its Soware Interface Specification (SIS) – second system, supplied by NASA, expected those results to be in SI units, in accordance with the SIS ACCU 2019 | Implementing a Physical Units Library for C++ 7 What went wrong? • The primary cause of this discrepancy was that – one piece of ground soware supplied by Lockheed Martin produced results in a United States customary unit, contrary to its Soware Interface Specification (SIS) – second system, supplied by NASA, expected those results to be in SI units, in accordance with the SIS • Specifically – soware that calculated the total impulse produced by thruster firings calculated results in pound- seconds – the trajectory calculation soware then used these results to update the predicted position of the spacecra and expected it to be in newton-seconds ACCU 2019 | Implementing a Physical Units Library for C++ 7 Human error occurs all the time Human error occurs all the time. But even so we have a tremendous success rate because we have systems that detect and correct the errors. The problem here is that our system failed to do that. -- Carl Pilcher science director at NASA ACCU 2019 | Implementing a Physical Units Library for C++ 9 ANOTHER EXAMPLE Why do I care? A long time ago in a galaxy far far away... ACCU 2019 | Implementing a Physical Units Library for C++ 11 A long time ago in a galaxy far far away... ACCU 2019 | Implementing a Physical Units Library for C++ 11 Tactical Flight Computer ACCU 2019 | Implementing a Physical Units Library for C++ 12 Tactical Flight Computer ACCU 2019 | Implementing a Physical Units Library for C++ 13 What is the correct order? void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing); ACCU 2019 | Implementing a Physical Units Library for C++ 14 What is the correct order? void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing); void FindLatitudeLongitude(double Lat, double Lon, double Bearing, double Distance, double *lat_out, double *lon_out); ACCU 2019 | Implementing a Physical Units Library for C++ 14 What is the correct order? void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing); void FindLatitudeLongitude(double Lat, double Lon, double Bearing, double Distance, double *lat_out, double *lon_out); ACCU 2019 | Implementing a Physical Units Library for C++ 14 double - an ultimate type to express quantity double GlidePolar::MacCreadyAltitude(double emcready, double Distance, const double Bearing, const double WindSpeed, const double WindBearing, double *BestCruiseTrack, double *VMacCready, const bool isFinalGlide, double *TimeToGo, const double AltitudeAboveTarget, const double cruise_efficiency, const double TaskAltDiff); ACCU 2019 | Implementing a Physical Units Library for C++ 15 We shouldn't write the code like that anymore // Air Density(kg/m3) from relative humidity(%), // temperature(°C) and absolute pressure(Pa) double AirDensity(double hr, double temp, double abs_press) { return (1/(287.06*(temp+273.15))) * (abs_press - 230.617 * hr * exp((17.5043*temp)/(241.2+temp))); } ACCU 2019 | Implementing a Physical Units Library for C++ 16 DID YOU EVER HAVE TO WRITE THE CODE THIS WAY? ACCU 2019 | Implementing a Physical Units Library for C++ 17 Why do we write our code this way? ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way? • No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way? • No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries oen not allowed in production code ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way? • No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries oen not allowed in production code • Implementing a good library by ourselves is hard ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way? • No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries oen not allowed in production code • Implementing a good library by ourselves is hard Let's do something about that! ACCU 2019 | Implementing a Physical Units Library for C++ 18 TERMS AND DEFINITIONS ACCU 2019 | Implementing a Physical Units Library for C++ 19 International System of Units (SI) • 7 base units • 22 named units • 20 prefixes to the unit names and unit symbols ACCU 2019 | Implementing a Physical Units Library for C++ 20 SI Base Units QUANTITY DIMENSION SYMBOL UNIT SYMBOL UNIT NAME time T s second length L m metre mass M kg kilogram electric current I A ampere thermodynamic temperature Θ K kelvin amount of substance N mol mole luminous intensity J cd candela ACCU 2019 | Implementing a Physical Units Library for C++ 21 Examples of SI derived units expressed in SI Based Units QUANTITY DIMENSION SYMBOL UNIT SYMBOL UNIT NAME area A m2 square metre volume V m3 cubic metre −1 velocity v m⋅ s metre per second −2 acceleration a m⋅ s metre per second squared −3 density ρ kg⋅ m kilogram per cubic metre −1 magnetic field strength H A⋅ m ampere per metre −2 luminance Lv cd⋅ m candela per square metre ACCU 2019 | Implementing a Physical Units Library for C++ 22 Examples of SI derived units with special name QUANTITY UNIT SYMBOL UNIT NAME IN OTHER SI UNITS IN SI BASE UNITS frequency Hz hertz --- s-1 -2 force N newton --- kg⋅ m⋅ s 2 −1 −2 preassure Pa pascal N/m kg⋅ m ⋅ s 2 −2 ⋅ energy J joule N m kg⋅ m ⋅ s 2 −3 power W watt J/s kg⋅ m ⋅ s electric charge C coulomb --- s⋅ A 2 −3 −1 voltage V volt W/A kg⋅ m ⋅ s ⋅ A −1 −2 4 2 capacitance F farad C/V kg ⋅ m ⋅ s ⋅ A 2 −3 −2 resistance Ω ohm V/A kg⋅ m ⋅ s ⋅ A ACCU 2019 | Implementing a Physical Units Library for C++ 23 Dimensional Analysis Power = Energy / Time ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis Power = Energy / Time • W ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis Power = Energy / Time • W • J/s ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis Power = Energy / Time • W • J/s • N⋅ m/s −2 • kg⋅ m⋅ s ⋅ m/s 2 −2 • kg⋅ m ⋅ s /s 2 −3 • kg⋅ m ⋅ s ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis // simple numeric operations static_assert(10_km / 2 == 5_km); ACCU 2019 | Implementing a Physical Units Library for C++ 25 Dimensional Analysis // simple numeric operations static_assert(10_km / 2 == 5_km); // unit conversions static_assert(1_h == 3600_s); static_assert(1_km + 1_m == 1001_m); ACCU 2019 | Implementing a Physical Units Library for C++ 25 Dimensional Analysis // simple numeric operations static_assert(10_km / 2 == 5_km); // unit conversions static_assert(1_h == 3600_s); static_assert(1_km + 1_m == 1001_m); // dimension conversions static_assert(1_km / 1_s == 1000_mps); static_assert(2_kmph * 2_h == 4_km); static_assert(2_km / 2_kmph == 1_h); static_assert(1000 / 1_s == 1_kHz); static_assert(10_km / 5_km == 2); ACCU 2019 | Implementing a Physical Units Library for C++ 25 SI prexes template<intmax_t Num, intmax_t Den = 1> struct ratio; ACCU 2019 | Implementing a Physical Units Library