Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Units

 

Technical facts

 

 

 

 

 

 

./CppUnits/CppUnits.pri

 

INCLUDEPATH += \
    ../../Classes/CppUnits

SOURCES += \
    ../../Classes/CppUnits/units.cpp \
    ../../Classes/CppUnits/sulfidemoleculeamount.cpp \
    ../../Classes/CppUnits/hydrogenmoleculeamount.cpp \
    ../../Classes/CppUnits/speciesdensity.cpp \
    ../../Classes/CppUnits/moleculeamount.cpp \
    ../../Classes/CppUnits/volumetricflow.cpp \
    ../../Classes/CppUnits/massflow.cpp \
    ../../Classes/CppUnits/massdensity.cpp \
    ../../Classes/CppUnits/concentration.cpp \
    ../../Classes/CppUnits/speciesgrowth.cpp \
    ../../Classes/CppUnits/rate.cpp \
    ../../Classes/CppUnits/concentrationchange.cpp \
    ../../Classes/CppUnits/ribi_time.cpp

HEADERS  += \
    ../../Classes/CppUnits/units.h \
    ../../Classes/CppUnits/moleculeamount.h \
    ../../Classes/CppUnits/sulfidemoleculeamount.h \
    ../../Classes/CppUnits/hydrogenmoleculeamount.h \
    ../../Classes/CppUnits/speciesdensity.h \
    ../../Classes/CppUnits/volumetricflow.h \
    ../../Classes/CppUnits/massflow.h \
    ../../Classes/CppUnits/massdensity.h \
    ../../Classes/CppUnits/concentration.h \
    ../../Classes/CppUnits/speciesgrowth.h \
    ../../Classes/CppUnits/rate.h \
    ../../Classes/CppUnits/concentrationchange.h \
    ../../Classes/CppUnits/ribi_time.h

OTHER_FILES += \
    ../../Classes/CppUnits/Licence.txt

 

 

 

 

 

./CppUnits/concentration.h

 

#ifndef CONCENTRATION_H
#define CONCENTRATION_H

///Mole per cubic meter
#include <boost/units/systems/si.hpp>

namespace boost {
  namespace units {
    using concentration_dimension
      = derived_dimension<
        amount_base_dimension,1,
        length_base_dimension,-3
      >::type;
  } // ~namespace units
} // ~namespace boost

namespace boost {
  namespace units {
    namespace si {

      using concentration = unit<concentration_dimension,si::system>;
      BOOST_UNITS_STATIC_CONSTANT(mol_per_cubic_meter,concentration);
      BOOST_UNITS_STATIC_CONSTANT(mole_per_cubic_meter,concentration);

      using Concentration = boost::units::quantity<boost::units::si::concentration>;
      std::istream& operator>>(std::istream& is,Concentration& sd);


    } // ~namespace si
  } // ~namespace units
} // ~namespace boost


namespace ribi {
  namespace units {
    using Concentration = boost::units::si::Concentration;
    #ifndef NDEBUG
    void TestConcentration() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi


#endif // CONCENTRATION_H

 

 

 

 

 

./CppUnits/concentration.cpp

 

#include "concentration.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>

#include <boost/units/io.hpp>

#include "fileio.h"
#include "testtimer.h"

std::istream& boost::units::si::operator>>(std::istream& is, Concentration& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "m^-3");
  is >> unit;
  assert(unit == "mol");
  sd = Concentration(value * boost::units::si::mole / boost::units::si::cubic_meter);
  return is;
}

#ifndef NDEBUG
void ribi::units::TestConcentration() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
  }
  const ribi::TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using Concentration = boost::units::quantity<boost::units::si::concentration>;
  //Concentration is in species per square meter
  {
    const Concentration d{
      1.0 * boost::units::si::mole / boost::units::si::cubic_meter
    };
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    std::cerr << t << std::endl;
    assert(t.substr(t.size() - 8, 8) == "m^-3 mol");
  }
  //Concentration uses a dot as a seperator
  {
    const Concentration d{12.34 * boost::units::si::mole / boost::units::si::cubic_meter};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 m^-3 mol");
  }
  //Concentration file I/O, one Concentration
  {
    const Concentration d{12.34 * boost::units::si::mole / boost::units::si::cubic_meter};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    Concentration d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Concentration file I/O, two Concentration
  {
    const Concentration a{12.34 * boost::units::si::mole / boost::units::si::cubic_meter};
    const Concentration b{23.45 * boost::units::si::mole / boost::units::si::cubic_meter};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    Concentration a_too;
    Concentration b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    if (b != b_too)
    {
      std::cerr << a << '\n'
        << b_too << '\n'
      ;
    }
    assert(a == a_too);
    assert(b == b_too);
  }
}
#endif

 

 

 

 

 

./CppUnits/concentrationchange.h

 

#ifndef CONCENTRATIONCHANGE_H
#define CONCENTRATIONCHANGE_H

//Species growth:
// The change in species density per time

#include "concentration.h"
#include <boost/units/systems/si.hpp>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#pragma GCC diagnostic pop

