Main Page | Class Hierarchy | Class List | File List | Class Members | Related Pages

satcurve.h

00001 /* 00002 00003 freesteam - IAPWS-IF97 steam tables library 00004 Copyright (C) 2004-2005 John Pye 00005 00006 This program is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU General Public License 00008 as published by the Free Software Foundation; either version 2 00009 of the License, or (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 // ZeroIn will be finding the TEMPERATURE at which SatCurve's ABSCISSA has the desired value: 00077 friend class ZeroIn<SatCurve,Temperature,Abscissa>; 00078 00079 public: 00080 00081 virtual ~SatCurve(){} 00082 00083 static Temperature getLowerBound(const int &flags){ 00084 /* 00085 if(flags & SAT_WATER 00086 && !(flags & SAT_LOW_TEMP) 00087 ){ 00088 return T_TRIPLE; 00089 } 00090 */ 00091 return T_TRIPLE; 00092 } 00093 00094 static Temperature getUpperBound(const int &flags){ 00095 /* 00096 if(flags & SAT_WATER 00097 && !(flags & SAT_LOW_TEMP) 00098 ){ 00099 return T_MIN_VOL; 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 //cerr << endl << "SatCurve<" << SteamProperty<Ordinate,OrdinateAlt>::name() << "," << SteamProperty<Abscissa,AbscissaAlt>::name() << ">::solve: Trying to solve for " << SteamProperty<Abscissa,AbscissaAlt>::name() << " = " << target; 00119 00120 this->target=target; 00121 00122 // Always try to solve to accuracy of 0.001% of the target value: 00123 Abscissa maxerror = fabs(target) * 0.002 * Percent; 00124 00125 //z.setLowerBound(fromcelsius(3.984)); 00126 z.setLowerBound(getLowerBound(flags)); 00127 00128 z.setUpperBound(getUpperBound(flags)); 00129 //z.setUpperBound(fromcelsius(3.984)); 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 //cerr << endl << "SatCurve<" << SteamProperty<Ordinate,OrdinateAlt>::name() << "," << SteamProperty<Abscissa,AbscissaAlt>::name() << ">::solve: found solution at T = " << z.getSolution(); 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 //cerr << endl << "SatCurve::getAbscissaErrorWater_T: Trying with T = " << T << ": "; 00171 00172 S.setSatWater_T(T); 00173 //cerr << SteamProperty<Abscissa,AbscissaAlt>::name() << " = " << getAbscissa(S); 00174 00175 return SatCurveBase<Ordinate,Abscissa,OrdinateAlt,AbscissaAlt>::getAbscissa(S) - target; 00176 } 00177 00178 Abscissa getAbscissaErrorSteam_T(const Temperature &T){ 00179 00180 //cerr << "SatCurve::getAbscissaErrorSteam_T: Trying with T = " << T << ": "; 00181 00182 S.setSatSteam_T(T); 00183 //cerr << SteamProperty<Abscissa,AbscissaAlt>::name() << " = " << getAbscissa(S); 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 template<class Ordinate,int OrdinateAlt> 00225 class SatCurve<Ordinate,Pressure,OrdinateAlt,0> 00226 : public SatCurveBase<Ordinate,Pressure,OrdinateAlt,0>{ 00227 00228 public: 00229 00230 SatCurve() : SatCurveBase<Ordinate,Pressure,OrdinateAlt,0>(){} 00231 virtual ~SatCurve(){} 00232 00233 virtual Ordinate solve(const Pressure &p,const int &flags=SAT_WATER){ 00234 SteamCalculator S; 00235 if(flags & SAT_STEAM){ 00236 S.setSatSteam_p(p); 00237 }else{ 00238 S.setSatWater_p(p); 00239 } 00240 return SatCurveBase<Ordinate,Pressure,OrdinateAlt,0>::getOrdinate(S); 00241 } 00242 }; 00243 */ 00244 00245 #endif

Generated on Tue Mar 22 19:07:05 2005 for freesteam by doxygen 1.3.8