Source code: C++ Temperature Conversion and Vapor Pressure Deficit (VPD) šŸ› 

Although VPD and Farenheit concersion are of no use to me
I do appreciate the effort that has gone into this and the fact you CCā€™d them is cool
Nice one

Keep thinking about an arduino contoller but my timer system is working ok right now
when it fails ill probably build a proper controller

1 Like

More to come over time. Perhaps, some future item will give you some ideas and help kickstart your arduino project :wink:

3 Likes

That just reminded me of my buddy who makes those all the time. I could probably ask him to help out. Heā€™s starting a grow for the first time soon

2 Likes

Ah this is awesome. I havenā€™t coded in C++ since 2000 but maybe Iā€™ll convert these over to C# so I can tie it into my dashboard. Nice work!

3 Likes

Vapor Pressure Deficit classes:

edit: 10/1/2018 Added additional algorithms for use in the calculation of the vapor pressure. These can be selected individually when using this class otherwise the default algorithm is utilized. Different algorithms have different accuracy depending on the environmental conditions. The more accurate algorithms can also have greater runtime complexity (bigO). In most cases, the default algorithm will be more than accurate. Error will be primarily due to the sensors.
edit: Addition of dewpoint calculation.
edit: Addition of precipitable water column estimation.
This class is used in conjunction with the aforementioned classes in the OP. I moved this class out of the OP since there is a limit on individual post size and the class has become larger.

//
// vpd.h
// Version timestamp: 10-4-2018, 1:29 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# pragma once
# include <boost/variant.hpp>
# include "temperature_types.h"

enum VPD_ALGORITHMS : unsigned short
{
    VPD_BUCK_1981,
    VPD_BUCK_1996,
    VPD_GOFF,
    VPD_WMO
};

class vpd : public celcius, farenheit, kelvin
{
public:
    vpd();
    vpd(celcius_variant temperature, float humidity);
    vpd(celcius_variant temperature, float relative_humidity, VPD_ALGORITHMS algorithm);
    vpd(celcius_variant temperature, celcius_variant leaf_temperature, float humidity);
    vpd(celcius_variant temperature, celcius_variant leaf_temperature, float relative_humidity, VPD_ALGORITHMS algorithm);
    vpd(const vpd& c); 
    ~vpd();
    void calculate_vpd(celcius temperature, celcius temperature_leaf, float relative_humidity, VPD_ALGORITHMS algorithm);
    double calculate_vapor_pressure(celcius temperature, unsigned int method);
    double calculate_buck_1981(celcius temperature);
    double calculate_buck_1996(celcius temperature);
    double calculate_wmo(celcius temperature);
    double calculate_goff_gratch(celcius temperature);
    double calculate_dewpoint(celcius temperature, double relative_humidity);
    double calculate_precipital_water(celcius dewpoint);
    double operator()(celcius_variant temperature, float relative_humidity);
    double operator()(celcius_variant temperature, celcius_variant temperature_leaf, float relative_humidity); 
    double operator()(celcius_variant temperature, float relative_humidity, VPD_ALGORITHMS algorithm);
    double operator()(celcius_variant temperature, celcius_variant temperature_leaf, float relative_humidity, VPD_ALGORITHMS algorithm); 
    double operator()();
    friend std::ostream& operator<<(std::ostream& lhs, const vpd& rhs)
    {
        return (lhs << rhs.vapor_pressure_deficit);
    }
    
    celcius degrees_celcius = 0.0;
    celcius degrees_celcius_leaf = 0.0;
    celcius dewpoint_atmosphere;
    celcius dewpoint_leaf;
    double  precipital_h2o;
    float   humidity = 0.0;
    double saturation_vapor_pressure_atmosphere = 0.0;
    double saturation_vapor_pressure_leaf = 0.0;
    double vapor_pressure_atmosphere = 0.0;
    double vapor_pressure_leaf = 0.0;
    double vapor_pressure_deficit = 0.0;
};

//
// vpd.cpp
// Version timestamp: 10-4-2018, 1:30 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//

// This source code may be utilized to calculate the vapor pressure deficit between plant mass and the surrounding environment.
// Requires the temperature conversion classes celcius, farenheit, and kelvin
//
// Some usage examples:
//
//  /* Determine the vapor pressure deficit for 80 degrees farenheit and 60 percent relative humidity. */
//  vpd vapor_pressure_deficit((farenheit) 80, 0.60);
//  std::cout << "Vapor pressure deficit" << vapor_pressure_deficit << std::endl;
//
//  /* Determine the vapor pressure deficit for 23 degrees celcius and 40 percent relative humidity. */
//  vpd vapor_pressure_deficit((celcius) 23, 0.40);
//  std::cout << "Vapor pressure deficit" << vapor_pressure_deficit << std::endl;
//
//  /* Using printf. */
//  vpd vapor_pressure_deficit((celcius) 23, 0.40);
//  printf("Vapor pressure deficit %8.3f \n",vapor_pressure_deficit());
//
//  /* If you know or have estimated the actual leaf temperature. */
//  vpd vapor_pressure_deficit((farenheit) 80, (farenheit) (80+1), 0.60);
//  std::cout << "Vapor pressure deficit" << vapor_pressure_deficit << std::endl;
//

# include "vpd.h"

/* Empty constructor for vapor pressure deficit. */
vpd::vpd()
{
    this->humidity = 0.0;
    this->degrees_celcius = 0.0;
    this->degrees_celcius_leaf = 0.0;
    this->vapor_pressure_atmosphere = 0.0;
    this->vapor_pressure_deficit = 0.0;
    this->vapor_pressure_leaf = 0.0;
}

/* Constructor */
/* Calculate the vapor pressure deficit based on the environment temperature and the relative humidity. */
/* In this case, the temperature of the plant mass is considered to be at the same temperature as the surrounding environment. */
vpd::vpd(celcius_variant temperature, float relative_humidity)
{
    if (relative_humidity > 1)
    {
        this->humidity = 1.0;
    }
    else if (relative_humidity < 0)
    {
        this->humidity = 0.0;
    }
    else
    {
        this->humidity = relative_humidity;
    }
    
    calculate_vpd(temperature, temperature, relative_humidity, VPD_BUCK_1981);
}

/* Constructor */
/* Calculate the vapor pressure deficit based on the environment temperature and the relative humidity. */
/* In this case, the temperature of the plant mass is considered to be at the same temperature as the surrounding environment. */
vpd::vpd(celcius_variant temperature, float relative_humidity, VPD_ALGORITHMS algorithm)
{
    if (relative_humidity > 1)
    {
        this->humidity = 1.0;
    }
    else if (relative_humidity < 0)
    {
        this->humidity = 0.0;
    }
    else
    {
        this->humidity = relative_humidity;
    }
    
    calculate_vpd(temperature, temperature, relative_humidity, algorithm);
}