namespace boost {
  namespace units {
    typedef derived_dimension<
      amount_base_dimension,1,
      length_base_dimension,-3,
      time_base_dimension,-1
    >::type concentration_change_dimension;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<concentration_change_dimension,si::system> concentration_change;
      BOOST_UNITS_STATIC_CONSTANT(mole_per_cubic_meter_per_second,concentration_change);

      using ConcentrationChange = boost::units::quantity<boost::units::si::concentration_change>;
      std::istream& operator>>(std::istream& is,ConcentrationChange& sd);

    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {

    using ConcentrationChange = boost::units::quantity<boost::units::si::concentration_change>;

    #ifndef NDEBUG
    void TestConcentrationChange() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi


#endif // CONCENTRATIONCHANGE_H

 

 

 

 

 

./CppUnits/concentrationchange.cpp

 


#include "concentrationchange.h"

#include <boost/units/io.hpp>

#include <iostream>
#include <fstream>
#include <sstream>

#include "fileio.h"
#include "testtimer.h"

#include "concentration.h"
#include "rate.h"

std::istream& boost::units::si::operator>>(std::istream& is, ConcentrationChange& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "m^-3");
  is >> unit;
  assert(unit == "mol");
  is >> unit;
  assert(unit == "s^-1");
  sd = ConcentrationChange(
    value
    * boost::units::si::mole_per_cubic_meter_per_second);
  return is;
}

#ifndef NDEBUG
void ribi::units::TestConcentrationChange() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
    TestConcentration();
    TestRate();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using ConcentrationChange = boost::units::quantity<boost::units::si::concentration_change>;
  //Concentration density is in species per square meter
  {
    const ConcentrationChange d{
      1.0 * boost::units::si::mole_per_cubic_meter_per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    //std::cerr << t << std::endl;
    assert(t.substr(t.size() - 13,13) == "m^-3 mol s^-1");
  }
  //Concentration density uses a dot as a seperator
  {
    const ConcentrationChange d{12.34 * boost::units::si::mole_per_cubic_meter_per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 m^-3 mol s^-1");
  }
  //Concentration growth can be multiplied by an area to obtain the growth rate
  {
    using Area = boost::units::quantity<boost::units::si::area>;
    const ConcentrationChange d{0.1 * boost::units::si::mole_per_cubic_meter_per_second};
    const Area a(123.4 * boost::units::si::square_meter);
    const auto n = d * a;
    std::stringstream s;
    s << n;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 4, 4) == "s^-1");
  }
  //Concentration density file I/O, one ConcentrationChange
  {
    const ConcentrationChange d{12.34 * boost::units::si::mole_per_cubic_meter_per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    ConcentrationChange d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Concentration density file I/O, two ConcentrationChange
  {
    const ConcentrationChange a{12.34 * boost::units::si::mole_per_cubic_meter_per_second};
    const ConcentrationChange b{23.45 * boost::units::si::mole_per_cubic_meter_per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    ConcentrationChange a_too;
    ConcentrationChange b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    assert(a == a_too);
    if (b != b_too)
    {
      std::cerr << b << '\n'
        << b_too << '\n'
      ;
    }
    assert(b == b_too);
  }
  //Combining ConcentrationDensity, ConcentrationChange and Rate
  //Exponential growth
  {
    const double n_unitless{0.7};
    const double r_unitless{1.3};
    const Concentration n{n_unitless * boost::units::si::mole_per_cubic_meter};
    const Rate r{r_unitless * boost::units::si::per_second};
    const ConcentrationChange dndt{n * r};
    assert(dndt.value() == n_unitless * r_unitless);
  }
  //Logistic growth
  {
    const double n_unitless{0.7};
    const double k_unitless{2.0};
    const double r_unitless{1.3};
    const Concentration n{n_unitless * boost::units::si::mole_per_cubic_meter};
    const Concentration k{k_unitless * boost::units::si::mole_per_cubic_meter};
    const Rate r{r_unitless * boost::units::si::per_second};
    const ConcentrationChange dndt{ n * r * (1.0 - (n / k))};
    assert(dndt.value() == n_unitless * r_unitless * (1.0 - (n_unitless / k_unitless)));
  }
  assert(1==2);
}
#endif

 

 

 

 

 

./CppUnits/hydrogenmoleculeamount.h

 

#ifndef HYDROGENMOLECULEAMOUNT_H
#define HYDROGENMOLECULEAMOUNT_H

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

namespace boost {
  namespace units {
    struct hydrogen_molecule_amount_dimension_tag : base_dimension<boost::units::amount_base_dimension,1>{};
    typedef derived_dimension<hydrogen_molecule_amount_dimension_tag,1>::type hydrogen_molecule_amount_dimension;
  } // namespace units
} // namespace boost


namespace boost {
  namespace units {
    namespace si {
      typedef unit<hydrogen_molecule_amount_dimension,si::system> hydrogen_molecule_amount;
      BOOST_UNITS_STATIC_CONSTANT(hydrogen_molecules_mol,hydrogen_molecule_amount);
    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void TestHydrogenMoleculeAmount() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // HYDROGENMOLECULEAMOUNT_H

 

 

 

 

 

./CppUnits/hydrogenmoleculeamount.cpp

 

#ifndef NDEBUG
#include "hydrogenmoleculeamount.h"

#include <sstream>
#include <iostream>

#include <boost/units/io.hpp>

#include "testtimer.h"
void ribi::units::TestHydrogenMoleculeAmount() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  using HydrogenMoleculeAmount = boost::units::quantity<boost::units::si::hydrogen_molecule_amount>;
  //Hydrogen molecule amounts can be displayed
  {
    const HydrogenMoleculeAmount sa{1.0 * boost::units::si::hydrogen_molecules_mol};
    std::stringstream s;
    s << sa;
    const std::string t{s.str()};
    assert(!t.empty());
  }
  //#define FIX_ISSUE_999
  #ifdef FIX_ISSUE_999
  //Hydrogen molecule amounts are in mole
  {
    const HydrogenMoleculeAmount sa{1.0 * boost::units::si::hydrogen_molecules_mol};
    std::stringstream s;
    s << sa;
    const std::string t{s.str()};
    assert(!t.empty());
    std::cout << t << std::endl;
    assert(t.substr(t.size()-3,3) == "mol");
  }
  #endif
  //Can add hydrogen molecule amounts
  {
    const double a{1.0};
    const double b{2.0};
    const double c{a + b};
    const HydrogenMoleculeAmount sa{a * boost::units::si::hydrogen_molecules_mol};
    const HydrogenMoleculeAmount sb{b * boost::units::si::hydrogen_molecules_mol};
    const HydrogenMoleculeAmount sc{sa + sb};
    assert(sc == HydrogenMoleculeAmount{c * boost::units::si::hydrogen_molecules_mol});
  }
}
#endif

 

 

 

 

 

./CppUnits/massdensity.h

 

#ifndef MASSDENSITY_H
#define MASSDENSITY_H

// Mass per square meter
//#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/mass_density.hpp>

/*
#include <iosfwd>
#include <boost/units/systems/si.hpp>


namespace boost {
  namespace units {
    typedef derived_dimension<
      mass_base_dimension,1,
      length_base_dimension,-2
    >::type mass_density_dimension;
  } // ~namespace units
} // ~namespace boost

namespace boost {
  namespace units {
    namespace si {

      using mass_density = unit<mass_density_dimension,si::system>;
      BOOST_UNITS_STATIC_CONSTANT(mass_per_square_meter,mass_density);
      BOOST_UNITS_STATIC_CONSTANT(mass_per_square_meters,mass_density);

      using MassDensity = boost::units::quantity<boost::units::si::mass_density>;
      std::istream& operator>>(std::istream& is,SpeciesDensity& sd);


    } // ~namespace si
  } // ~namespace units
} // ~namespace boost

*/

namespace ribi {
  namespace units {

    #ifndef NDEBUG
    void TestMassDensity() noexcept;
    #endif

    //using MassDensity = boost::units::quantity<boost::units::si::mass_density>;

    //std::string ToStr(const SpeciesDensity& density) noexcept;
    //SpeciesDensity ToSpeciesDensity(const std::string& s) noexcept;

  } //~namespace units
} //~namespace ribi

#endif // MASSDENSITY_H

 

 

 

 

 

./CppUnits/massdensity.cpp

 

#ifndef NDEBUG

#include "massdensity.h"

#include <boost/units/io.hpp>

#include <iostream>
#include <fstream>
#include <sstream>

#include "fileio.h"
#include "testtimer.h"

#ifdef RIBI_USE_MASS_DENSITY
std::istream& boost::units::si::operator>>(std::istream& is, MassDensity& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "m^-2");
  sd = MassDensity(value * boost::units::si::mass_per_square_meter);
  return is;
}
#endif

void ribi::units::TestMassDensity() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  #ifdef RIBI_USE_MASS_DENSITY
  using ribi::fileio::FileIo;
  using MassDensity = boost::units::quantity<boost::units::si::mass_density>;
  //Mass density is in mass per square meter
  {
    const MassDensity d{1.0 * boost::units::si::mass_per_square_meter};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 4, 4) == "m^-2");
  }
  //Mass density uses a dot as a seperator
  {
    const MassDensity d{12.34 * boost::units::si::mass_per_square_meter};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 m^-2");
  }
  //Mass density can be multiplied by an area to obtain the number of mass
  {
    using Area = boost::units::quantity<boost::units::si::area>;
    const MassDensity d{0.1 * boost::units::si::mass_per_square_meter};
    const Area a(123.4 * boost::units::si::square_meter);
    const auto n = d * a;
    std::stringstream s;
    s << n;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 13, 13) == "dimensionless");
  }
  //Mass density file I/O
  {
    const MassDensity d{12.34 * boost::units::si::mass_per_square_meter};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    MassDensity d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  #endif // RIBI_USE_MASS_DENSITY
}

#endif

 

 

 

 

 

./CppUnits/massflow.h

 

#ifndef MASSFLOW_H
#define MASSFLOW_H

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

namespace boost {
  namespace units {
    typedef derived_dimension<
        mass_base_dimension,1,
        time_base_dimension,-1
      >::type mass_flow_dimension
    ;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<mass_flow_dimension,si::system> mass_flow;
      BOOST_UNITS_STATIC_CONSTANT(kilogram_per_second,mass_flow);
      BOOST_UNITS_STATIC_CONSTANT(kilogramme_meters_per_second,mass_flow);
      BOOST_UNITS_STATIC_CONSTANT(kilograms_metre_per_second,mass_flow);
      BOOST_UNITS_STATIC_CONSTANT(kilogrammes_metres_per_second,mass_flow);
    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void TestMassFlow() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // MASSFLOW_H

 

 

 

 

 

./CppUnits/massflow.cpp

 

#ifndef NDEBUG
#include "massflow.h"

#include <iostream>
#include <sstream>

#include <boost/units/io.hpp>

#include "testtimer.h"
#include "volumetricflow.h"

void ribi::units::TestMassFlow() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Allow one extra TestTimer, to test MassFlow <-> VolumetricFlow
  test_timer.SetMaxCnt(2);

