Search code examples
c++boosttimeboost-units

Computations using derived units


I used this approach in order to define a new derived dimension mass flow which should have units kg / s:

include

#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>
#include <boost/units/systems/si/prefixes.hpp>    

namespace Units
{
  using namespace boost::units;

  namespace SI
  {
    using namespace boost::units::si;
  }

  template <class U> using Quantity = quantity<U>;

  typedef Quantity<SI::time> Time;
  typedef Quantity<SI::mass> Mass;

  typedef Units::derived_dimension<Units::mass_base_dimension, 1,
                                   Units::time_base_dimension, -1>::type MassFlowDimension;

  typedef Quantity<MassFlowDimension> MassFlowRate;

  BOOST_UNITS_STATIC_CONSTANT(kilogram_per_seconds, MassFlowRate);
}

I would have thought that conversion from / to existing base units would work out of the box, but apparently this is not the case:

int main()
{
  // does work
  Units::MassFlowRate mass_flow = 1.0*(Units::kilogram_per_seconds);

  // does not work
  Units::MassFlowRate other_mass_flow = 1.0*(Units::SI::kilogram / Units::SI::second);

  // does not work either
  Units::Mass total_flow = mass_flow * (1.0*Units::SI::second);
}

I would like to use the derived dimension to define quantities which integrate into the existing framework. Do I have to call some macro in order to make it possible to convert to / from existing units?

Edit: The error messages are the following:

main.cc:39:44: error: conversion from ‘boost::units::multiply_typeof_helper<double, boost::units::unit<boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-1> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10, boost::units::static_rational<3> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > >, void> >::type {aka boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-1> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10, boost::units::static_rational<3> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > >, void>, double>}’ to non-scalar type ‘Units::MassFlowRate {aka boost::units::quantity<boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-1> >, boost::units::dimensionless_type> >, double>}’ requested
   Units::MassFlowRate other_mass_flow = 1.0*(Units::SI::kilogram / Units::SI::second);

main.cc:39:38: error: conversion from ‘boost::units::multiply_typeof_helper<boost::units::quantity<boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-1> >, boost::units::dimensionless_type> >, double>, boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<1> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10, boost::units::static_rational<3> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > > >, double> >::type {aka boost::units::quantity<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<1> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10, boost::units::static_rational<3> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > > >, boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-1> >, boost::units::dimensionless_type> > >, double>}’ to non-scalar type ‘Units::Mass {aka boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10, boost::units::static_rational<3> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > > >, double>}’ requested
   Units::Mass total_flow = mass_flow * (1.0*Units::SI::second);

Solution

  • You're confusing units, dimensions and quantities.

    • This is your dimension,

      typedef Units::derived_dimension<Units::mass_base_dimension, 1,
                                       Units::time_base_dimension, -1>::type MassFlowDimension;
      

      You can't create a quantity from a dimension:

      typedef Quantity<MassFlowDimension> MassFlowRate;
      

      Instead create a unit first, and then a dimension from it:

    • Your constant is supposed to be a Unit constant, not a quantity:

      typedef Quantity<MassFlowDimension> MassFlowRate;
      BOOST_UNITS_STATIC_CONSTANT(kilogram_per_seconds, MassFlowRate);
      

    Fixed

    Live On Coliru

    #include <boost/units/io.hpp>
    #include <boost/units/systems/si.hpp>
    #include <boost/units/systems/si/io.hpp>
    
    namespace Units {
        using namespace boost::units;
        namespace SI = boost::units::si;
    
        template <class U> using Quantity = quantity<U>;
    
        typedef quantity<si::mass> Mass;
        typedef quantity<si::time> Time;
    
        typedef derived_dimension<mass_base_dimension, 1, time_base_dimension, -1>::type MassFlowDimension;
        typedef unit<MassFlowDimension, si::system> MassFlow;
        typedef Quantity<MassFlow> MassFlowRate;
        BOOST_UNITS_STATIC_CONSTANT(kilogram_per_seconds, MassFlow);
    }
    
    #include <iostream>
    int main() {
        Units::MassFlowRate const mass_flow       = 7.0*Units::kilogram_per_seconds;
        Units::MassFlowRate const other_mass_flow = 1.0*(Units::SI::kilogram / Units::SI::second);
        Units::Mass         const total_flow      = mass_flow * (1.0*Units::SI::second);
    
        std::cout << "mass_flow:       " << mass_flow       << "\n";
        std::cout << "other_mass_flow: " << other_mass_flow << "\n";
        std::cout << "total_flow:      " << total_flow      << "\n";
    }
    

    Prints

    mass_flow:       7 kg s^-1
    other_mass_flow: 1 kg s^-1
    total_flow:      7 kg