/* Constructor */
/* Calculate the vapor pressure deficit based on the environment temperature, leaf temperature and the relative humidity. */
/* In this case, the temperature of the plant mass is used in the calculation of the pressure deficit. */
vpd::vpd(celcius_variant temperature, celcius_variant leaf_temperature, float relative_humidity)
{
    if (relative_humidity > 1)
    {
        humidity = 1.0;
    }
    else if (relative_humidity < 0)
    {
        humidity = 0.0;
    }
    else
    {
        humidity = relative_humidity;
    }
    
    calculate_vpd(temperature, leaf_temperature, relative_humidity, VPD_BUCK_1981);
}

/* Constructor */
/* Calculate the vapor pressure deficit based on the environment temperature, leaf temperature and the relative humidity. */
/* In this case, the temperature of the plant mass is used in the calculation of the pressure deficit and the calculation method is specified. */
vpd::vpd(celcius_variant temperature, celcius_variant leaf_temperature, float relative_humidity, VPD_ALGORITHMS algorithm)
{
    if (relative_humidity > 1)
    {
        humidity = 1.0;
    }
    else if (relative_humidity < 0)
    {
        humidity = 0.0;
    }
    else
    {
        humidity = relative_humidity;
    }
    
    calculate_vpd(temperature, leaf_temperature, relative_humidity, algorithm);
}


/* Copy Constructor */
vpd::vpd(const vpd& c) 
{ 
    this->degrees_celcius = c.degrees_celcius;  
    this->degrees_celcius_leaf = c.degrees_celcius_leaf; 
    this->humidity = c.humidity; 
    this->saturation_vapor_pressure_atmosphere = c.saturation_vapor_pressure_atmosphere;
    this->saturation_vapor_pressure_leaf = c.saturation_vapor_pressure_leaf;
    this->vapor_pressure_atmosphere = c.vapor_pressure_atmosphere; 
    this->vapor_pressure_leaf = c.vapor_pressure_leaf; 
    this->vapor_pressure_deficit = c.vapor_pressure_deficit;
} 

/* Destructor */
vpd::~vpd()
{
}

/* Do the VPD calculations. */
/* VPD units are in kPa. A rough estimate in millibars would be to multiply the results in kPa by ten.  */
void vpd::calculate_vpd(celcius temperature, celcius temperature_leaf, float relative_humidity, VPD_ALGORITHMS algorithm) 
{
    /* Save the temperatures and humidity. */
    this->degrees_celcius = temperature;
    this->degrees_celcius_leaf = temperature_leaf;
    this->humidity = relative_humidity;
    
    /* Calculate the water vapor pressure of the air. */
    this->saturation_vapor_pressure_atmosphere = calculate_vapor_pressure(this->degrees_celcius, algorithm);
    this->vapor_pressure_atmosphere = (humidity) * this->saturation_vapor_pressure_atmosphere;
    
    /* Calculate the water vapor pressure in the leaf. */
    
    /* Leaf has 100% humidity */
    this->saturation_vapor_pressure_leaf = calculate_vapor_pressure(this->degrees_celcius_leaf, algorithm);
    this->vapor_pressure_leaf = (1) * this->saturation_vapor_pressure_leaf;
    
    /* Calculate the water vapor pressure deficit of the air. */
    this->vapor_pressure_deficit = vapor_pressure_leaf - vapor_pressure_atmosphere;
	
	/* Calculate the dewpoints */
	this->dewpoint_atmosphere = calculate_dewpoint(temperature, relative_humidity);
	this->dewpoint_leaf = calculate_dewpoint(temperature_leaf, relative_humidity);
	
	/* Estimate the percipital H20 water column (in cm at sea level) */
	this->precipital_h2o = calculate_precipital_water(this->dewpoint_atmosphere);
	
}

double vpd::calculate_vapor_pressure(celcius temperature, unsigned int method)
{
    double vapor_pressure = 0.0;
    
    switch(method)
    {
    case VPD_BUCK_1981:
        vapor_pressure = calculate_buck_1981(temperature);
        break;
    case VPD_BUCK_1996:
        vapor_pressure = calculate_buck_1996(temperature);
        break;
    case VPD_GOFF:
        vapor_pressure = calculate_goff_gratch(temperature);
        break;
    case VPD_WMO:
        vapor_pressure = calculate_wmo(temperature);
        break;
    default: 
        vapor_pressure = calculate_buck_1981(temperature);
        break;
    }
    
    return (vapor_pressure);	
}

double vpd::calculate_buck_1981(celcius temperature)
{
    /* Buck, A. L., New equations for computing vapor pressure and enhancement factor, J. Appl. Meteorol., 20, 1527-1532, 1981. */
    double vapor_pressure = 0.61121 * pow(EULER, (17.502*temperature()) / (temperature() + 240.97));
    return (vapor_pressure);
}

double vpd::calculate_buck_1996(celcius temperature)
{
    double vapor_pressure = 0.61121 * pow(EULER, ((18.678 - temperature() / 234.5)*temperature()) / (temperature() + 257.14));
    return (vapor_pressure);
}

double vpd::calculate_wmo(celcius temperature)
{
    double vapor_pressure = 0.61121 * pow(EULER, (17.62*temperature()) / (temperature() + 243.12));
    return (vapor_pressure);
}

double vpd::calculate_goff_gratch(celcius temperature)
{
    kelvin Tkelvin = temperature;
    
    double a1 = -7.90298 * (373.16 / Tkelvin() - 1.0);
    double a2 = 5.02808 * log10(373.16 / Tkelvin() );
    double a3 = (-1.3816 / 10000000) * (powf(10, 11.344*(1.0 - Tkelvin() / 373.16)) - 1.0);
    double a4 = (8.1328 / 1000) * (powf(10, -3.49149*(373.16 / Tkelvin() - 1.0) - 1.0) );
        
    double vapor_pressure = a1 + a2 + a3 + a4 + log10(1013.246);
    
    return (powf(10.0,vapor_pressure)/10.0);
}

double vpd::calculate_dewpoint(celcius temperature, double relative_humidity)
{
	double dewpoint = 0.0;
	dewpoint = pow((relative_humidity), (1.0 / 8.0)) * (112.0 + (0.9 * temperature())) - 112.0 + (0.1 * temperature());
	
	return (dewpoint);
}

/* Estimate the clearday precipital water in the atomospheric column based on the surface dewpoint. */
/* ā€œModeling Daylight Availability and Irradiance Components from Direct and Global Irradiance,ā€ Perez, et.al. 1990 Solar Energy 44(5) eq. 3. */
/* The coefficients are emperically generated based on monthly averages across 15 sites in the US. */
/* This may have significant error components depending on application and environmental conditions. */
double vpd::calculate_precipital_water(celcius dewpoint)
{
	double prcp = 0.0;
	
	prcp = exp(0.07 * dewpoint() - 0.075);
	
	return (prcp);
}


double vpd::operator()(celcius_variant temperature, float relative_humidity) 
{
    calculate_vpd(temperature, temperature, relative_humidity, VPD_BUCK_1981);
    double temp = this->vapor_pressure_deficit;
    return (temp);
}