  using MassFlow = boost::units::quantity<boost::units::si::mass_flow>;
  using Mass = boost::units::quantity<boost::units::si::mass>;
  using Time = boost::units::quantity<boost::units::si::time>;
  //MassFlow has unit mass per second, 'kg s^-1'
  {
    const MassFlow phi_m{
        1.0
      * boost::units::si::kilogram / boost::units::si::second
    };
    std::stringstream s;
    s << phi_m;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 7,7) == "kg s^-1");
  }
  //MassFlow can be obtained by dividing a mass by a time unit
  {
    const Mass mass{1.0 * boost::units::si::kilogram};
    const Time time{1.0 * boost::units::si::second};
    const MassFlow phi_m{mass / time};
  }
  //MassFlow can be converted to VolumetricFlow
  {
    using Volume = boost::units::quantity<boost::units::si::volume>;
    using VolumetricFlow = boost::units::quantity<boost::units::si::volumetric_flow>;
    using Density = boost::units::quantity<boost::units::si::mass_density>;

    const Volume v{1.0 * boost::units::si::cubic_meter};
    const Time t{1.0 * boost::units::si::second};
    const MassFlow phi_m{
      1.0 * boost::units::si::kilogram / boost::units::si::second
    };
    const Density d{
      1.0 * boost::units::si::kilogram / boost::units::si::cubic_meter
    };
    const VolumetricFlow phi_v{phi_m / d};
    //const VolumetricFlow phi_v_wrong{phi_m * d}; //GOOD: does not compile
    //const VolumetricFlow phi_v_wrong{d / phi_m}; //GOOD: does not compile
  }
  test_timer.SetMaxCnt(1);
}
#endif

 

 

 

 

 

