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