double vpd::operator()(celcius_variant temperature, celcius_variant temperature_leaf, float relative_humidity) 
{
    calculate_vpd(temperature, temperature_leaf, relative_humidity, VPD_BUCK_1981);
    double temp = this->vapor_pressure_deficit;
    return (temp);
}

double vpd::operator()(celcius_variant temperature, float relative_humidity, VPD_ALGORITHMS algorithm) 
{
    calculate_vpd(temperature, temperature, relative_humidity, algorithm);
    double temp = this->vapor_pressure_deficit;
    return (temp);
}

double vpd::operator()(celcius_variant temperature, celcius_variant temperature_leaf, float relative_humidity, VPD_ALGORITHMS algorithm) 
{
    calculate_vpd(temperature, temperature_leaf, relative_humidity, algorithm);
    double temp = this->vapor_pressure_deficit;
    return (temp);
}

double vpd::operator()() 
{
    double temp = this->vapor_pressure_deficit;
    return (temp);
}

CC BY-SA 4.0

4 Likes

Is there any chance you could post just the formulas used to calculate VPD?

I donā€™t know C (of any type) and I am wanting to calculate VPD in Python on the fly from live data. I donā€™t need finished code, I can turn formulas into code easily enough.

I have tried to figure it out but it is a bit too alien (only just got my head round OOC in python, it took a long time to remove the virus which is BASIC) for my brain to understand.

3 Likes

There are several VPD algorithms that are essentially estimations applicable to specific circumstances. Here are a couple that are most applicable (with reasonable error) for the temperature ranges weā€™d typically consider. Itā€™s been awhile since I looked at this but from what I recall, three steps, here:

  1. Saturation pressure (aka partial pressure of water)
  2. Vapor pressure
  3. Vapor pressure deficit

(1) Saturation pressure

These calculate the ā€œsaturation pressureā€:

Goff Gratch (1984):

where the equations differ depending if the temperature is > 0 celcius or < 0 celcius, respectively. The variables a(n), b(n), c(n), and g(n) are fixed coefficients:

Note that temperatures (T) input to the Goff-Gratch algorithm is in Kelvin and output is hPa (kPa = hPa / 10).

Another one,

Teten (1960s?):

Accurate for temperatures > 0 Celcius only:

where temperature (t) for Teten is in Celcius and output is kPa.

(2) Vapor Pressure

Then you calculate the vapor pressure of the atmosphere from the saturation pressure:

vapor pressure atmosphere = Rh * Es

and the vapor pressure of the leaf:

vapor pressure leaf = (1) * Es

Es is from the above calculated saturation pressure. Rh is the relative humidity. Calculate both the leaf and the atmosphere vapor pressures.

A leaf has 100% humidity (but the temperature may be different). For simplicity, you can estimate the leaf temperature or just say itā€™s the same as the surrounding air. The leaf temperature does impact the VPD and is an important consideration for determining the leaf transpiration.

(3) Vapor pressure deficit

VPD = (vapor pressure leaf) - (vapor pressure atmosphere)

Done. Pay attention to consistency of the units when applying these algorithms.

Some interesting observations, notice that the vapor pressure (partial pressures) is distilled down to the difference in the relative humidity between the leaf and the surrounding air! A non-dead leaf is considered to be ā€œ100% humidā€ no matter the temperature. If the air happens to also be 100% humid and the temperature of the leaf and the air happen to be the same, VPD would be zero = no transpiration possible.


The specific portion for calculating the saturation pressure in the C / C++ code is (for Goff Gratch):

double a1 = -7.90298 * (373.16 / Tkelvin() - 1.0);
double a2 = 5.02808 * log10(373.16 / Tkelvin() );
double a3 = (-1.3816 / 10000000) * (powf(10, 11.344*(1.0 - Tkelvin() / 373.16)) - 1.0);
double a4 = (8.1328 / 1000) * (powf(10, -3.49149*(373.16 / Tkelvin() - 1.0) - 1.0) );
double vapor_pressure = a1 + a2 + a3 + a4 + log10(1013.246);
return (powf(10.0,vapor_pressure)/10.0);

where TKelvin is the temperature in Kelvin. powf in the above calculates 10^(some number) as a floating point number. log10 is the log base 10 of some number. Other operators are typical mathematical operations. Double means floating point number (not integer). Most of the rest of the code is doing other things such as converting temperatures. Compare this to the above formula for Goff-Gratch.

This would be the ā€œmeatā€ of the problem(step 1). Then apply steps two and three as noted above.

It should be straight forward to convert that portion to over to Python since itā€™s mainly maths. Let me know if you run into trouble.

5 Likes