./CppUnits/moleculeamount.h

 

#ifndef MOLECULEAMOUNT_H
#define MOLECULEAMOUNT_H

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

namespace boost {
  namespace units {
    //1 states that the amount is in moles (of molecules, in this context)
    typedef derived_dimension<boost::units::amount_base_dimension,1>::type molecule_amount_dimension;
  } // namespace units
} // namespace boost


namespace boost {
  namespace units {
    namespace si {
      typedef unit<molecule_amount_dimension,si::system> molecule_amount;
      BOOST_UNITS_STATIC_CONSTANT(molecules_mol,molecule_amount);
    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void TestMoleculeAmount() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // MOLECULEAMOUNT_H

 

 

 

 

 

./CppUnits/moleculeamount.cpp

 

#ifndef NDEBUG
#include "moleculeamount.h"

#include "units.h"

#include <iostream>
#include <sstream>

#include <boost/units/io.hpp>

#include "moleculeamount.h"
#include "testtimer.h"

void ribi::units::TestMoleculeAmount() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using MoleculeAmount = boost::units::quantity<boost::units::si::molecule_amount>;
  //Can add molecule amounts
  {
    const MoleculeAmount a{1.0 * boost::units::si::molecules_mol};
    const MoleculeAmount b{1.0 * boost::units::si::molecules_mol};
    a + b;
  }
  //Molecule amounts are in mole
  {
    using MoleculeAmount = boost::units::quantity<boost::units::si::molecule_amount>;
    const MoleculeAmount a{1.0 * boost::units::si::molecules_mol};
    std::stringstream s;
    s << a;
    const std::string t{s.str()};
    assert(!t.empty());
    assert(t.substr(t.size()-3,3) == "mol");
  }
}
#endif

 

 

 

 

 

./CppUnits/rate.h

 

#ifndef RATE_H
#define RATE_H

//Rate
// The relative (unitless) change of something in time

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#pragma GCC diagnostic pop

namespace boost {
  namespace units {
    typedef derived_dimension<
      time_base_dimension,-1
    >::type rate_dimension;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<rate_dimension,si::system> rate;
      BOOST_UNITS_STATIC_CONSTANT(per_second,rate);

