double conversion_factor(std::string num) { double factor = 1.0; // Parse the first entry if (num[0] != '1') { std::string key; key.resize(1); key[0] = num[0]; factor *= convert_from_SI_to_unit_system(get_param_index(key),1,get_standard_unit_system()); } for (int i = 1; i < (int)num.size(); i += 2) { char op = num[i]; std::string key; key.resize(1); key[0] = num[i+1]; double term = convert_from_SI_to_unit_system(get_param_index(key),1,get_standard_unit_system()); if (op == '*') { factor *= term; } else { factor /= term; } } return factor; }
thinkpad_fan::thinkpad_fan(): device() { start_rate = 0; end_rate = 0; fan_index = get_param_index("thinkpad-fan"); fansqr_index = get_param_index("thinkpad-fan-sqr"); fancub_index = get_param_index("thinkpad-fan-cub"); r_index = get_result_index("thinkpad-fan"); register_sysfs_path("/sys/devices/platform/thinkpad_hwmon"); }
cpudevice::cpudevice(const char *classname, const char *dev_name, class abstract_cpu *_cpu) { strcpy(_class, classname); strcpy(_cpuname, dev_name); cpu = _cpu; wake_index = get_param_index("cpu-wakeups");; consumption_index = get_param_index("cpu-consumption");; r_wake_index = get_result_index("cpu-wakeups");; r_consumption_index = get_result_index("cpu-consumption");; }
EXPORT_CODE double CONVENTION Props(const char *Output, const char Name1, double Prop1, const char Name2, double Prop2, const char * Ref) { try { // Get parameter indices std::string sName1 = std::string(1, Name1), sName2 = std::string(1, Name2); long iOutput = get_param_index(Output); long iName1 = CoolProp::get_parameter_index(sName1); long iName2 = CoolProp::get_parameter_index(sName2); // Convert inputs to SI Prop1 = convert_from_kSI_to_SI(iName1, Prop1); Prop2 = convert_from_kSI_to_SI(iName2, Prop2); // Call the SI function double val = PropsSI(Output, sName1.c_str(), Prop1, sName2.c_str(), Prop2, Ref); reset_fpu(); // Convert back to unit system return convert_from_SI_to_kSI(iOutput, val); } catch(std::exception &e){CoolProp::set_error_string(e.what()); return _HUGE;} catch(...){CoolProp::set_error_string("Undefined error"); return _HUGE;} }
double convert_from_unit_system_to_SI(std::string input, double value, std::string old_system) { int iSys = -1; if (!old_system.compare("kSI")) iSys = UNIT_SYSTEM_KSI; if (!old_system.compare( "SI")) iSys = UNIT_SYSTEM_SI; double val = convert_from_unit_system_to_SI(get_param_index(input), value, iSys); return val; }
double get_parameter_value(const char *name, struct parameter_bundle *the_bundle) { unsigned int index; index = get_param_index(name); if (index >= the_bundle->parameters.size()) { fprintf(stderr, "BUG: requesting unregistered parameter %s\n", name); } return the_bundle->parameters[index]; }
void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle) { int index; index = get_param_index(name); if (index >= (int)bundle->parameters.size()) { bundle->parameters.resize(index+1, 0.0); bundle->weights.resize(index+1, 1.0); } bundle->parameters[index] = value; }
void register_parameter(const char *name, double default_value, double weight) { int index; index = get_param_index(name); if (index >= (int)all_parameters.parameters.size()) { all_parameters.parameters.resize(index+1, 0.0); all_parameters.weights.resize(index+1, 1.0); } if (all_parameters.parameters[index] <= 0.0001) all_parameters.parameters[index] = default_value; all_parameters.weights[index] = weight; }
double _Props1(char *Fluid, char *Output) { // Try to load the CoolProp Fluid pFluid = Fluids.get_fluid(Fluid); if (pFluid != NULL) { // It's a CoolProp fluid // Convert the parameter to integer long iOutput = get_param_index(Output); if (iOutput < 0){ throw ValueError(format("Your output key [%s] is not valid. (names are case sensitive)",Output)); } // Get the output using the conventional function return _CoolProp_Fluid_Props(iOutput,0,0,0,0,pFluid); } else if (IsREFPROP(Fluid)) { // REFPROP fluid, or something else that is invalid try{ if (!strcmp(Output,"Ttriple")) return Props('R','T',0,'P',0,Fluid); else if (!strcmp(Output,"Tcrit")) return Props('B','T',0,'P',0,Fluid); else if (!strcmp(Output,"pcrit")) return Props('E','T',0,'P',0,Fluid); else if (!strcmp(Output,"Tmin")) return Props('t','T',0,'P',0,Fluid); else if (!strcmp(Output,"molemass")) return Props('M','T',0,'P',0,Fluid); else if (!strcmp(Output,"rhocrit")) return Props('N','T',0,'P',0,Fluid); else if (!strcmp(Output,"accentric")) return Props('w','T',0,'P',0,Fluid); else throw ValueError(format("Output parameter \"%s\" is invalid for REFPROP fluid",Output)); } // Catch any error that subclasses the std::exception catch(std::exception &e){ err_string = std::string("CoolProp error: ").append(e.what()); return _HUGE; } } else { throw ValueError(format("Fluid \"%s\" is an invalid fluid",Fluid)); } }
c_hints() { int i,index; plintf("#include <math.h>\n\n extern double constants[]; \n"); plintf("main(argc,argv)\n char **argv; \n int argc;\n{\n do_main(argc,argv);\n }\n"); plintf("/* defines for %s */ \n",this_file); for(i=0;i<NUPAR;i++){ index=get_param_index(upar_names[i]); plintf("#define %s constants[%d]\n",upar_names[i],index); } for(i=0;i<NODE;i++){ plintf("#define %s y[%d]\n",uvar_names[i],i); plintf("#define %sDOT ydot[%d]\n",uvar_names[i],i); } for(i=NODE;i<NEQ;i++) plintf("#define %s y[%d]\n",uvar_names[i],i); plintf("my_rhs(t,y,ydot,neq)\n double t,*y,*ydot; \n int neq;\n{\n }\n"); plintf("set_fix_rhs(t,y,neq)\n double y,*y;\n int neq;\n{\n }\n"); plintf("extra(y,t,nod,neq)\n double t,*y; \n int nod,neq;\n{\n }\n"); }
double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results) { double power = 0; unsigned int i; static int bpi = 0; if (!bpi) bpi = get_param_index("base power"); if (!precomputed_valid) precompute_valid(); power = parameters->parameters[bpi]; for (i = 0; i < all_devices.size(); i++) { if (all_devices[i]->cached_valid) power += all_devices[i]->power_usage(results, parameters); } return power; }
double compute_bundle(struct parameter_bundle *parameters, struct result_bundle *results) { double power = 0; unsigned int i; static int bpi = 0; if (!bpi) bpi = get_param_index("base power"); power = parameters->parameters[bpi]; for (i = 0; i < all_devices.size(); i++) { power += all_devices[i]->power_usage(results, parameters); } // printf("result power is %6.2f guessed is %6.2f\n", results->power, power); parameters->actual_power = results->power; parameters->guessed_power = power; /* scale the squared error by the actual power so that non-idle data points weigh heavier */ parameters->score += results->power * (power - results->power) * (power - results->power); return power; }
// Make this a wrapped function so that error bubbling can be done properly double _Props(std::string Output, std::string Name1, double Prop1, std::string Name2, double Prop2, std::string Ref) { if (get_debug_level()>5){ std::cout<<__FILE__<<": "<<Output.c_str()<<","<<Name1.c_str()<<","<<Prop1<<","<<Name2.c_str()<<","<<Prop2<<","<<Ref.c_str()<<std::endl; } /* If the fluid name is not actually a refrigerant name, but a string beginning with "REFPROP-", then REFPROP is used to calculate the desired property. */ if (IsREFPROP(Ref)) // First eight characters match "REFPROP-" { // Stop here if there is no REFPROP support if (REFPROPFluidClass::refpropSupported()) { return REFPROP(Output,Name1,Prop1,Name2,Prop2,Ref); } else { throw AttributeError(format("Your refrigerant [%s] is from REFPROP, but CoolProp does not support REFPROP on this platform, yet.",Ref.c_str())); return -_HUGE; } } else if (IsCoolPropFluid(Ref)) { pFluid = Fluids.get_fluid(Ref); // Convert all the parameters to integers long iOutput = get_param_index(Output); if (iOutput<0) throw ValueError(format("Your output key [%s] is not valid. (names are case sensitive)",Output.c_str())); long iName1 = get_param_index(std::string(Name1)); if (iName1<0) throw ValueError(format("Your input key #1 [%s] is not valid. (names are case sensitive)",Name1.c_str())); long iName2 = get_param_index(std::string(Name2)); if (iName2<0) throw ValueError(format("Your input key #2 [%s] is not valid. (names are case sensitive)",Name2.c_str())); // Call the internal method that uses the parameters converted to longs return _CoolProp_Fluid_Props(iOutput,iName1,Prop1,iName2,Prop2,pFluid); } // It's a brine, call the brine routine else if (IsBrine((char*)Ref.c_str())) { //Enthalpy and pressure are the inputs if ((Name1.c_str()[0]=='H' && Name2.c_str()[0]=='P') || (Name2.c_str()[0]=='H' && Name1.c_str()[0]=='P')) { if (Name2.c_str()[0]=='H' && Name1.c_str()[0]=='P') { std::swap(Prop1,Prop2); std::swap(Name1,Name2); } // Start with a guess of 10 K below max temp of fluid double Tguess = SecFluids('M',Prop1,Prop2,(char*)Ref.c_str())-10; // Solve for the temperature double T =_T_hp_secant(Ref,Prop1,Prop2,Tguess); // Return whatever property is desired return SecFluids(Output[0],T,Prop2,(char*)Ref.c_str()); } else if ((Name1.c_str()[0] == 'T' && Name2.c_str()[0] =='P') || (Name1.c_str()[0] == 'P' && Name2.c_str()[0] == 'T')) { if (Name1.c_str()[0] =='P' && Name2.c_str()[0] =='T'){ std::swap(Prop1,Prop2); } return SecFluids(Output[0],Prop1,Prop2,(char*)Ref.c_str()); } else { throw ValueError("For brine, inputs must be (order doesnt matter) 'T' and 'P', or 'H' and 'P'"); } } // It's an incompressible liquid, call the routine else if (IsIncompressibleLiquid((char*)Ref.c_str())) { //Enthalpy and pressure are the inputs if ((Name1.c_str()[0]=='H' && Name2.c_str()[0]=='P') || (Name2.c_str()[0]=='H' && Name1.c_str()[0]=='P')) { if (Name2.c_str()[0]=='H' && Name1.c_str()[0]=='P') { std::swap(Prop1,Prop2); std::swap(Name1,Name2); } // Solve for the temperature double T =_T_hp_secant(Ref,Prop1,Prop2,300); // Return whatever property is desired return IncompLiquid(get_param_index(Output),T,Prop2,(char*)Ref.c_str()); } else if ((Name1.c_str()[0] == 'T' && Name2.c_str()[0] =='P') || (Name1.c_str()[0] == 'P' && Name2.c_str()[0] == 'T')) { if (Name1.c_str()[0] =='P' && Name2.c_str()[0] =='T'){ std::swap(Prop1,Prop2); } return IncompLiquid(get_param_index(Output),Prop1,Prop2,Ref); } else { throw ValueError("For brine, inputs must be (order doesnt matter) 'T' and 'P', or 'H' and 'P'"); } } else { throw ValueError(format("Your fluid name [%s] is not a CoolProp fluid, a REFPROP fluid, a brine or a liquid",Ref.c_str())); } }
/* leaks like a sieve */ void learn_parameters(int iterations, int do_base_power) { struct parameter_bundle *best_so_far; double best_score = 10000000000000000.0; int retry = iterations; int prevparam = -1; int locked = 0; static unsigned int bpi = 0; unsigned int i; time_t start; if (global_fixed_parameters) return; /* don't start fitting anything until we have at least 1 more measurement than we have parameters */ if (past_results.size() <= all_parameters.parameters.size()) return; // if (past_results.size() == previous_measurements) // return; precompute_valid(); previous_measurements = past_results.size(); double delta = 0.50; best_so_far = &all_parameters; if (!bpi) bpi = get_param_index("base power"); calculate_params(best_so_far); best_score = best_so_far->score; delta = 0.001 / pow(0.8, iterations / 2.0); if (iterations < 25) delta = 0.001 / pow(0.5, iterations / 2.0); if (delta > 0.2) delta = 0.2; if (1.0 * best_score / past_results.size() < 4 && delta > 0.05) delta = 0.05; if (debug_learning) printf("Delta starts at %5.3f\n", delta); if (best_so_far->parameters[bpi] > min_power * 0.9) best_so_far->parameters[bpi] = min_power * 0.9; /* We want to give up a little of base power, to give other parameters room to change; base power is the end post for everything after all */ if (do_base_power && !debug_learning) best_so_far->parameters[bpi] = best_so_far->parameters[bpi] * 0.9998; start = time(NULL); while (retry--) { int changed = 0; int bestparam; double newvalue = 0; double orgscore; double weight; bestparam = -1; if (time(NULL) - start > 1 && !debug_learning) retry = 0; calculate_params(best_so_far); orgscore = best_score = best_so_far->score; for (i = 1; i < best_so_far->parameters.size(); i++) { double value, orgvalue; weight = delta * best_so_far->weights[i]; orgvalue = value = best_so_far->parameters[i]; if (value <= 0.001) { value = 0.1; } else value = value * (1 + weight); if (i == bpi && value > min_power) value = min_power; if (i == bpi && orgvalue > min_power) orgvalue = min_power; if (value > 5000) value = 5000; // printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), best_so_far->parameters[param], value); best_so_far->parameters[i] = value; calculate_params(best_so_far); if (best_so_far->score < best_score || random_disturb(retry)) { best_score = best_so_far->score; newvalue = value; bestparam = i; changed++; } value = orgvalue * 1 / (1 + weight); if (value < 0.0001) value = 0.0; if (try_zero(value)) value = 0.0; if (value > 5000) value = 5000; // printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), orgvalue, value); if (orgvalue != value) { best_so_far->parameters[i] = value; calculate_params(best_so_far); if (best_so_far->score + 0.00001 < best_score || (random_disturb(retry) && value > 0.0)) { best_score = best_so_far->score; newvalue = value; bestparam = i; changed++; } } best_so_far->parameters[i] = orgvalue; } if (!changed) { double mult; if (!locked) { mult = 0.8; if (iterations < 25) mult = 0.5; delta = delta * mult; } locked = 0; prevparam = -1; } else { if (debug_learning) { printf("Retry is %i \n", retry); printf("delta is %5.4f\n", delta); printf("Best parameter is %i \n", bestparam); printf("Changing score from %4.3f to %4.3f\n", orgscore, best_score); printf("Changing value from %4.3f to %4.3f\n", best_so_far->parameters[bestparam], newvalue); } best_so_far->parameters[bestparam] = newvalue; if (prevparam == bestparam) delta = delta * 1.1; prevparam = bestparam; locked = 1; } if (delta < 0.001 && !locked) break; if (retry % 50 == 49) weed_empties(best_so_far); } /* now we weed out all parameters that don't have value */ if (iterations > 50) weed_empties(best_so_far); if (debug_learning) printf("Final score %4.2f (%i points)\n", best_so_far->score / past_results.size(), (int)past_results.size()); // dump_parameter_bundle(best_so_far); // dump_past_results(); }