Iā€™ve been using the VPD class (ported to C#) for quite some time now. I recently went ahead and made a new page that can render the VPD chart around a specific point (Temp/RH). This will be used to render an overlay on my stream showing the real-time VPD using SensorPush data.

Thanks again for this @Northern_Loki ā€“ this was a big help getting started.

8 Likes

Cool! Iā€™m excited that you were able to find it helpful towards adding that feature to your system.

Seeing folk finding use for some of this stuff is encouraging toward future works. Thank you.

3 Likes

This is great. Definitely going to have a play with this at the weekend. Was thinking about writing something like this for my app, would definitely be a good start to get my head around the intricacies of VPD

2 Likes

Seeing folk finding use for some of this stuff is encouraging toward future works. Thank you.

:pray: :pray: :pray:

2 Likes

Iā€™ve made several updates to the temperature conversion classes:

  • Added Rankine units.
  • Set the base class to Celcius such that any mathematical operations using the temperature types are always performed in Celcius and then converted back to the target temperature unit. Math with temperature, in some cases, is nonsensical since we should be talking temperature deltas. Though, as a class, mathematical formulas can utilize the conversions allowing for flexibility. Just be aware that additions between two different units will always be converted to Celcius for the operation, first.
  • Refactored code such that temperature types are preserved internally. Previously, everything was converted to double float internally.
  • Fixed speeling error on faranheit.

This update will be utilized for any additional sourcecode that utilizes these classes and replaces the original source in the OP.

Temperature conversion classes:

//
// temperature_types.h
// Version timestamp: 2-9-2020, 1:33 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# pragma once

# include <string>
# include <sstream>
# include <boost/variant.hpp>
# include <iostream>

# include "Conversion_Constants.h"

class celcius; class kelvin; class Temperature; class fahrenheit; class rankine;
typedef boost::variant<celcius, kelvin, fahrenheit, rankine, double> celcius_variant;
typedef boost::variant<celcius, kelvin, fahrenheit, rankine, double> kelvin_variant;
typedef boost::variant<celcius, kelvin, fahrenheit, rankine, double> fahrenheit_variant;
typedef boost::variant<celcius, kelvin, fahrenheit, rankine, double> rankine_variant;

class fahrenheit
{
    
public:
    double degrees_fahrenheit = 0;
    fahrenheit()
        : degrees_fahrenheit(0) {}
    fahrenheit(const fahrenheit& c) { degrees_fahrenheit = c.degrees_fahrenheit; } // Copy contructor
    fahrenheit(double r) { degrees_fahrenheit = r; }
    fahrenheit(fahrenheit_variant &r);
    void operator=(fahrenheit_variant &temp2);
    virtual fahrenheit operator-(fahrenheit_variant temp2);
    virtual fahrenheit operator+(fahrenheit_variant temp2); 
    virtual fahrenheit operator*(fahrenheit_variant temp2); 
    virtual fahrenheit operator/(fahrenheit_variant temp2); 
    virtual fahrenheit operator-=(fahrenheit_variant temp2);
    virtual fahrenheit operator+=(fahrenheit_variant temp2); 
    virtual fahrenheit operator++(int incr);
    virtual fahrenheit operator--(int incr); 
    virtual fahrenheit operator*=(fahrenheit_variant temp2);
    virtual fahrenheit operator/=(fahrenheit_variant temp2); 
    virtual double operator()(fahrenheit_variant temp2);
    virtual double operator()(); 
    virtual bool operator>(fahrenheit_variant temp2); 
    virtual bool operator<(fahrenheit_variant temp2); 
    virtual bool operator>=(fahrenheit_variant temp2); 
    virtual bool operator<=(fahrenheit_variant temp2); 
    virtual bool operator==(fahrenheit_variant temp2); 
    virtual bool operator!=(fahrenheit_variant temp2); 
    virtual operator celcius();
    virtual operator kelvin();
    virtual operator rankine();

    friend std::ostream& operator<<(std::ostream& lhs, const fahrenheit& rhs)
    {
        return (lhs << rhs.degrees_fahrenheit);
    }
    
    friend fahrenheit operator+(const double &c1, fahrenheit c2); 
    friend fahrenheit operator*(const double &c1, fahrenheit c2); 
    friend fahrenheit operator/(const double &c1, fahrenheit c2); 
    friend fahrenheit operator-(const double &c1, fahrenheit c2); 
    
    explicit operator double() const { return degrees_fahrenheit;}
    explicit operator float() const { return degrees_fahrenheit;}
    explicit operator int() const { return (int)(degrees_fahrenheit + 0.5);}
};


class kelvin 
{
    
public:
    double degrees_kelvin = 0;
    kelvin()
        : degrees_kelvin(0) {}
    kelvin(const kelvin& c) { degrees_kelvin = c.degrees_kelvin; } // Copy contructor
    kelvin(double r) { degrees_kelvin = r; }
    kelvin(kelvin_variant &r);
    void operator=(kelvin_variant &temp2);
    virtual kelvin operator-(kelvin_variant temp2);
    virtual kelvin operator+(kelvin_variant temp2); 
    virtual kelvin operator*(kelvin_variant temp2); 
    virtual kelvin operator/(kelvin_variant temp2); 
    virtual kelvin operator-=(kelvin_variant temp2);
    virtual kelvin operator+=(kelvin_variant temp2); 
    virtual kelvin operator++(int incr);
    virtual kelvin operator--(int incr); 
    virtual kelvin operator*=(kelvin_variant temp2);
    virtual kelvin operator/=(kelvin_variant temp2); 
    virtual double operator()(kelvin_variant temp2); 
    virtual double operator()(); 
    virtual bool operator>(kelvin_variant temp2); 
    virtual bool operator<(kelvin_variant temp2); 
    virtual bool operator>=(kelvin_variant temp2); 
    virtual bool operator<=(kelvin_variant temp2); 
    virtual bool operator==(kelvin_variant temp2); 
    virtual bool operator!=(kelvin_variant temp2); 
    virtual operator celcius();
    virtual operator fahrenheit();
    virtual operator rankine();

    friend std::ostream& operator<<(std::ostream& lhs, const kelvin& rhs)
    {
        return (lhs << rhs.degrees_kelvin);
    }
    
    friend kelvin operator+(const double &c1, kelvin c2); 
    friend kelvin operator*(const double &c1, kelvin c2); 
    friend kelvin operator/(const double &c1, kelvin c2); 
    friend kelvin operator-(const double &c1, kelvin c2); 
    
    explicit operator double() const { return degrees_kelvin;}
    explicit operator float() const { return degrees_kelvin;}
    explicit operator int() const { return (int)(degrees_kelvin + 0.5);}
};


class celcius
{
    
public:
    double degrees_celcius = 0;
    celcius()
        : degrees_celcius(0) {}
    celcius(const celcius& c) { degrees_celcius = c.degrees_celcius; } // Copy contructor
    celcius(double r) { degrees_celcius = r; }
    celcius(celcius_variant &r);
    void operator=(celcius_variant &temp2);
    virtual celcius operator-(celcius_variant temp2);
    virtual celcius operator+(celcius_variant temp2); 
    virtual celcius operator*(celcius_variant temp2); 
    virtual celcius operator/(celcius_variant temp2); 
    virtual celcius operator-=(celcius_variant temp2);
    virtual celcius operator+=(celcius_variant temp2); 
    virtual celcius operator++(int incr);
    virtual celcius operator--(int incr); 
    virtual celcius operator*=(celcius_variant temp2);
    virtual celcius operator/=(celcius_variant temp2); 
    virtual double operator()(celcius_variant temp2); 
    virtual double operator()(); 
    virtual bool operator>(celcius_variant temp2); 
    virtual bool operator<(celcius_variant temp2); 
    virtual bool operator>=(celcius_variant temp2); 
    virtual bool operator<=(celcius_variant temp2); 
    virtual bool operator==(celcius_variant temp2); 
    virtual bool operator!=(celcius_variant temp2); 
    virtual operator kelvin();
    virtual operator fahrenheit();
    virtual operator rankine();
    
    friend std::ostream& operator<<(std::ostream& lhs, const celcius& rhs)
    {
        return (lhs << rhs.degrees_celcius);
    }
    
    friend celcius operator+(const double &c1, const celcius &c2); 
    friend celcius operator*(const double &c1, const celcius &c2); 
    friend celcius operator/(const double &c1, const celcius &c2); 
    friend celcius operator-(const double &c1, const celcius &c2); 
    
    explicit operator double() const { return degrees_celcius;}
    explicit operator float() const { return degrees_celcius;}
    explicit operator int() const { return (int)(degrees_celcius + 0.5);}
    
};

class rankine
{
    
public:
    double degrees_rankine = 0;
    rankine()
        : degrees_rankine(0) {}
    rankine(const rankine& c) { degrees_rankine = c.degrees_rankine; } // Copy contructor
    rankine(double r) { degrees_rankine = r; }
    rankine(rankine_variant &r);
    void operator=(rankine_variant &temp2);
    virtual rankine operator-(rankine_variant temp2);
    virtual rankine operator+(rankine_variant temp2); 
    virtual rankine operator*(rankine_variant temp2); 
    virtual rankine operator/(rankine_variant temp2); 
    virtual rankine operator-=(rankine_variant temp2);
    virtual rankine operator+=(rankine_variant temp2); 
    virtual rankine operator++(int incr);
    virtual rankine operator--(int incr); 
    virtual rankine operator*=(rankine_variant temp2);
    virtual rankine operator/=(rankine_variant temp2); 
    virtual double operator()(rankine_variant temp2); 
    virtual double operator()(); 
    virtual bool operator>(rankine_variant temp2); 
    virtual bool operator<(rankine_variant temp2); 
    virtual bool operator>=(rankine_variant temp2); 
    virtual bool operator<=(rankine_variant temp2); 
    virtual bool operator==(rankine_variant temp2); 
    virtual bool operator!=(rankine_variant temp2); 
    virtual operator kelvin();
    virtual operator fahrenheit();
    virtual operator celcius();
    
    friend std::ostream& operator<<(std::ostream& lhs, const rankine& rhs)
    {
        return (lhs << rhs.degrees_rankine);
    }
    
    friend rankine operator+(const double &c1, const rankine &c2); 
    friend rankine operator*(const double &c1, const rankine &c2); 
    friend rankine operator/(const double &c1, const rankine &c2); 
    friend rankine operator-(const double &c1, const rankine &c2); 
    
    explicit operator double() const { return degrees_rankine;}
    explicit operator float() const { return degrees_rankine;}
    explicit operator int() const { return (int)(degrees_rankine + 0.5);}
};



class tcelcius_variant : public boost::static_visitor<celcius>
{
public:
    celcius operator()(double temperature) const
    {
        return (temperature);
    }
    
    celcius operator()(celcius temperature) const
    {
        return (temperature);
    }
    
    celcius operator()(kelvin temperature) const
    {
        celcius temp = temperature.degrees_kelvin - 273.15;
        return (temp);
    }
    
    celcius operator()(fahrenheit temperature) const
    {
        celcius temp = (temperature.degrees_fahrenheit - 32.0) / (1.8);
        return (temp);
    }
    
    celcius operator()(rankine temperature) const
    {
        celcius temp = (temperature.degrees_rankine -  491.67) / (1.8);
        return (temp);
    }
    
};

class tkelvin_variant : public boost::static_visitor<kelvin>
{
public:
    kelvin operator()(double temperature) const
    {
        return (temperature);
    }
    
    kelvin operator()(kelvin temperature) const
    {
        return (temperature);
    }
    
    kelvin operator()(celcius temperature) const
    {
        kelvin temp = temperature.degrees_celcius + 273.15;
        return (temp);
    }
    
    kelvin operator()(fahrenheit temperature) const
    {
        kelvin temp = (temperature.degrees_fahrenheit - 32.0) / (1.8) + 273.15;
        return (temp);
    }
    
    kelvin operator()(rankine temperature) const
    {
        kelvin temp = (temperature.degrees_rankine) / (1.8);
        return (temp);
    }
    
};

class tfahrenheit_variant : public boost::static_visitor<fahrenheit>
{
public:
    fahrenheit operator()(double temperature) const
    {
        return (temperature);
    }
    
    fahrenheit operator()(fahrenheit temperature) const
    {
        return (temperature);
    }
    
    fahrenheit operator()(celcius temperature) const
    {
        fahrenheit temp = temperature.degrees_celcius * (1.8) + 32.0;
        return (temp);
    }
    
    fahrenheit operator()(kelvin temperature) const
    {
        fahrenheit temp = (temperature.degrees_kelvin) * (1.8) - 459.67;
        return (temp);
    }
    
    fahrenheit operator()(rankine temperature) const
    {
        fahrenheit temp = (temperature.degrees_rankine) - 459.67;
        return (temp);
    }
    
};

class trankine_variant : public boost::static_visitor<rankine>
{
public:
    rankine operator()(double temperature) const
    {
        return (temperature);
    }
    
    rankine operator()(rankine temperature) const
    {
        return (temperature);
    }
    
    rankine operator()(celcius temperature) const
    {
        rankine temp = (temperature.degrees_celcius + 273.15) * (1.8);
        return (temp);
    }
    
    rankine operator()(kelvin temperature) const
    {
        rankine temp = (temperature.degrees_kelvin) * (1.8);
        return (temp);
    }
    
    rankine operator()(fahrenheit temperature) const
    {
        rankine temp = (temperature.degrees_fahrenheit) + 459.67;
        return (temp);
    }
    
};
//
// Conversion_Utilities.h
// Version timestamp: 2-9-2020, 7:50 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# pragma once
# include "temperature_types.h"
# include "power_types.h"
# include "volume_types.h"
# include "pressure_types.h"
# include "mass_types.h"
# include "volume_types.h"

# ifdef __cplusplus
extern "C" {
# endif

    int Conversion_UtilitiesTest();

# ifdef __cplusplus
}
# endif
//
// Kelvin.cpp
// Version timestamp: 2-9-2020, 1:33 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# include "temperature_types.h"

kelvin::kelvin(kelvin_variant &r)
{
    kelvin_variant c = r;
    kelvin temp = boost::apply_visitor(tkelvin_variant(), c);
    this->degrees_kelvin = temp.degrees_kelvin;
}

kelvin::operator fahrenheit()
{
    fahrenheit temp = (this->degrees_kelvin) * (1.8) - 459.67;
    return (temp);
}

kelvin::operator celcius()
{
    celcius temp = this->degrees_kelvin - 273.15;
    return (temp);
}

kelvin::operator rankine()
{
    rankine temp = this->degrees_kelvin * (1.8);
    return (temp);
}


void kelvin::operator=(kelvin_variant &temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    this->degrees_kelvin = temp.degrees_kelvin;
}

kelvin kelvin::operator-(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp -= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((kelvin)temp);
}

kelvin kelvin::operator+(celcius_variant temp2) 
{
    celcius temp = celcius(*this);
    temp += boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((kelvin)temp);
}

kelvin operator+(const double &c1, kelvin c2)
{
    celcius temp = c1 + celcius(c2);
    return ((kelvin)temp);
}

kelvin operator*(const double &c1, kelvin c2)
{
    celcius temp = c1 * celcius(c2);
    return ((kelvin)temp);
}

kelvin operator/(const double &c1, kelvin c2)
{
    celcius temp = c1 / celcius(c2);
    return ((kelvin)temp);
}

kelvin operator-(const double &c1, kelvin c2)
{
    celcius temp = c1 - celcius(c2);
    return ((kelvin)temp);
}

kelvin kelvin::operator*(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp *= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((kelvin)temp);
}

kelvin kelvin::operator/(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp /= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((kelvin)temp);
}

double kelvin::operator()(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    return (temp.degrees_kelvin);
}

double kelvin::operator()() 
{
    double temp = this->degrees_kelvin;
    return (temp);
}

kelvin kelvin::operator-=(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp - boost::apply_visitor(tcelcius_variant(), temp2);
    kelvin tempk = temp;
    this->degrees_kelvin = tempk.degrees_kelvin;
    
    return (tempk);
}

kelvin kelvin::operator+=(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp + boost::apply_visitor(tcelcius_variant(), temp2);
    kelvin tempk = temp;
    this->degrees_kelvin = tempk.degrees_kelvin;
    
    return (tempk);
}

kelvin kelvin::operator++(int incr) 
{
    this->degrees_kelvin +=  1.0;
    return (this->degrees_kelvin);
}

kelvin kelvin::operator--(int incr) 
{
    this->degrees_kelvin -= 1.0;
    return (this->degrees_kelvin);
}

kelvin kelvin::operator*=(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp * boost::apply_visitor(tcelcius_variant(), temp2);
    kelvin tempk = temp;
    this->degrees_kelvin = tempk.degrees_kelvin;
    
    return (tempk);
}

kelvin kelvin::operator/=(kelvin_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp / boost::apply_visitor(tcelcius_variant(), temp2);
    kelvin tempk = temp;
    this->degrees_kelvin = tempk.degrees_kelvin;
    
    return (tempk);
}

bool kelvin::operator>(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (this->degrees_kelvin > temp.degrees_kelvin) return (1);
    return (0);
}

bool kelvin::operator<(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (this->degrees_kelvin < temp.degrees_kelvin) return (1);
    return (0);
}

bool kelvin::operator==(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (fabs(temp.degrees_kelvin - this->degrees_kelvin) <= 
    __DBL_EPSILON__ * fmax(fabs(temp.degrees_kelvin), fabs(this->degrees_kelvin))) return (1);
    return (0);
}

bool kelvin::operator!=(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (fabs(temp.degrees_kelvin - this->degrees_kelvin) <= 
        __DBL_EPSILON__ * fmax(fabs(temp.degrees_kelvin), fabs(this->degrees_kelvin))) return (0);
    return (1);
}

bool kelvin::operator>=(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (this->degrees_kelvin >= temp.degrees_kelvin) return (1);
    return (0);
}
bool kelvin::operator<=(kelvin_variant temp2) 
{
    kelvin temp = boost::apply_visitor(tkelvin_variant(), temp2);
    if (this->degrees_kelvin <= temp.degrees_kelvin) return (1);
    return (0);
}
//
// fahrenheit.cpp
// Version timestamp: 2-9-2020, 1:33 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# include "temperature_types.h"

fahrenheit::fahrenheit(fahrenheit_variant &r)
{
    fahrenheit_variant c = r;
    
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), c);
    this->degrees_fahrenheit = temp.degrees_fahrenheit;
}