      using Rate = boost::units::quantity<boost::units::si::rate>;
      std::istream& operator>>(std::istream& is,Rate& sd);

    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {

    using Rate = boost::units::quantity<boost::units::si::rate>;

    #ifndef NDEBUG
    void TestRate() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // RATE_H

 

 

 

 

 

./CppUnits/rate.cpp

 

#include "rate.h"

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/units/io.hpp>

#include "speciesdensity.h"

std::istream& boost::units::si::operator>>(std::istream& is, Rate& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "s^-1");
  sd = Rate(
    value
    * boost::units::si::per_second);
  return is;
}

#ifndef NDEBUG
#include "fileio.h"
#include "testtimer.h"
void ribi::units::TestRate() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using Rate = boost::units::quantity<boost::units::si::rate>;
  //Species density is in species per square meter
  {
    const Rate d{
      1.0 * boost::units::si::per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    //std::cerr << t << std::endl;
    assert(t.substr(t.size() - 4, 4) == "s^-1");
  }
  //Species density uses a dot as a seperator
  {
    const Rate d{12.34 * boost::units::si::per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 s^-1");
  }
  //Species growth can be multiplied by an area to obtain the growth rate
  {
    using Area = boost::units::quantity<boost::units::si::area>;
    const Rate d{0.1 * boost::units::si::per_second};
    const Area a(123.4 * boost::units::si::square_meter);
    const auto n = d * a;
    std::stringstream s;
    s << n;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 4, 4) == "s^-1");
  }
  //Species density file I/O, one Rate
  {
    const Rate d{12.34 * boost::units::si::per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    Rate d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Species density file I/O, two Rate
  {
    const Rate a{12.34 * boost::units::si::per_second};
    const Rate b{23.45 * boost::units::si::per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    Rate a_too;
    Rate b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    assert(a == a_too);
    if (b != b_too)
    {
      std::cerr << b << '\n'
        << b_too << '\n'
      ;
    }
    assert(b == b_too);
  }
}
#endif

 

 

 

 

 

./CppUnits/ribi_time.h

 

#ifndef RIBI_TIME_H
#define RIBI_TIME_H

//Time
// The relative (unitless) change of something in time

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#pragma GCC diagnostic pop

namespace boost {
  namespace units {
    namespace si {
      using Time = boost::units::quantity<boost::units::si::time>;
      std::istream& operator>>(std::istream& is,Time& sd);

    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {

    using Time = boost::units::quantity<boost::units::si::time>;

    #ifndef NDEBUG
    void TestTime() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // RIBI_TIME_H

 

 

 

 

 

./CppUnits/ribi_time.cpp

 

#include "ribi_time.h"

#include <fstream>
#include <sstream>

#include <boost/units/io.hpp>

#include "fileio.h"

std::istream& boost::units::si::operator>>(std::istream& is, Time& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "s");
  sd = Time(value * seconds);
  return is;
}

#ifndef NDEBUG
#include "testtimer.h"

#include <iostream>

void ribi::units::TestTime() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using Time = boost::units::quantity<boost::units::si::time>;
  using boost::units::si::seconds;

  //Time is in seconds
  {
    const Time d{1.0 * seconds};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 1,1) == "s");
  }
  //Time uses a dot as a seperator
  {
    const Time d{12.34 * seconds};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 s");
  }
  //Time file I/O, one Time
  {
    const Time d{12.34 * seconds};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    Time d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Time file I/O, two Time
  {
    const Time a{12.34 * seconds};
    const Time b{23.45 * seconds};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    Time a_too;
    Time b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    assert(a == a_too);
    if (b != b_too)
    {
      std::cerr << b << '\n'
        << b_too << '\n'
      ;
    }
    assert(b == b_too);
  }
}
#endif

 

 

 

 

 

./CppUnits/speciesdensity.h

 

#ifndef SPECIESDENSITY_H
#define SPECIESDENSITY_H

#include <iosfwd>
#include <boost/units/systems/si.hpp>

namespace boost {
  namespace units {
    using species_density_dimension = derived_dimension<length_base_dimension,-2>::type;
  } // ~namespace units
} // ~namespace boost

namespace boost {
  namespace units {
    namespace si {

      using species_density = unit<species_density_dimension,si::system>;
      BOOST_UNITS_STATIC_CONSTANT(species_per_square_meter,species_density);
      BOOST_UNITS_STATIC_CONSTANT(species_per_square_meters,species_density);

      using SpeciesDensity = boost::units::quantity<boost::units::si::species_density>;
      std::istream& operator>>(std::istream& is,SpeciesDensity& sd);


    } // ~namespace si
  } // ~namespace units
} // ~namespace boost

namespace ribi {
  namespace units {

    #ifndef NDEBUG
    void TestSpeciesDensity() noexcept;
    #endif

    using SpeciesDensity = boost::units::quantity<boost::units::si::species_density>;

  } //~namespace units
} //~namespace ribi


#endif // SPECIESDENSITY_H

 

 

 

 

 

./CppUnits/speciesdensity.cpp

 

#include "speciesdensity.h"

#include <fstream>
#include <sstream>

#include <boost/units/io.hpp>

#include "fileio.h"

std::istream& boost::units::si::operator>>(std::istream& is, SpeciesDensity& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "m^-2");
  sd = SpeciesDensity(value * boost::units::si::species_per_square_meter);
  return is;
}

#ifndef NDEBUG
#include "testtimer.h"

#include <iostream>

void ribi::units::TestSpeciesDensity() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using SpeciesDensity = boost::units::quantity<boost::units::si::species_density>;
  //Species density is in species per square meter
  {
    const SpeciesDensity d{1.0 * boost::units::si::species_per_square_meter};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 4, 4) == "m^-2");
  }
  //Species density uses a dot as a seperator
  {
    const SpeciesDensity d{12.34 * boost::units::si::species_per_square_meters};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 m^-2");
  }
  //Species density can be multiplied by an area to obtain the number of species
  {
    using Area = boost::units::quantity<boost::units::si::area>;
    const SpeciesDensity d{0.1 * boost::units::si::species_per_square_meter};
    const Area a(123.4 * boost::units::si::square_meter);
    const auto n = d * a;
    std::stringstream s;
    s << n;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 13, 13) == "dimensionless");
  }
  //Species density file I/O, one SpeciesDensity
  {
    const SpeciesDensity d{12.34 * boost::units::si::species_per_square_meter};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    SpeciesDensity d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Species density file I/O, two SpeciesDensity
  {
    const SpeciesDensity a{12.34 * boost::units::si::species_per_square_meter};
    const SpeciesDensity b{23.45 * boost::units::si::species_per_square_meter};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    SpeciesDensity a_too;
    SpeciesDensity b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    assert(a == a_too);
    if (b != b_too)
    {
      std::cerr << b << '\n'
        << b_too << '\n'
      ;
    }
    assert(b == b_too);
  }
}
#endif

 

 

 

 

 

./CppUnits/speciesgrowth.h

 

#ifndef SPECIESGROWTH_H
#define SPECIESGROWTH_H

//Species growth:
// The change in species density per time

#include "speciesdensity.h"
#include <boost/units/systems/si.hpp>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#pragma GCC diagnostic pop

namespace boost {
  namespace units {
    typedef derived_dimension<
      length_base_dimension,-2,
      time_base_dimension,-1
    >::type species_growth_dimension;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<species_growth_dimension,si::system> species_growth;
      BOOST_UNITS_STATIC_CONSTANT(species_per_square_meter_per_second,species_growth);

