Skip to content

Commit

Permalink
Add an accessor function to DLL to allow for getting multiple outputs…
Browse files Browse the repository at this point in the history
… at once from low-level interface

see #888
see #880
  • Loading branch information
ibell committed Dec 13, 2015
1 parent 1237e41 commit 2401650
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 3 deletions.
11 changes: 10 additions & 1 deletion Web/coolprop/LowLevelAPI.rst
Expand Up @@ -334,4 +334,13 @@ Here is a further example in C++:

which yields the output:

.. literalinclude:: snippets/HighLevelLowLevel.cxx.output
.. literalinclude:: snippets/HighLevelLowLevel.cxx.output

Here is a further example in C++ that shows how to obtain many output variables at the same time, either 5 common outputs, or up to 5 user-selected vectors:

.. literalinclude:: snippets/HighLevelLowLevelMulti.cxx
:language: c++

which yields the output:

.. literalinclude:: snippets/HighLevelLowLevelMulti.cxx.output
2 changes: 1 addition & 1 deletion Web/coolprop/snippets/HighLevelLowLevel.cxx.output
@@ -1 +1 @@
value(all): 8339004.432517, 0.59425 us/call
value(all): 8339004.432514, 0.5 us/call
35 changes: 35 additions & 0 deletions Web/coolprop/snippets/HighLevelLowLevelMulti.cxx
@@ -0,0 +1,35 @@
#include "CoolPropLib.h"
#include "CoolPropTools.h"
#include <vector>
#include <time.h>

int main(){
const long buffer_size = 1000, length = 100000;
long ierr;
char herr[buffer_size];
long handle = AbstractState_factory("BICUBIC&HEOS", "Water", &ierr, herr, buffer_size);
std::vector<double> T(length), p(length), rhomolar(length), hmolar(length), smolar(length);
std::vector<double> input1 = linspace(700000.0, 1500000.0, length);
std::vector<double> input2 = linspace(2.8e6, 3.0e6, length);
long input_pair = get_input_pair_index("HmassP_INPUTS");
double t1 = clock();
AbstractState_update_and_common_out(handle, input_pair, &(input1[0]), &(input2[0]), length,
&(T[0]), &(p[0]), &(rhomolar[0]), &(hmolar[0]), &(smolar[0]),
&ierr, herr, buffer_size);
double t2 = clock();
std::cout << format("value(commons): %g us/call\n", ((double)(t2-t1))/CLOCKS_PER_SEC/double(length)*1e6);

std::vector<long> outputs(5);
outputs[0] = get_param_index("T");
outputs[1] = get_param_index("P");
outputs[2] = get_param_index("Dmolar");
outputs[3] = get_param_index("Hmolar");
outputs[4] = get_param_index("Smolar");
std::vector<double> out1(length), out2(length), out3(length), out4(length), out5(length);
t1 = clock();
AbstractState_update_and_5_out(handle, input_pair, &(input1[0]), &(input2[0]), length,
&(outputs[0]), &(out1[0]), &(out2[0]), &(out3[0]), &(out4[0]), &(out5[0]),
&ierr, herr, buffer_size);
t2 = clock();
std::cout << format("value(user-specified): %g us/call\n", ((double)(t2-t1))/CLOCKS_PER_SEC/double(length)*1e6);
}
2 changes: 2 additions & 0 deletions Web/coolprop/snippets/HighLevelLowLevelMulti.cxx.output
@@ -0,0 +1,2 @@
value(commons): 0.57 us/call
value(user-specified): 5.89 us/call
46 changes: 45 additions & 1 deletion include/CoolPropLib.h
Expand Up @@ -283,7 +283,51 @@
* @return
*/
EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long *errcode, char *message_buffer, const long buffer_length);