fahrenheit::operator kelvin()
{
    kelvin temp = (this->degrees_fahrenheit - 32.0) / (1.8) + 273.15;
    return (temp);
}

fahrenheit::operator celcius()
{
    celcius temp = (this->degrees_fahrenheit - 32.0) / (1.8);
    return (temp);
}

fahrenheit::operator rankine()
{
    rankine temp = (this->degrees_fahrenheit + 459.67);
    return (temp);
}

void fahrenheit::operator=(fahrenheit_variant &temp2) 
{
    fahrenheit temp = boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_fahrenheit = temp.degrees_fahrenheit;
}

fahrenheit fahrenheit::operator-(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp -= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((fahrenheit)temp);
}

fahrenheit fahrenheit::operator+(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp += boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((fahrenheit)temp);
}

fahrenheit operator+(const double &c1, fahrenheit c2)
{
    celcius temp = c1 + celcius(c2);
    return ((fahrenheit)temp);
}

fahrenheit operator*(const double &c1, fahrenheit c2)
{
    celcius temp = c1 * celcius(c2);
    return ((fahrenheit)temp);
}

fahrenheit operator/(const double &c1, fahrenheit c2)
{
    celcius temp = c1 / celcius(c2);
    return ((fahrenheit)temp);
}

fahrenheit operator-(const double &c1, fahrenheit c2)
{
    celcius temp = c1 - celcius(c2);
    return ((fahrenheit)temp);
}