      using SpeciesGrowth = boost::units::quantity<boost::units::si::species_growth>;
      std::istream& operator>>(std::istream& is,SpeciesGrowth& sd);

    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {

    using SpeciesGrowth = boost::units::quantity<boost::units::si::species_growth>;

    #ifndef NDEBUG
    void TestSpeciesGrowth() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi



#endif // SPECIESGROWTH_H

 

 

 

 

 

./CppUnits/speciesgrowth.cpp

 

#include "speciesgrowth.h"

#include <fstream>
#include <sstream>

#include <boost/units/io.hpp>

#include "speciesdensity.h"
#include "rate.h"

std::istream& boost::units::si::operator>>(std::istream& is, SpeciesGrowth& sd)
{
  double value = 0.0;
  is >> value;
  std::string unit;
  is >> unit;
  assert(unit == "m^-2");
  is >> unit;
  assert(unit == "s^-1");
  sd = SpeciesGrowth(
    value
    * boost::units::si::species_per_square_meter_per_second);
  return is;
}

#ifndef NDEBUG
#include <iostream>

#include "fileio.h"
#include "testtimer.h"

void ribi::units::TestSpeciesGrowth() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    ribi::fileio::FileIo();
    TestSpeciesDensity();
    TestRate();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using ribi::fileio::FileIo;
  using SpeciesGrowth = boost::units::quantity<boost::units::si::species_growth>;
  //Species density is in species per square meter
  {
    const SpeciesGrowth d{
      1.0 * boost::units::si::species_per_square_meter_per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    //std::cerr << t << std::endl;
    assert(t.substr(t.size() - 9, 9) == "m^-2 s^-1");
  }
  //Species density uses a dot as a seperator
  {
    const SpeciesGrowth d{12.34 * boost::units::si::species_per_square_meter_per_second};
    std::stringstream s;
    s << d;
    const std::string t{s.str()};
    assert(t == "12.34 m^-2 s^-1");
  }
  //Species growth can be multiplied by an area to obtain the growth rate
  {
    using Area = boost::units::quantity<boost::units::si::area>;
    const SpeciesGrowth d{0.1 * boost::units::si::species_per_square_meter_per_second};
    const Area a(123.4 * boost::units::si::square_meter);
    const auto n = d * a;
    std::stringstream s;
    s << n;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 4, 4) == "s^-1");
  }
  //Species density file I/O, one SpeciesGrowth
  {
    const SpeciesGrowth d{12.34 * boost::units::si::species_per_square_meter_per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << d;
    }
    std::ifstream f{filename};
    SpeciesGrowth d_too;
    f >> d_too;
    if (d != d_too)
    {
      std::cerr << d << '\n'
        << d_too << '\n'
      ;
    }
    assert(d == d_too);
  }
  //Species density file I/O, two SpeciesGrowth
  {
    const SpeciesGrowth a{12.34 * boost::units::si::species_per_square_meter_per_second};
    const SpeciesGrowth b{23.45 * boost::units::si::species_per_square_meter_per_second};
    const std::string filename{FileIo().GetTempFileName(".txt")};
    {
      std::ofstream f{filename};
      f << a << " " << b;
    }
    std::ifstream f{filename};
    SpeciesGrowth a_too;
    SpeciesGrowth b_too;
    f >> a_too >> b_too;
    if (a != a_too)
    {
      std::cerr << a << '\n'
        << a_too << '\n'
      ;
    }
    assert(a == a_too);
    if (b != b_too)
    {
      std::cerr << b << '\n'
        << b_too << '\n'
      ;
    }
    assert(b == b_too);
  }
  //Combining SpeciesDensity, SpeciesGrowth and Rate
  //Exponential growth
  {
    const double n_unitless{0.7};
    const double r_unitless{1.3};
    const SpeciesDensity n{n_unitless * boost::units::si::species_per_square_meter};
    const Rate r{r_unitless * boost::units::si::per_second};
    const SpeciesGrowth dndt{n * r};
    assert(dndt.value() == n_unitless * r_unitless);
  }
  //Logistic growth
  {
    const double n_unitless{0.7};
    const double k_unitless{2.0};
    const double r_unitless{1.3};
    const SpeciesDensity n{n_unitless * boost::units::si::species_per_square_meter};
    const SpeciesDensity k{k_unitless * boost::units::si::species_per_square_meter};
    const Rate r{r_unitless * boost::units::si::per_second};
    const SpeciesGrowth dndt{ n * r * (1.0 - (n / k))};
    assert(dndt.value() == n_unitless * r_unitless * (1.0 - (n_unitless / k_unitless)));
  }
}
#endif

 

 

 

 

 

./CppUnits/sulfidemoleculeamount.h

 

#ifndef SULFIDEMOLECULEAMOUNT_H
#define SULFIDEMOLECULEAMOUNT_H

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

namespace boost {
  namespace units {
    struct sulfide_molecule_amount_dimension_tag : base_dimension<boost::units::amount_base_dimension,1>{};
    typedef derived_dimension<sulfide_molecule_amount_dimension_tag,1>::type sulfide_molecule_amount_dimension;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<sulfide_molecule_amount_dimension,si::system> sulfide_molecule_amount;
      BOOST_UNITS_STATIC_CONSTANT(sulfide_molecules_mol,sulfide_molecule_amount);
    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void TestSulfideMoleculeAmount() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // SULFIDEMOLECULEAMOUNT_H

 

 

 

 

 

./CppUnits/sulfidemoleculeamount.cpp

 

#ifndef NDEBUG
#include "sulfidemoleculeamount.h"

#include <iostream>
#include <sstream>

#include <boost/units/io.hpp>

#include "testtimer.h"

void ribi::units::TestSulfideMoleculeAmount() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    //ribi::fileio::FileIo();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  using SulfideMoleculeAmount = boost::units::quantity<boost::units::si::sulfide_molecule_amount>;
  //Sulfide molecule amounts can be displayed
  {
    const SulfideMoleculeAmount sa{1.0 * boost::units::si::sulfide_molecules_mol};
    std::stringstream s;
    s << sa;
    const std::string t{s.str()};
    assert(!t.empty());
  }
  //#define FIX_ISSUE_999
  #ifdef FIX_ISSUE_999
  //Sulfide molecule amounts are in mole
  {
    const SulfideMoleculeAmount sa{1.0 * boost::units::si::sulfide_molecules_mol};
    std::stringstream s;
    s << sa;
    const std::string t{s.str()};
    assert(!t.empty());
    std::cout << t << std::endl;
    assert(t.substr(t.size()-3,3) == "mol");
  }
  #endif
  //Can add sulfide molecule amounts
  {
    const double a{1.0};
    const double b{2.0};
    const double c{a + b};
    const SulfideMoleculeAmount sa{a * boost::units::si::sulfide_molecules_mol};
    const SulfideMoleculeAmount sb{b * boost::units::si::sulfide_molecules_mol};
    const SulfideMoleculeAmount sc{sa + sb};
    assert(sc == SulfideMoleculeAmount{c * boost::units::si::sulfide_molecules_mol});
  }
}
#endif

 

 

 

 

 

./CppUnits/units.h

 

#ifndef RIBI_UNITS_H
#define RIBI_UNITS_H

///Collection of my own units

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void Test() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // RIBI_UNITS_H

 

 

 

 

 

./CppUnits/units.cpp

 

#ifndef NDEBUG
#include "units.h"

#include <iostream>
#include <sstream>

#include <boost/units/io.hpp>

#include "concentration.h"
#include "hydrogenmoleculeamount.h"
#include "rate.h"
#include "massflow.h"
#include "moleculeamount.h"
#include "speciesdensity.h"
#include "speciesgrowth.h"
#include "sulfidemoleculeamount.h"
#include "testtimer.h"
#include "ribi_time.h"
#include "volumetricflow.h"

void ribi::units::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    TestConcentration();
    TestHydrogenMoleculeAmount();
    TestMassFlow();
    TestRate();
    TestMoleculeAmount();
    TestSpeciesDensity();
    TestSpeciesGrowth();
    TestSulfideMoleculeAmount();
    TestTime();
    TestVolumetricFlow();
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);

