00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#ifndef SATCURVE_H
00023
#define SATCURVE_H
00024
00025
#include "steamproperty.h"
00026
#include "units.h"
00027
#include "steamcalculator.h"
00028
#include "common.h"
00029
#include "zeroin.h"
00030
#include "exception.h"
00031
00032
const int SAT_WATER=0;
00033
const int SAT_STEAM=1;
00034
00035
const int SAT_LOW_TEMP=2;
00036
00038
template<
class Ordinate,
class Abscissa,
int OrdinateAlt=0,
int AbscissaAlt=0>
00039 class SatCurveBase{
00040
00041
public:
00042
00043
virtual Ordinate solve(
const Abscissa &target,
const int &flags=SAT_WATER) = 0;
00044
00045
protected:
00046
00047
SatCurveBase(){}
00048
virtual ~
SatCurveBase(){}
00049
00050 Ordinate getOrdinate(
SteamCalculator S){
00051
return SteamProperty<Ordinate,OrdinateAlt>::get(S);
00052 }
00053
00054 Abscissa getAbscissa(
SteamCalculator S){
00055
return SteamProperty<Abscissa,AbscissaAlt>::get(S);
00056 }
00057
00058 };
00059
00061
00073
template<
class Ordinate,
class Abscissa,
int OrdinateAlt=0,
int AbscissaAlt=0>
00074 class SatCurve :
public SatCurveBase<Ordinate,Abscissa,OrdinateAlt,AbscissaAlt>{
00075
00076
00077
friend class ZeroIn<SatCurve,Temperature,Abscissa>;
00078
00079
public:
00080
00081
virtual ~SatCurve(){}
00082
00083
static Temperature getLowerBound(
const int &flags){
00084
00085
00086
00087
00088
00089
00090
00091
return T_TRIPLE;
00092 }
00093
00094
static Temperature getUpperBound(
const int &flags){
00095
00096
00097
00098
00099
00100
00101
00102
return T_CRIT;
00103 }
00104
00112 Ordinate
solve(
const Abscissa &target,
const int &flags=SAT_WATER){
00113
00114
ZeroIn<SatCurve,Abscissa,Temperature> z;
00115
00116
try{
00117
00118
00119
00120 this->target=target;
00121
00122
00123 Abscissa maxerror = fabs(target) * 0.002 * Percent;
00124
00125
00126 z.
setLowerBound(getLowerBound(flags));
00127
00128 z.
setUpperBound(getUpperBound(flags));
00129
00130
00131 z.
setTolerance(1e-10 * Kelvin);
00132
00133
if(flags & SAT_STEAM){
00134 z.
setMethod(&SatCurve::getAbscissaErrorSteam_T);
00135 }
else{
00136 z.
setMethod(&SatCurve::getAbscissaErrorWater_T);
00137 }
00138
00139 z.
visit(
this);
00140
00141
if(!z.
isSolved(maxerror)){
00142 stringstream s;
00143 s.flags(ios_base::showbase);
00144 s <<
"Unable to solve for target " <<
SteamProperty<Abscissa,AbscissaAlt>::name() <<
" = " << target <<
" (error was " << z.
getError() <<
", max allowed is " << maxerror <<
")";
00145
throw new Exception(s.str());
00146 }
00147
00148
00149
00150
if(flags & SAT_STEAM){
00151 S.
setSatSteam_T(z.
getSolution());
00152 }
else{
00153 S.
setSatWater_T(z.
getSolution());
00154 }
00155
00156
return SatCurveBase<Ordinate,Abscissa,OrdinateAlt,AbscissaAlt>::getOrdinate(S);
00157
00158 }
catch(Exception *e){
00159 stringstream s;
00160 s <<
"SatCurve<" <<
SteamProperty<Ordinate,OrdinateAlt>::name() <<
"," <<
SteamProperty<Abscissa,AbscissaAlt>::name() <<
">::solve(" <<
SteamProperty<Abscissa,AbscissaAlt>::name() <<
" = " << target <<
"," << (flags & SAT_STEAM ?
"SAT_STEAM" :
"SAT_WATER") <<
"): " << e->what();
00161
delete e;
00162
throw new Exception(s.str());
00163 }
00164 }
00165
00166
private:
00167
00168 Abscissa getAbscissaErrorWater_T(
const Temperature &T){
00169
00170
00171
00172 S.
setSatWater_T(T);
00173
00174
00175
return SatCurveBase<Ordinate,Abscissa,OrdinateAlt,AbscissaAlt>::getAbscissa(S) - target;
00176 }
00177
00178 Abscissa getAbscissaErrorSteam_T(
const Temperature &T){
00179
00180
00181
00182 S.
setSatSteam_T(T);
00183
00184
00185
return SatCurveBase<Ordinate,Abscissa,OrdinateAlt,AbscissaAlt>::getAbscissa(S) - target;
00186 }
00187
00188
SteamCalculator S;
00189 Abscissa target;
00190 };
00191
00193
00196
template<
class Ordinate,
int OrdinateAlt>
00197 class SatCurve<Ordinate,Temperature,OrdinateAlt,0>
00198 :
public SatCurveBase<Ordinate,Temperature,OrdinateAlt,0>{
00199
00200
public:
00201
00202
SatCurve() :
SatCurveBase<Ordinate,Temperature,OrdinateAlt,0>(){}
00203
virtual ~
SatCurve(){}
00204
00205
virtual Ordinate
solve(
const Temperature &T,
const int &flags=SAT_WATER){
00206
SteamCalculator S;
00207
if(flags & SAT_STEAM){
00208 S.
setSatSteam_T(T);
00209 }
else{
00210 S.
setSatWater_T(T);
00211 }
00212
return SatCurveBase<Ordinate,Temperature,OrdinateAlt,0>::getOrdinate(S);
00213 }
00214
00215 };
00216
00218
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
#endif