fahrenheit fahrenheit::operator*(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp *= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((fahrenheit)temp);
}

fahrenheit fahrenheit::operator/(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp /= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((fahrenheit)temp);
}

double fahrenheit::operator()(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    return (temp.degrees_fahrenheit);
}

double fahrenheit::operator()() 
{
    double temp = this->degrees_fahrenheit;
    return (temp);
}

fahrenheit fahrenheit::operator-=(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp - boost::apply_visitor(tcelcius_variant(), temp2);
    fahrenheit tempf = temp;
    this->degrees_fahrenheit = tempf.degrees_fahrenheit;
    
    return (tempf);
}

fahrenheit fahrenheit::operator+=(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp + boost::apply_visitor(tcelcius_variant(), temp2);
    fahrenheit tempf = temp;
    this->degrees_fahrenheit = tempf.degrees_fahrenheit;
    
    return (tempf);
}

fahrenheit fahrenheit::operator++(int incr) 
{
    this->degrees_fahrenheit +=  1.0;
    return (this->degrees_fahrenheit);
}

fahrenheit fahrenheit::operator--(int incr) 
{
    this->degrees_fahrenheit -=  1.0;
    return (this->degrees_fahrenheit);
}

fahrenheit fahrenheit::operator*=(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp * boost::apply_visitor(tcelcius_variant(), temp2);
    fahrenheit tempf = temp;
    this->degrees_fahrenheit = tempf.degrees_fahrenheit;
    
    return (tempf);
}

fahrenheit fahrenheit::operator/=(fahrenheit_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp / boost::apply_visitor(tcelcius_variant(), temp2);
    fahrenheit tempf = temp;
    this->degrees_fahrenheit = tempf.degrees_fahrenheit;
    
    return (tempf);
}

bool fahrenheit::operator>(fahrenheit_variant temp2) 
{ 
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (this->degrees_fahrenheit > temp.degrees_fahrenheit) return (1);
    return (0);
}

bool fahrenheit::operator<(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (this->degrees_fahrenheit < temp.degrees_fahrenheit) return (1);
    return (0);
}

bool fahrenheit::operator==(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (fabs(temp.degrees_fahrenheit - this->degrees_fahrenheit) <= 
    __DBL_EPSILON__ * fmax(fabs(temp.degrees_fahrenheit), fabs(this->degrees_fahrenheit))) return (1);
    return (0);
}

bool fahrenheit::operator!=(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (fabs(temp.degrees_fahrenheit - this->degrees_fahrenheit) <= 
    __DBL_EPSILON__ * fmax(fabs(temp.degrees_fahrenheit), fabs(this->degrees_fahrenheit))) return (0);
    return (1);
}

bool fahrenheit::operator>=(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (this->degrees_fahrenheit >= temp.degrees_fahrenheit) return (1);
    return (0);
}
bool fahrenheit::operator<=(fahrenheit_variant temp2) 
{
    fahrenheit temp = boost::apply_visitor(tfahrenheit_variant(), temp2);
    if (this->degrees_fahrenheit <= temp.degrees_fahrenheit) return (1);
    return (0);
}
//
// Celcius.cpp
// Version timestamp: 2-9-2020, 1:33 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# include "temperature_types.h"