  #ifdef MUST_NOT_COMPILE_CREATE_HYDROGEN_FROM_SULFIDE
  //Cannot create hydrogen from sulfide
  {
    using HydrogenMoleculeAmount = boost::units::quantity<boost::units::si::hydrogen_molecule_amount>;
    const HydrogenMoleculeAmount h{1.0 * boost::units::si::sulfide_molecules_mol}; //Must fail
  }
  #endif
  #ifdef MUST_NOT_COMPILE_CREATE_SULFIDE_FROM_HYDROGEN
  //Cannot create sulfide from hydrogen
  {
    using SulfideMoleculeAmount = boost::units::quantity<boost::units::si::sulfide_molecule_amount>;
    const SulfideMoleculeAmount s{1.0 * boost::units::si::hydrogen_molecules_mol};
  }
  #endif
  #ifdef MUST_NOT_COMPILE_ADD_HYDROGEN_AND_SULFIDE
  //Cannot add hydrogen and sulfide molecule amounts
  {
    using HydrogenMoleculeAmount = boost::units::quantity<boost::units::si::hydrogen_molecule_amount>;
    using SulfideMoleculeAmount = boost::units::quantity<boost::units::si::sulfide_molecule_amount>;
    const HydrogenMoleculeAmount h{1.0 * boost::units::si::hydrogen_molecules_mol};
    const SulfideMoleculeAmount s{1.0 * boost::units::si::sulfide_molecules_mol};
    h + s; //Must fail
  }
  #endif
}
#endif

 

 

 

 

 

./CppUnits/volumetricflow.h

 

#ifndef VOLUMETRICFLOW_H
#define VOLUMETRICFLOW_H

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

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#pragma GCC diagnostic pop

namespace boost {
  namespace units {
    typedef derived_dimension<
      length_base_dimension,3,
      time_base_dimension,-1
    >::type volumetric_flow_dimension;
  } // namespace units
} // namespace boost

namespace boost {
  namespace units {
    namespace si {
      typedef unit<volumetric_flow_dimension,si::system> volumetric_flow;
      BOOST_UNITS_STATIC_CONSTANT(cubic_meter_per_second,volumetric_flow);
      BOOST_UNITS_STATIC_CONSTANT(cubic_meters_per_second,volumetric_flow);
      BOOST_UNITS_STATIC_CONSTANT(cubic_metre_per_second,volumetric_flow);
      BOOST_UNITS_STATIC_CONSTANT(cubic_metres_per_second,volumetric_flow);
    } // namespace si
  } // namespace units
} //namespace boost

namespace ribi {
  namespace units {
    #ifndef NDEBUG
    void TestVolumetricFlow() noexcept;
    #endif
  } //~namespace units
} //~namespace ribi

#endif // VOLUMETRICFLOW_H

 

 

 

 

 

./CppUnits/volumetricflow.cpp

 

#ifndef NDEBUG
#include "volumetricflow.h"

#include <boost/units/io.hpp>
#include <sstream>
#include "massflow.h"
#include "testtimer.h"

void ribi::units::TestVolumetricFlow() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);

