2
* Algorithms.cpp is part of Brewtarget, and is Copyright Philip G. Lee
3
* (rocketman768@gmail.com), 2009.
5
* Brewtarget is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* Brewtarget is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21
#include "Algorithms.h"
23
double* PlatoFromSG_20C20C = 0;
24
unsigned int PlatoFromSG_20C20C_order;
25
double* waterDensityPoly_C = 0;
26
unsigned int waterDensityPoly_C_order = 0;
30
if( PlatoFromSG_20C20C == 0 )
32
PlatoFromSG_20C20C = new double[4];
33
PlatoFromSG_20C20C_order = 3;
34
PlatoFromSG_20C20C[0] = -616.868;
35
PlatoFromSG_20C20C[1] = 1111.14;
36
PlatoFromSG_20C20C[2] = -630.272;
37
PlatoFromSG_20C20C[3] = 135.997;
40
if( waterDensityPoly_C == 0 )
42
waterDensityPoly_C = new double[4];
43
waterDensityPoly_C_order = 3;
44
waterDensityPoly_C[0] = 0.999924134;
45
waterDensityPoly_C[1] = 3.113930471e-5;
46
waterDensityPoly_C[2] = 6.268385468e-6;
47
waterDensityPoly_C[3] = 1.80544064e-8;
51
inline double intPow( double base, unsigned int pow )
60
// NOTE: order is the ORDER of the polynomial, NOT THE SIZE of the poly array.
61
double polyEval( double* poly, unsigned int order, double x )
65
for( ; order > 0; --order )
67
ret += poly[order] * intPow( x, order );
74
// Root finding of a polynomial via the secant method. Returns HUGE_VAL on failure.
75
double rootFind( double* poly, unsigned int order, double x0, double x1 )
77
double guesses[] = { x0, x1 };
79
double maxAllowableSeparation = fabs( x0 - x1 ) * 1e3;
81
while( fabs( guesses[0] - guesses[1] ) > ROOT_PRECISION )
83
newGuess = guesses[1] - (guesses[1] - guesses[0]) * polyEval( poly, order, guesses[1]) / ( polyEval( poly, order, guesses[1]) - polyEval( poly, order, guesses[0]) );
85
guesses[0] = guesses[1];
86
guesses[1] = newGuess;
88
if( fabs( guesses[0] - guesses[1] ) > maxAllowableSeparation )
95
double SG_20C20C_toPlato( double sg )
98
return polyEval(PlatoFromSG_20C20C, PlatoFromSG_20C20C_order, sg );
101
double PlatoToSG_20C20C( double plato )
104
double poly[PlatoFromSG_20C20C_order+1];
106
// Copy the polynomial, cuz we need to alter it.
107
for( int i = 0; i <= PlatoFromSG_20C20C_order; ++i )
109
poly[i] = PlatoFromSG_20C20C[i];
112
// After this, finding the root of the polynomial will be finding the SG.
115
return rootFind( poly, PlatoFromSG_20C20C_order, 1.000, 1.050 );
118
double getWaterDensity_kgL( double celsius )
121
return polyEval(waterDensityPoly_C, waterDensityPoly_C_order, celsius);
b'\\ No newline at end of file'