celcius::celcius(celcius_variant &r)
{
    celcius_variant c = r;
    
    celcius temp = boost::apply_visitor(tkelvin_variant(), c);
    this->degrees_celcius = temp.degrees_celcius;
}

celcius::operator kelvin()
{
    kelvin temp = this->degrees_celcius + 273.15;
    return (temp);
}

celcius::operator fahrenheit()
{
    fahrenheit temp = this->degrees_celcius * (1.8) + 32.0;
    return (temp);
}

celcius::operator rankine()
{
    rankine temp = (this->degrees_celcius + 273.15) * (1.8);
    return (temp);
}

void celcius::operator=(celcius_variant &temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_celcius = temp.degrees_celcius;
}

celcius celcius::operator-(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius - boost::apply_visitor(tcelcius_variant(), temp2);
    return (temp);
}

celcius celcius::operator+(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius + boost::apply_visitor(tcelcius_variant(), temp2);
    return (temp);
}

celcius operator+(const double &c1, const celcius &c2)
{
    celcius temp = c1 + c2.degrees_celcius;
    return (temp);
}

celcius operator*(const double &c1, const celcius &c2)
{
    celcius temp = c1 * c2.degrees_celcius;
    return (temp);
}

celcius operator/(const double &c1, const celcius &c2)
{
    celcius temp = c1 / c2.degrees_celcius;
    return (temp);
}

celcius operator-(const double &c1, const celcius &c2)
{
    celcius temp = c1 - c2.degrees_celcius;
    return (temp);
}

celcius celcius::operator++(int incr) 
{
    this->degrees_celcius +=  1.0;
    return (this->degrees_celcius);
}

celcius celcius::operator--(int incr) 
{
    this->degrees_celcius -=  1.0;
    return (this->degrees_celcius);
}

celcius celcius::operator*(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius * boost::apply_visitor(tcelcius_variant(), temp2);
    return (temp);
}

celcius celcius::operator/(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius / boost::apply_visitor(tcelcius_variant(), temp2);
    return (temp);
}

double celcius::operator()(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    return (temp.degrees_celcius);
}

double celcius::operator()() 
{
    celcius temp = this->degrees_celcius;
    return (temp.degrees_celcius);
}

celcius celcius::operator-=(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius - boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_celcius = temp.degrees_celcius;
    return (this->degrees_celcius);
}

celcius celcius::operator+=(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius + boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_celcius = temp.degrees_celcius;
    return (this->degrees_celcius);
}

celcius celcius::operator*=(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius * boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_celcius = temp.degrees_celcius;
    return (this->degrees_celcius);
}

celcius celcius::operator/=(celcius_variant temp2) 
{
    celcius temp = this->degrees_celcius / boost::apply_visitor(tcelcius_variant(), temp2);
    this->degrees_celcius = temp.degrees_celcius;
    return (this->degrees_celcius);
}

bool celcius::operator>(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (this->degrees_celcius > temp.degrees_celcius) return (1);
    return (0);
}

bool celcius::operator<(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (this->degrees_celcius < temp.degrees_celcius) return (1);
    return (0);
}

bool celcius::operator==(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (fabs(temp.degrees_celcius - this->degrees_celcius) <= 
        __DBL_EPSILON__ * fmax(fabs(temp.degrees_celcius), fabs(this->degrees_celcius))) return (1);
    return (0);
}

bool celcius::operator!=(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (fabs(temp.degrees_celcius - this->degrees_celcius) <=
        __DBL_EPSILON__ * fmax(fabs(temp.degrees_celcius), fabs(this->degrees_celcius))) return (0);
    return (1);
}

bool celcius::operator>=(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (this->degrees_celcius >= temp.degrees_celcius) return (1);
    return (0);
}

bool celcius::operator<=(celcius_variant temp2) 
{
    celcius temp = boost::apply_visitor(tcelcius_variant(), temp2);
    if (this->degrees_celcius <= temp.degrees_celcius) return (1);
    return (0);
}

CC BY-SA 4.0

3 Likes
//
// Rankine.cpp
// Version timestamp: 2-9-2020, 1:33 PM
//
// Attribution : Copyright (c) 2020 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# include "temperature_types.h"

rankine::rankine(rankine_variant &r)
{
    rankine_variant c = r;
    rankine temp = boost::apply_visitor(trankine_variant(), c);
    this->degrees_rankine = temp.degrees_rankine;
}

rankine::operator fahrenheit()
{
    fahrenheit temp = (this->degrees_rankine) - 459.67;
    return (temp);
}

rankine::operator celcius()
{
    celcius temp = (this->degrees_rankine - 491.67) / (1.8);
    return (temp);
}

rankine::operator kelvin()
{
    kelvin temp = this->degrees_rankine * (1.8);
    return (temp);
}

void rankine::operator=(rankine_variant &temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    this->degrees_rankine = temp.degrees_rankine;
}

rankine rankine::operator-(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp -= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((rankine)temp);
}

rankine rankine::operator+(celcius_variant temp2) 
{
    celcius temp = celcius(*this);
    temp += boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((rankine)temp);
}

rankine operator+(const double &c1, rankine c2)
{
    celcius temp = c1 + celcius(c2);
    return ((rankine)temp);
}

rankine operator*(const double &c1, rankine c2)
{
    celcius temp = c1 * celcius(c2);
    return ((rankine)temp);
}

rankine operator/(const double &c1, rankine c2)
{
    celcius temp = c1 / celcius(c2);
    return ((rankine)temp);
}

rankine operator-(const double &c1, rankine c2)
{
    celcius temp = c1 - celcius(c2);
    return ((rankine)temp);
}

rankine rankine::operator*(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp *= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((rankine)temp);
}

rankine rankine::operator/(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp /= boost::apply_visitor(tcelcius_variant(), temp2);
    
    return ((rankine)temp);
}

double rankine::operator()(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    return (temp.degrees_rankine);
}

double rankine::operator()() 
{
    double temp = this->degrees_rankine;
    return (temp);
}

rankine rankine::operator-=(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp - boost::apply_visitor(tcelcius_variant(), temp2);
    rankine tempk = temp;
    this->degrees_rankine = tempk.degrees_rankine;
    
    return (tempk);
}

rankine rankine::operator+=(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp + boost::apply_visitor(tcelcius_variant(), temp2);
    rankine tempk = temp;
    this->degrees_rankine = tempk.degrees_rankine;
    
    return (tempk);
}

rankine rankine::operator++(int incr) 
{
    this->degrees_rankine +=  1.0;
    return (this->degrees_rankine);
}

rankine rankine::operator--(int incr) 
{
    this->degrees_rankine -= 1.0;
    return (this->degrees_rankine);
}