  //Allow one extra TestTimer, to test MassFlow <-> VolumetricFlow
  test_timer.SetMaxCnt(2);

  using VolumetricFlow = boost::units::quantity<boost::units::si::volumetric_flow>;
  using Volume = boost::units::quantity<boost::units::si::volume>;
  using Time = boost::units::quantity<boost::units::si::time>;
  //VolumetricFlow has unit cubic metre per second, 'm^3 s^-1'
  {
    const VolumetricFlow phi_v{
        1.0
      * boost::units::si::cubic_meter / boost::units::si::second
    };
    std::stringstream s;
    s << phi_v;
    const std::string t{s.str()};
    assert(t.substr(t.size() - 8,8) == "m^3 s^-1");
  }
  //VolumetricFlow can be obtained by dividing a volume by a time unit
  {
    const Volume volume{1.0 * boost::units::si::cubic_meter};
    const Time time{1.0 * boost::units::si::second};
    const VolumetricFlow phi_v{volume / time};
  }

  //VolumetricFlow can be converted to MassFlow
  {
    using Volume = boost::units::quantity<boost::units::si::volume>;
    using MassFlow = boost::units::quantity<boost::units::si::mass_flow>;
    using Density = boost::units::quantity<boost::units::si::mass_density>;

    const Volume v{1.0 * boost::units::si::cubic_meter};
    const Time t{1.0 * boost::units::si::second};
    const VolumetricFlow phi_v{v / t};
    const Density d{
      1.0
       * boost::units::si::kilogram / boost::units::si::cubic_meter
    };
    const MassFlow phi_m{phi_v * d};
  }
  test_timer.SetMaxCnt(1);
}
#endif

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml