static int region1_df(const gsl_vector *x, void *user_data, gsl_matrix *J){ #define D ((Solver2Data *)user_data) double p = gsl_vector_get(x,0); double T = gsl_vector_get(x,1); SteamState S = freesteam_region1_set_pT(p,T); gsl_matrix_set(J, 0, 0, freesteam_region1_dAdpT(D->A,S)); gsl_matrix_set(J, 0, 1, freesteam_region1_dAdTp(D->A,S)); gsl_matrix_set(J, 1, 0, freesteam_region1_dAdpT(D->B,S)); gsl_matrix_set(J, 1, 1, freesteam_region1_dAdTp(D->B,S)); return GSL_SUCCESS; #undef D }
SteamState freesteam_set_pu(double p, double u){ double lb, ub, tol, sol, err; SolvePUData D = {p, u, 0.}; SteamState S; int region = freesteam_region_pu(p,u); switch(region){ case 1: lb = IAPWS97_TMIN; ub = REGION1_TMAX; tol = 1e-9; /* ??? */ zeroin_solve(&pu_region1_fn, &D, lb, ub, tol, &sol, &err); S = freesteam_region1_set_pT(p,sol); break; case 2: lb = IAPWS97_TMIN; ub = REGION2_TMAX; tol = 1e-9; /* ??? */ zeroin_solve(&pu_region2_fn, &D, lb, ub, tol, &sol, &err); S = freesteam_region2_set_pT(p,sol); break; case 4: lb = 0.; ub = 1.; tol = 1e-9; /* ??? */ D.T = freesteam_region4_Tsat_p(p); //fprintf(stderr,"%s: (%s:%d): p = %g\n",__func__,__FILE__,__LINE__,D.p); zeroin_solve(&pu_region4_fn, &D, lb, ub, tol, &sol, &err); S = freesteam_region4_set_Tx(D.T,sol); break; case 3: /* FIXME looks like a problem with the derivative routines here? */ { int status; SteamState guess = freesteam_region3_set_rhoT(IAPWS97_RHOCRIT,IAPWS97_TCRIT); S = freesteam_solver2_region3('p','u', p, u, guess, &status); if(status){ fprintf(stderr,"%s (%s:%d): Failed solve in region 3 for (p = %g MPa, u = %g kJ/kg\n" ,__func__,__FILE__,__LINE__,p/1e6,u/1e3); //exit(1); } } break; default: fprintf(stderr,"%s (%s:%d): Region '%d' not implemented\n",__func__,__FILE__,__LINE__,region); exit(1); } return S; }
double freesteam_drhofdT_T(double T){ double dpsatdT = freesteam_region4_dpsatdT_T(T); if(T < REGION1_TMAX){ double psat = freesteam_region4_psat_T(T); SteamState Sf = freesteam_region1_set_pT(psat,T); double vf = freesteam_v(Sf); return -1./SQ(vf) * (PT1('v',Sf) * dpsatdT + TP1('v',Sf)); }else{ /* FIXME: add iterative refinement of value of rhof */ double rhof = freesteam_region4_rhof_T(T); SteamState Sf = freesteam_region3_set_rhoT(rhof,T); double dpdT = TV3('p',Sf); double dpdrho = -1./SQ(rhof) * VT3('p',Sf); return (dpsatdT - dpdT)/dpdrho; } }
/* ⎰ ∂z ⎱ = ⎰∂z_f⎱ (1 - x) + ⎰∂z_f⎱ x ⎱ ∂T ⎰x ⎱ ∂T ⎰ ⎱ ∂T ⎰ */ double freesteam_region4_dAdTx(FREESTEAM_CHAR z, SteamState S){ double res; #define T S.R4.T switch(z){ case 'p': res = freesteam_region4_dpsatdT_T(T); return res; case 'T': res = 1; return res; case 'x': res = 0; return res; } //fprintf(stderr,"%s: T = %g\n",__func__,T); assert(!isnan(T)); double dzfdT, dzgdT; if(T < REGION1_TMAX){ //fprintf(stderr,"%s: below REGION1_TMAX\n",__func__); double psat = freesteam_region4_psat_T(T); SteamState Sf = freesteam_region1_set_pT(psat,T); SteamState Sg = freesteam_region2_set_pT(psat,T); double dpsatdT = freesteam_region4_dpsatdT_T(T); dzfdT = PT1(z,Sf)*dpsatdT + TP1(z,Sf); dzgdT = PT2(z,Sg)*dpsatdT + TP2(z,Sg); }else{ double rhof = freesteam_region4_rhof_T(T); double rhog = freesteam_region4_rhog_T(T); assert(rhof!=0); assert(rhog!=0); SteamState Sf = freesteam_region3_set_rhoT(rhof,T); SteamState Sg = freesteam_region3_set_rhoT(rhog,T); double dvfdT = -1./SQ(rhof) * freesteam_drhofdT_T(T); assert(!isnan(dvfdT)); double dvgdT = -1./SQ(rhog) * freesteam_drhogdT_T(T); assert(!isnan(dvgdT)); dzfdT = VT3(z,Sf)*dvfdT + TV3(z,Sf); dzgdT = VT3(z,Sg)*dvgdT + TV3(z,Sg); } assert(!isnan(dzfdT)); assert(!isnan(dzgdT)); #define x S.R4.x res = dzfdT*(1-x) + dzgdT*x; //fprintf(stderr,"(∂%c/∂T)x = %g\n",z,res); return res; #undef T #undef x }
SteamState freesteam_solver2_region1(FREESTEAM_CHAR A, FREESTEAM_CHAR B, double atarget, double btarget, SteamState guess, int *retstatus){ const gsl_multiroot_fdfsolver_type *T; gsl_multiroot_fdfsolver *s; int status; size_t iter = 0; const size_t n = 2; //fprintf(stderr,"region 1 solver...\n"); Solver2Data D = {A,B,solver2_region1_propfn(A), solver2_region1_propfn(B), atarget,btarget}; gsl_multiroot_function_fdf f = {®ion1_f, ®ion1_df, ®ion1_fdf, n, &D}; gsl_vector *x = gsl_vector_alloc(n); gsl_vector_set(x, 0, freesteam_rho(guess)); gsl_vector_set(x, 1, freesteam_T(guess)); T = gsl_multiroot_fdfsolver_gnewton; s = gsl_multiroot_fdfsolver_alloc(T, n); gsl_multiroot_fdfsolver_set(s, &f, x); //region1_print_state(iter, s); do{ iter++; status = gsl_multiroot_fdfsolver_iterate(s); //region1_print_state(iter, s); if(status){ /* check if solver is stuck */ break; } status = gsl_multiroot_test_residual(s->f, 1e-6); } while(status == GSL_CONTINUE && iter < 20); SteamState S = freesteam_region1_set_pT(gsl_vector_get(s->x,0), gsl_vector_get(s->x,1)); gsl_multiroot_fdfsolver_free(s); gsl_vector_free(x); *retstatus = status; if(status){ fprintf(stderr,"%s (%s:%d): %s: ",__func__,__FILE__,__LINE__,gsl_strerror(status)); freesteam_fprint(stderr,S); } return S; }