高温氦气物性补全;三通四通能量计算bug修正
This commit is contained in:
1 parent
6fc9afe41d
commit
2b07d996cf
133 files changed
+5230
-253310
No files matched your search
@@ -1,6 +1,6 @@
|
||||
/* Helium Peng-Robinson and compressible-orifice kernels.
|
||||
* Ported from the project's Python physical equations; validated independently
|
||||
* against Python at ordinary, reverse-flow and contact trial states.
|
||||
* Helium NASA ranges and continuation are checked against independent
|
||||
* Amesim 2404 property-library outputs, including high-temperature boundaries.
|
||||
*/
|
||||
#include "component_properties_internal.h"
|
||||
#include "component_constants_internal.h"
|
||||
@@ -24,12 +24,22 @@ NATIVE_COMPONENT_INTERNAL int same_medium(const NativeMedium *a,const NativeMedi
|
||||
}
|
||||
void native_properties_init(NativePropertyCache *cache,NativePropertyState *states,size_t capacity) {
|
||||
cache->states=states;cache->count=0;cache->capacity=states?capacity:0;
|
||||
cache->temperatures=NULL;
|
||||
}
|
||||
static void observe_temperature(NativePropertyTemperatures *report,const NativeMedium *m,double T,unsigned domains) {
|
||||
if(!report || !m->real_helium || !isfinite(T))return;
|
||||
for(int i=0;i<NATIVE_PROPERTY_DOMAINS;i++)if(domains&(1u<<i)) {
|
||||
if(!(report->seen&(1u<<i)))report->minimum[i]=report->maximum[i]=T;
|
||||
else {report->minimum[i]=fmin(report->minimum[i],T);report->maximum[i]=fmax(report->maximum[i],T);}
|
||||
report->seen|=1u<<i;
|
||||
}
|
||||
}
|
||||
static NativePropertyState *property_new(NativePropertyCache *cache,const NativeMedium *m,
|
||||
double p,double T,NativePropertyState *scratch) {
|
||||
int valid=p>0 && T>0 && isfinite(p) && isfinite(T);
|
||||
NativePropertyState *s=valid && cache && cache->count<cache->capacity ? &cache->states[cache->count++] : scratch;
|
||||
*s=(NativePropertyState){0};s->medium=*m;s->p=p;s->T=T;s->valid=valid?NATIVE_PROPERTY_PT:0;
|
||||
s->temperatures=cache?cache->temperatures:NULL;
|
||||
return s;
|
||||
}
|
||||
NATIVE_COMPONENT_INTERNAL NativePropertyState *property_pt(NativePropertyCache *cache,const NativeMedium *m,
|
||||
@@ -41,6 +51,7 @@ NATIVE_COMPONENT_INTERNAL NativePropertyState *property_pt(NativePropertyCache *
|
||||
return property_new(cache,m,p,T,scratch);
|
||||
}
|
||||
NATIVE_COMPONENT_INTERNAL double property_density(NativePropertyState *s) {
|
||||
observe_temperature(s->temperatures,&s->medium,s->T,1);
|
||||
if(!(s->valid&NATIVE_PROPERTY_RHO)) {
|
||||
s->rho=native_density(&s->medium,s->p,s->T);
|
||||
if(s->rho>0 && isfinite(s->rho))s->valid|=NATIVE_PROPERTY_RHO;
|
||||
@@ -48,6 +59,7 @@ NATIVE_COMPONENT_INTERNAL double property_density(NativePropertyState *s) {
|
||||
return s->rho;
|
||||
}
|
||||
NATIVE_COMPONENT_INTERNAL double property_viscosity(NativePropertyState *s) {
|
||||
observe_temperature(s->temperatures,&s->medium,s->T,4);
|
||||
if(!(s->valid&NATIVE_PROPERTY_MU)) {
|
||||
s->mu=native_viscosity(&s->medium,s->T,0);
|
||||
if(s->mu>0 && isfinite(s->mu))s->valid|=NATIVE_PROPERTY_MU;
|
||||
@@ -55,6 +67,7 @@ NATIVE_COMPONENT_INTERNAL double property_viscosity(NativePropertyState *s) {
|
||||
return s->mu;
|
||||
}
|
||||
static void remember_gas(NativePropertyCache *cache,const NativeMedium *m,const NativeGas *gas) {
|
||||
observe_temperature(cache?cache->temperatures:NULL,m,gas->T,3);
|
||||
/* Below helium's critical temperature retain the existing vapor-root/PH
|
||||
selection. A future phase-aware medium contract can carry that state. */
|
||||
if(!cache || (m->real_helium && gas->T<=TC))return;
|
||||
@@ -68,9 +81,12 @@ static void remember_gas(NativePropertyCache *cache,const NativeMedium *m,const
|
||||
double native_temperature_ph_context(NativePropertyCache *cache,const NativeMedium *m,double p,double h) {
|
||||
if(cache)for(size_t i=0;i<cache->count;i++) {
|
||||
NativePropertyState *s=&cache->states[i];
|
||||
if((s->valid&NATIVE_PROPERTY_H) && s->p==p && s->h==h && same_medium(&s->medium,m))return s->T;
|
||||
if((s->valid&NATIVE_PROPERTY_H) && s->p==p && s->h==h && same_medium(&s->medium,m)) {
|
||||
observe_temperature(cache->temperatures,m,s->T,3);return s->T;
|
||||
}
|
||||
}
|
||||
double T=native_temperature_ph(m,p,h);
|
||||
observe_temperature(cache?cache->temperatures:NULL,m,T,3);
|
||||
if(cache && isfinite(h) && T>0 && isfinite(T) && p>0 && isfinite(p)) {
|
||||
NativePropertyState scratch,*s=property_pt(cache,m,p,T,&scratch);
|
||||
if((s->valid&NATIVE_PROPERTY_H) && s->h!=h)s=property_new(cache,m,p,T,&scratch);
|
||||
@@ -119,10 +135,75 @@ static double h_departure(double p,double T) {
|
||||
double dep=RU*T*(z-1)+(T*da-a)*log((z+(1+sq)*B)/(z+(1-sq)*B))/(2*sq*pr_b);
|
||||
return dep/MOLAR_MASS;
|
||||
}
|
||||
static double u_ideal(double T) { return rg*(1.5*T-745.375); }
|
||||
static double h_ideal(double T) { return rg*(2.5*T-745.375); }
|
||||
static double temperature_u(double u) { return (u/rg+745.375)/1.5; }
|
||||
static double temperature_h(double h) { return (h/rg+745.375)/2.5; }
|
||||
/* Amesim 2404 helium_cp_h_s.data, NASA 2002 ideal contribution.
|
||||
* The two lower ranges have Cp/R=2.5. Amesim shifts the third range's
|
||||
* constant Cp coefficient and integration constant to preserve Cp and h
|
||||
* at 6000 K; copying its raw a8 would introduce a ~3.94 J/kg enthalpy jump.
|
||||
* The PR departure terms below are unchanged.
|
||||
*/
|
||||
static double helium_high_cp_r(double T) {
|
||||
return 3396845/(T*T)-2194.038/T+3.080232+
|
||||
T*(-8.068958e-5+T*(6.252785e-9+T*(-2.574990e-13+T*4.429960e-18)));
|
||||
}
|
||||
static double helium_high_cp_slope_r(double T) {
|
||||
return -2*3396845/(T*T*T)+2194.038/(T*T)-8.068958e-5+
|
||||
T*(2*6.252785e-9+T*(-3*2.574990e-13+T*4*4.429960e-18));
|
||||
}
|
||||
static double cp_ideal(double T) {
|
||||
if(T<=6000)return 2.5*rg;
|
||||
double offset=helium_high_cp_r(6000)-2.5;
|
||||
if(T<=20000)return rg*(helium_high_cp_r(T)-offset);
|
||||
/* Amesim's out-of-table continuation: quadratic Cp with matched value
|
||||
and slope. This is extrapolation, not a wider validity claim. */
|
||||
double c=helium_high_cp_r(20000)-offset;
|
||||
double x=(T-20000)*helium_high_cp_slope_r(20000)/c;
|
||||
return rg*c*(1+x+.5*x*x);
|
||||
}
|
||||
static double helium_high_enthalpy_increment(double T) {
|
||||
const double b=6000,b2=b*b,b3=b2*b,b4=b3*b;
|
||||
double x=T-b,t2=T*T,t3=t2*T,t4=t3*T;
|
||||
/* Integrate Cp from the boundary; log1p and factored powers retain
|
||||
precision when an integrator crosses 6000 K by a very small step. */
|
||||
return rg*(3396845*x/(T*b)-2194.038*log1p(x/b)+x*(
|
||||
3.080232-(helium_high_cp_r(b)-2.5)-8.068958e-5*(T+b)/2+
|
||||
6.252785e-9*(t2+T*b+b2)/3-2.574990e-13*(t3+t2*b+T*b2+b3)/4+
|
||||
4.429960e-18*(t4+t3*b+t2*b2+T*b3+b4)/5));
|
||||
}
|
||||
static double h_ideal(double T) {
|
||||
if(T<=6000)return rg*(2.5*T-745.375);
|
||||
double h=rg*(2.5*6000-745.375)+helium_high_enthalpy_increment(fmin(T,20000));
|
||||
if(T>20000) {
|
||||
double c=helium_high_cp_r(20000)-helium_high_cp_r(6000)+2.5;
|
||||
double dt=T-20000,x=dt*helium_high_cp_slope_r(20000)/c;
|
||||
h+=rg*c*dt*(1+.5*x+x*x/6);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
static double u_ideal(double T) {
|
||||
return T<=6000 ? rg*(1.5*T-745.375) : h_ideal(T)-rg*T;
|
||||
}
|
||||
static double temperature_ideal(double energy,int enthalpy) {
|
||||
double c=enthalpy?2.5:1.5,linear=(energy/rg+745.375)/c;
|
||||
if(linear<=6000 || !isfinite(linear))return linear;
|
||||
double lo=6000,hi=fmax(linear,6001);
|
||||
for(int i=0;i<64;i++) {
|
||||
double value=enthalpy?h_ideal(hi):u_ideal(hi);
|
||||
if(value>=energy)break;
|
||||
hi*=2;
|
||||
}
|
||||
double T=fmin(linear,hi);
|
||||
for(int i=0;i<64;i++) {
|
||||
double value=enthalpy?h_ideal(T):u_ideal(T),residual=value-energy;
|
||||
if(fabs(residual)<=1e-12*fmax(fabs(energy),1))return T;
|
||||
if(residual>0)hi=T;else lo=T;
|
||||
double next=T-residual/(cp_ideal(T)-(enthalpy?0:rg));
|
||||
if(!isfinite(next) || next<=lo || next>=hi)next=lo+.5*(hi-lo);
|
||||
T=next;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
static double temperature_u(double u) { return temperature_ideal(u,0); }
|
||||
static double temperature_h(double h) { return temperature_ideal(h,1); }
|
||||
static double pressure_rho(double T,double rho) {
|
||||
double v=MOLAR_MASS/rho,a,da,dda;attraction(T,&a,&da,&dda);
|
||||
if(v<=pr_b || T<=0) return NAN;
|
||||
@@ -144,12 +225,13 @@ static double temperature_ph(double p,double h) {
|
||||
int done=fabs(next-T)<=1e-10*fmax(T,1);T=next;if(done) break; }return T;
|
||||
}
|
||||
static void local_isentropic(NativePropertyState *s) {
|
||||
observe_temperature(s->temperatures,&s->medium,s->T,3);
|
||||
if(s->valid&NATIVE_PROPERTY_ISENTROPIC)return;
|
||||
double p=s->p,T=s->T,rho=property_density(s),v=MOLAR_MASS/rho,a,da,dda;attraction(T,&a,&da,&dda);
|
||||
double d=v*(v+pr_b)+pr_b*(v-pr_b);
|
||||
double dpT=RU/(v-pr_b)-da/d;
|
||||
double dpR=(-RU*T/pow(v-pr_b,2)+a*2*(v+pr_b)/(d*d))*(-MOLAR_MASS/(rho*rho));
|
||||
double cv=1.5*rg+T*dda*log_volume(rho);
|
||||
double cv=cp_ideal(T)-rg+T*dda*log_volume(rho);
|
||||
double cp=cv+T*dpT*dpT/(rho*rho*dpR),gamma=cp/cv;
|
||||
s->isentropic_factor=p/(rho*dpR*gamma);s->isentropic_exponent=p*(gamma-1)/(gamma*T*dpT);
|
||||
if(isfinite(s->isentropic_factor) && isfinite(s->isentropic_exponent))s->valid|=NATIVE_PROPERTY_ISENTROPIC;
|
||||
@@ -222,8 +304,18 @@ double native_temperature_ph(const NativeMedium *m, double p, double h) {
|
||||
double native_viscosity(const NativeMedium *m, double T, int diagnostic) {
|
||||
/* Retain the ABI argument; flow and diagnostics use the same property. */
|
||||
(void)diagnostic;
|
||||
if (m->real_helium)
|
||||
return 1e-7*exp(.7501594*log(T)+35.76324/T-2212.129/(T*T)+.9212635);
|
||||
if (m->real_helium) {
|
||||
/* helium_mu.data: NASA 96, microPoise -> Pa.s. Anchor ln(mu)
|
||||
at each boundary, as Amesim does, to remove coefficient rounding
|
||||
jumps. The last range is also its out-of-table extrapolation. */
|
||||
double l1000=.7501594*log(1000)+35.76324/1000-2212.129/1e6+.9212635;
|
||||
if(T<=1000)return 1e-7*exp(.7501594*log(T)+35.76324/T-2212.129/(T*T)+.9212635);
|
||||
if(T<=5000)return 1e-7*exp(l1000+.8339417*log(T/1000)+
|
||||
220.8266*(1/T-1./1000)-52852.59*(1/(T*T)-1e-6));
|
||||
double l5000=l1000+.8339417*log(5)+220.8266*(1./5000-1./1000)-52852.59*(1./25e6-1e-6);
|
||||
return 1e-7*exp(l5000+.8631635*log(T/5000)+
|
||||
962.0518*(1/T-1./5000)-1249870*(1/(T*T)-1./25e6));
|
||||
}
|
||||
return m->mu*pow(T/m->muT,1.5)*(m->muT+m->S)/(T+m->S);
|
||||
}
|
||||
int native_medium_gas(const NativeMedium *medium, double m, double U, double V, NativeGas *g) {
|
||||
|
||||
Reference in new issue
Block a user