rankine rankine::operator*=(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp * boost::apply_visitor(tcelcius_variant(), temp2);
    rankine tempk = temp;
    this->degrees_rankine = tempk.degrees_rankine;
    
    return (tempk);
}

rankine rankine::operator/=(rankine_variant temp2) 
{
    celcius temp = celcius(*this);
    temp = temp / boost::apply_visitor(tcelcius_variant(), temp2);
    rankine tempk = temp;
    this->degrees_rankine = tempk.degrees_rankine;
    
    return (tempk);
}

bool rankine::operator>(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (this->degrees_rankine > temp.degrees_rankine) return (1);
    return (0);
}

bool rankine::operator<(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (this->degrees_rankine < temp.degrees_rankine) return (1);
    return (0);
}

bool rankine::operator==(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (fabs(temp.degrees_rankine - this->degrees_rankine) <= 
    __DBL_EPSILON__ * fmax(fabs(temp.degrees_rankine), fabs(this->degrees_rankine))) return (1);
    return (0);
}

bool rankine::operator!=(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (fabs(temp.degrees_rankine - this->degrees_rankine) <= 
        __DBL_EPSILON__ * fmax(fabs(temp.degrees_rankine), fabs(this->degrees_rankine))) return (0);
    return (1);
}

bool rankine::operator>=(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (this->degrees_rankine >= temp.degrees_rankine) return (1);
    return (0);
}
bool rankine::operator<=(rankine_variant temp2) 
{
    rankine temp = boost::apply_visitor(trankine_variant(), temp2);
    if (this->degrees_rankine <= temp.degrees_rankine) return (1);
    return (0);
}

Vapor Pressure Deficit classes:

See earlier posts with the VPD class.

Definitions :

//
// Constants.h
// Version timestamp: 9-26-2018, 10:45 PM
//
// Attribution : Copyright (c) 2018 Northern_Loki (sha256::6F290BF833967127BE26C92C8F6B1C1A3949C55A7EABCEF3ECC785CD2D38D30D)
// License is granted under the Creative Commons Attribution-ShareAlike 4.0 International.  https://creativecommons.org/licenses/by-sa/4.0/
//
# pragma once

/* Euler's constant */
# define EULER 2.7182818284590452353602875

/* Avogadro's Constant SI unit (1/mol) */
# define NA (6.022140758 * pow(10,23))

/* Boltzmann's constant (J/K) */
# define BOLTZMANN (1.38064852 * (pow(10,āˆ’23)))


/* Stefan-Boltzmann's constant SI units (W/(m^2.K^4)) */
# define STEFAN_BOLTZMANN (5.67036713 * (pow(10,-8)))

/* Latent heat of vaporization 1ATM and 0 degrees C SI units (J/g) */
# define L0 2500

/* Latent heat of vaporization 1ATM and 20 degrees C SI units (J/g) */
# define L20 2450

/* Latent heat of vaporization 1ATM and 100 degrees C SI units (J/g) */
# define L100 2260

/* Density of dry air 1ATM and 0 degrees C SI units (kg/m^3) */
# define p_air0 1.2922

/* Isobaric heat capacity of dry air 1ATM and 0 degrees C SI units (J/kg K) */
# define Cp_air0 1010

/* Molecular weight of water (g/mol) */
# define M_H20 18.0


/**************/
/* Conversion */
/**************/
# define TO_DEGREE(radians) ((radians) * 57.295779513082320876798154814105)
# define TO_RADIAN(degrees) ((degrees) * 0.017453292519943295769236907684886)


/*********/
/* Time  */
/********/
/* Julian J2000 */
# define J2000 (2451545.0)

/* Julian UNIX epoch 0h Jan 1, 1970 */
# define UNIX_JULIAN_EPOCH (2440587.5)

/* Julian days per year */
# define JULIAN_DAYS_YEAR (365.25)

/* Julian days per century */
# define JULIAN_DAYS_CENTURY  (JULIAN_DAYS_YEAR) * 100.0

/* Solar days per century */
# define SOLAR_CENTURY (36524.22)

/* Hours per day*/
# define HOURS_DAY (24.0)

/* Minutes per hour */
# define MINUTES_HOUR (60.0)

/* Minutes per day */
# define MINUTES_DAY (MINUTES_HOUR) * (HOURS_DAY)

/* Seconds per minute*/
# define SECONDS_MINUTE (60.0)

/* Seconds per hour (3600) */
# define SECONDS_HOUR ((SECONDS_MINUTE) * (MINUTES_HOUR))

/* Seconds per day (86400) */
# define SECONDS_DAY ((HOURS_DAY) * (SECONDS_HOUR))

/* Mean tropical days per year */
# define MEAN_TROPICAL_DAYS_YEAR (365.242189)

/* Mean sidereal days per year */
# define SIDEREAL_DAYS_YEAR (365.25636)


/**************/
/* Distance   */
/**************/

/* Astronomical units. Kilometers per AU */ 
# define AU_KM (149597870.700) 


/**************/
/*   Solar   */
/*************/

/* Solar constant W/m^2 (averaged of a year) Page, 1986 */
# define SOLAR_CONSTANT 1366.9444

/* Planetary Atmospheric Albedo Mean */
# define ALBEDO_MEAN_Rp 0.3

/* Sun Blackbody Temperature in Kelvin */
# define SUN_BLACKBODY_TEMP 5777

/**************/
/* Pressure   */
/*************/

/* Average atmospheric pressure at sea level (Pascals) */
# define ATM1_AVE 101325.0
	
/* Pascals to millibars */
# define TO_MILLIBAR(pascal) (pascal / 100.0)
	
/* Millibars to pascals */
# define TO_PASCAL(millibars) (millibars * 100.0)

CC BY-SA 4.0

3 Likes

@Northern_Loki Do you have a git project or anything for this code? or you just post the sources here as and when you make any changes?

1 Like

A repository can be found over here: github link

I generally utilize a local version control system as part of a larger project. What is on github is not really a project of any sort, currently only updated occasionally, placed there for convenience, and it consists of the source posted on OG. Havenā€™t the time or inclination to build a thorough github ā€œexperienceā€ at this point. Barely have the time to work on the source :slight_smile:

.

5 Likes

Lokiā€™s is much more sophisticated and useful; but for anyone who is scared with compiled programs and likes the web I transposed his to plain jane JavaScript. Prints out the tables and nothing more. I used the buck 1981.

Feel free to modify and play with it anyway you like =)

5 Likes

I was hoping someone would contribute some additional options beyond the compiled c/c++. Excited. :+1:

Thanks @plant! Itā€™s a much more a compact, efficient, and portable implementation. Very nice work.

8 Likes

oh i so wish i found this forum 6 months beforeā€¦ nice job mateā€¦

7 Likes

Iā€™m having a matrix neo momentā€¦ waking in the chair, ā€œI know C++ā€. Show meā€¦
My hat off to you, outstanding work.

4 Likes

Awesome work @Northern_Loki.

Tagged for the trip down the rabbit holeā€¦ :call_me_hand:

1 Like