/**
* @brief Update the state of the AbstractState and get an output value five common outputs (temperature, pressure, molar density, molar enthalpy and molar entropy)
* @brief from the AbstractState using pointers as inputs and output to allow array computation.
* @param handle The integer handle for the state class stored in memory
* @param input_pair The integer value for the input pair obtained from get_input_pair_index
* @param value1 The pointer to the array of the first input parameters
* @param value2 The pointer to the array of the second input parameters
* @param length The number of elements stored in the arrays (both inputs and outputs MUST be the same length)
* @param T The pointer to the array of temperature
* @param p The pointer to the array of pressure
* @param rhomolar The pointer to the array of molar density
* @param hmolar The pointer to the array of molar enthalpy
* @param smolar The pointer to the array of molar entropy
* @param errcode The errorcode that is returned (0 = no error, !0 = error)
* @param message_buffer A buffer for the error code
* @param buffer_length The length of the buffer for the error code
* @return
*
* @note If there is an error in an update call for one of the inputs, no change in the output array will be made
*/
EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, double* T, double* p, double* rhomolar, double* hmolar, double* smolar, long *errcode, char *message_buffer, const long buffer_length);

/**
* @brief Update the state of the AbstractState and get an output value five common outputs (temperature, pressure, molar density, molar enthalpy and molar entropy)
* @brief from the AbstractState using pointers as inputs and output to allow array computation.
* @param handle The integer handle for the state class stored in memory
* @param input_pair The integer value for the input pair obtained from get_input_pair_index
* @param value1 The pointer to the array of the first input parameters
* @param value2 The pointer to the array of the second input parameters
* @param length The number of elements stored in the arrays (both inputs and outputs MUST be the same length)
* @param outputs The 5-element vector of indices for the outputs desired
* @param out1 The pointer to the array for the first output
* @param out2 The pointer to the array for the second output
* @param out3 The pointer to the array for the third output
* @param out4 The pointer to the array for the fourth output
* @param out4 The pointer to the array for the fifth output
* @param errcode The errorcode that is returned (0 = no error, !0 = error)
* @param message_buffer A buffer for the error code
* @param buffer_length The length of the buffer for the error code
* @return
*
* @note If there is an error in an update call for one of the inputs, no change in the output array will be made
*/
EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, long *inputs, double* out1, double* out2, double* out3, double* out4, double* out5, long *errcode, char *message_buffer, const long buffer_length);


// *************************************************************************************
Expand Down
70 changes: 70 additions & 0 deletions src/CoolPropLib.cpp
Expand Up @@ -518,4 +518,74 @@ EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long ha
*errcode = 3;
}
return _HUGE;
}

EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, double* T, double* p, double* rhomolar, double* hmolar, double* smolar, long *errcode, char *message_buffer, const long buffer_length)
{
*errcode = 0;
try{
shared_ptr<CoolProp::AbstractState> &AS = handle_manager.get(handle);

for (int i = 0; i<length; i++){
try{
AS->update(static_cast<CoolProp::input_pairs>(input_pair), *(value1+i), *(value2+i));
*(T+i) = AS->T();
*(p+i) = AS->p();
*(rhomolar+i) = AS->rhomolar();
*(hmolar+i) = AS->hmolar();
*(smolar+i) = AS->smolar();
}
catch (...){

}
};
}
catch (CoolProp::HandleError &e){
std::string errmsg = std::string("HandleError: ") + e.what();
if (errmsg.size() < static_cast<std::size_t>(buffer_length)){
*errcode = 1;
strcpy(message_buffer, errmsg.c_str());
}
else{
*errcode = 2;
}
}
catch (...){
*errcode = 3;
}
}

EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, long* outputs, double* out1, double* out2, double* out3, double* out4, double* out5, long *errcode, char *message_buffer, const long buffer_length)
{
*errcode = 0;
try{
shared_ptr<CoolProp::AbstractState> &AS = handle_manager.get(handle);

for (int i = 0; i<length; i++){
try{
AS->update(static_cast<CoolProp::input_pairs>(input_pair), *(value1+i), *(value2+i));
*(out1+i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[0]));
*(out2+i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[1]));
*(out3+i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[2]));
*(out4+i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[3]));
*(out5+i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[4]));
}
catch (...){

}
};
}
catch (CoolProp::HandleError &e){
std::string errmsg = std::string("HandleError: ") + e.what();
if (errmsg.size() < static_cast<std::size_t>(buffer_length)){
*errcode = 1;
strcpy(message_buffer, errmsg.c_str());
}
else{
*errcode = 2;
}
}
catch (...){
*errcode = 3;
}
}

0 comments on commit 2401650

Please sign in to comment.