From 90cfa1e2a612cf195175f27a4df7e104cc8a2be6 Mon Sep 17 00:00:00 2001 From: Jeff Henning Date: Sun, 9 Apr 2017 23:27:05 -0400 Subject: [PATCH] Updated Build Scripts to support Mathcad 15 and Prime wrappers (#21) * Update CMakeLists.txt to Build Wrappers - Build for either Mathcad 15 or Mathcad Prime 3.x - Slight mod to IF97.cpp for WIN32 builds - Updated README with Build instructions * Included Mathad wrapper header files in VS project via CMake script * Fix memory allocation for Mathcad if97_getvers() function, which returns a string * Added utility routines for forward and reverse vapor quality - Calc vapor quality within vapor dome - Calc H, S, U, V in terms of P & Q - Update documentation - Minor fixups with CMake script - Minor fixes to eliminate compiler warnings - Updated version to 2.1.0 --- .gitignore | 4 +- CMakeLists.txt | 88 +++++++++++++++- IF97.h | 143 +++++++++++++++++++++++++- README.md | 9 +- wrapper/Mathcad/IF97.cpp | 160 +++++++++++++++++------------ wrapper/Mathcad/README.md | 35 ------- wrapper/Mathcad/README.rst | 108 +++++++++++++++++++ wrapper/Mathcad/if97_EN.xml | 70 +++++++++++++ wrapper/Mathcad/includes/hpx.h | 43 ++++++++ wrapper/Mathcad/includes/rhopx.h | 43 ++++++++ wrapper/Mathcad/includes/spx.h | 43 ++++++++ wrapper/Mathcad/includes/upx.h | 43 ++++++++ wrapper/Mathcad/includes/version.h | 5 +- wrapper/Mathcad/includes/vpx.h | 43 ++++++++ wrapper/Mathcad/includes/xph.h | 43 ++++++++ wrapper/Mathcad/includes/xprho.h | 43 ++++++++ wrapper/Mathcad/includes/xps.h | 43 ++++++++ wrapper/Mathcad/includes/xpu.h | 41 ++++++++ wrapper/Mathcad/includes/xpv.h | 43 ++++++++ 19 files changed, 938 insertions(+), 112 deletions(-) delete mode 100644 wrapper/Mathcad/README.md create mode 100644 wrapper/Mathcad/README.rst create mode 100644 wrapper/Mathcad/includes/hpx.h create mode 100644 wrapper/Mathcad/includes/rhopx.h create mode 100644 wrapper/Mathcad/includes/spx.h create mode 100644 wrapper/Mathcad/includes/upx.h create mode 100644 wrapper/Mathcad/includes/vpx.h create mode 100644 wrapper/Mathcad/includes/xph.h create mode 100644 wrapper/Mathcad/includes/xprho.h create mode 100644 wrapper/Mathcad/includes/xps.h create mode 100644 wrapper/Mathcad/includes/xpu.h create mode 100644 wrapper/Mathcad/includes/xpv.h diff --git a/.gitignore b/.gitignore index 28b7ac9..ae8b94c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ /wrapper/Mathcad/Release /wrapper/Mathcad/Debug /wrapper/Mathcad/ipch -/wrapper/Mathcad/if97_validation.xmcd \ No newline at end of file +/wrapper/Mathcad/if97_validation.xmcd +/wrapper/Mathcad/Prime + diff --git a/CMakeLists.txt b/CMakeLists.txt index 27def31..9ced831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,87 @@ -project(IF97) +cmake_minimum_required(VERSION 2.8.11) + +####################################### +# PROJECT INFORMATION # +#-------------------------------------# +# This CMakeLists.txt file is for the # +# IAPWS-IF97 thermodynamic library # +# written by Ian Bell and Jeff # +# Henning. The following section # +# contains project and version # +# information. # +####################################### + +# Project name +set(project_name "IF97") +set(app_name ${project_name}) +project(${project_name}) + +SET(CMAKE_BUILD_TYPE Release) + +######################################################################### +# WRAPPER MODULES # +#-----------------------------------------------------------------------# +# Wrapper module compilation should be flagged from the command line. # +# Each wrapper should set(IF97_FLAG ON) to indicate a module was built. # +# If no module is specified on the command line, the IF97_FLAG is not # +# set and the default test program is built. # +######################################################################### + +######################### +# MATHCAD PRIME MODULE # +######################### + +if (IF97_PRIME_MODULE) + set(IF97_FLAG ON) + if(NOT WIN32) + message(FATAL_ERROR "IF97_PRIME_MODULE can only be used on windows host") + endif() + IF( "${IF97_PRIME_ROOT}" STREQUAL "") + message(FATAL_ERROR "You must provide the path to MathCAD Prime Root directory using something like -DIF97_PRIME_ROOT=\"C:/Program Files/PTC/Mathcad Prime 3.1\"") + else() + message(STATUS "IF97_PRIME_ROOT: ${IF97_PRIME_ROOT}") + endif() + FILE(GLOB_RECURSE IF97_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/Mathcad/includes/*.h") + include_directories("${IF97_PRIME_ROOT}/Custom Functions" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/Mathcad/includes") + add_library(IF97 SHARED ${IF97_HEADERS} "${CMAKE_CURRENT_SOURCE_DIR}/IF97.h" "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/MathCAD/IF97.cpp") + target_link_libraries(IF97 "${IF97_PRIME_ROOT}/Custom Functions/mcaduser.lib") + SET_TARGET_PROPERTIES(IF97 PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") + set_target_properties(IF97 PROPERTIES SUFFIX ".dll" PREFIX "") +# install (TARGETS IF97 DESTINATION "${IF97_INSTALL_PREFIX}/MathCADPrime") +# install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/if97_validation.mcdx" DESTINATION MathCADPrime) +endif() + +######################### +# MATHCAD 15 MODULE # +######################### + +if (IF97_MATHCAD15_MODULE) + set(IF97_FLAG ON) + if(NOT WIN32) + message(FATAL_ERROR "IF97_MATHCAD15_MODULE can only be used on windows host") + endif() + IF( "${IF97_MATHCAD15_ROOT}" STREQUAL "") + message(FATAL_ERROR "You must provide the path to MathCAD 15 Root directory using something like -DIF97_MATHCAD15_ROOT=\"C:/Program Files (x86)/Mathcad/Mathcad 15\"") + else() + message(STATUS "IF97_MATHCAD15_ROOT: ${IF97_MATHCAD15_ROOT}") + endif() + FILE(GLOB_RECURSE IF97_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/Mathcad/includes/*.h") + include_directories("${IF97_MATHCAD15_ROOT}/userefi/microsft/include" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/Mathcad/includes") + add_library(IF97 SHARED ${IF97_HEADERS} "${CMAKE_CURRENT_SOURCE_DIR}/IF97.h" "${CMAKE_CURRENT_SOURCE_DIR}/wrapper/MathCAD/IF97.cpp") + target_link_libraries(IF97 "${IF97_MATHCAD15_ROOT}/userefi/microsft/lib/mcaduser.lib") + SET_TARGET_PROPERTIES(IF97 PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") + set_target_properties(IF97 PROPERTIES SUFFIX ".dll" PREFIX "") + # install (TARGETS IF97 DESTINATION "${IF97_INSTALL_PREFIX}/MathCAD15") + # install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/if97_validation.xmcdz" DESTINATION MathCAD15) + # install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/if97_EN.xml" DESTINATION MathCAD15) +endif() + +######################### +# TEST MODULE (DEFAULT) # +######################### + +if (NOT IF97_FLAG) + message(STATUS "Stand-alone IF97 Test.") + add_executable(IF97 "${CMAKE_CURRENT_SOURCE_DIR}/IF97.cpp") +endif() -add_executable(IF97 IF97.cpp) diff --git a/IF97.h b/IF97.h index ebbbd3b..04a6761 100644 --- a/IF97.h +++ b/IF97.h @@ -28,7 +28,7 @@ struct RegionResidualElement // Structure for the double indexed state equa namespace IF97 { // CoolProp-IF97 Version Number - static char IF97VERSION [] = "v2.0.1"; + static char IF97VERSION [] = "v2.1.0"; // Setup Water Constants for Trivial Functions and use in Region Classes // Constant values from: // Revised Release on the IAPWS Industrial Formulation 1997 @@ -4094,6 +4094,81 @@ namespace IF97 } } + inline double Q_pX(double p, double X, IF97parameters inkey){ + double Xliq, Xvap; + if ((pPmax)) { + throw std::out_of_range("Pressure out of range"); + } else if (pPcrit) { + double t; + switch (inkey) { + case IF97_HMASS: + case IF97_SMASS: + t = RegionOutputBackward( p, X, inkey); break; + case IF97_UMASS: + case IF97_DMASS: + default: + // There are no reverse functions for t(p,U) or t(p,rho) + throw std::invalid_argument("Quality cannot be determined for these inputs."); + } + if (tPcrit) && (t>Tcrit) + throw std::invalid_argument("Quality not defined in supercritical region."); + } else { + switch (inkey) { + case IF97_HMASS: + case IF97_SMASS: + case IF97_UMASS: + Xliq = RegionOutput( inkey, Tsat97(p), p, LIQUID); + Xvap = RegionOutput( inkey, Tsat97(p), p, VAPOR); + return std::min(1.0,std::max(0.0,(X-Xliq)/(Xvap-Xliq))); + break; + case IF97_DMASS: + Xliq = 1.0/RegionOutput( IF97_DMASS, Tsat97(p), p, LIQUID); + Xvap = 1.0/RegionOutput( IF97_DMASS, Tsat97(p), p, VAPOR); + X = 1.0/X; + return std::min(1.0,std::max(0.0,(X-Xliq)/(Xvap-Xliq))); + break; + default: + throw std::invalid_argument("Quality cannot be determined for these inputs."); + }; + } + // If all else fails, which it shouldn't... + throw std::invalid_argument("Quality cannot be determined for these inputs."); + return -1; // Should never occur, but eliminates warnings. + }; + + inline double X_pQ(IF97parameters inkey, double p, double Q){ + double Xliq, Xvap; + if ((pPcrit)) + throw std::out_of_range("Pressure out of range"); + if ((Q<0.0) || (Q>1.0)) + throw std::out_of_range("Quality out of range"); + switch (inkey) { + case IF97_HMASS: + case IF97_SMASS: + case IF97_UMASS: + Xliq = RegionOutput( inkey, Tsat97(p), p, LIQUID); + Xvap = RegionOutput( inkey, Tsat97(p), p, VAPOR); + return Q*Xvap + (1-Q)*Xliq; + break; + case IF97_DMASS: + Xliq = 1.0/RegionOutput( IF97_DMASS, Tsat97(p), p, LIQUID); + Xvap = 1.0/RegionOutput( IF97_DMASS, Tsat97(p), p, VAPOR); + return 1.0/(Q*Xvap + (1-Q)*Xliq); + break; + default: + throw std::invalid_argument("Mixture property undefined"); + return -1; // Should never occur but eliminates warnings. + break; + }; + return -1; // Should never occur but eliminates warnings. + }; + + static double HTmaxdata[] = { 1.00645619394616E4, 1.94706669580164E5, @@ -4131,7 +4206,7 @@ namespace IF97 static Backwards::Region2cHS R2c; // Check Overall Boundaries - if ( (s < 0.0) || (s > Smax) ) + if ( (s < Smin) || (s > Smax) ) throw std::out_of_range("Entropy out of range"); if ( (h > Hmax(s)) || (h < Hmin(s)) ) throw std::out_of_range("Enthalpy out of range"); @@ -4243,8 +4318,6 @@ namespace IF97 return RegionOutputBackward(Pval,h,IF97_HMASS); // Not REGION 4 Calc from Backward T(p,h) } // Region Output backward - - // ******************************************************************************** // // API // // ******************************************************************************** // @@ -4403,6 +4476,9 @@ namespace IF97 inline double get_MW() { return MW; }; inline double get_Rgas() { return Rgas; }; inline double get_Acentric() { return -log10(psat97(0.7*Tcrit)/Pcrit) - 1; }; + // ******************************************************************************** // + // Utility Functions // + // ******************************************************************************** // inline std::string get_if97_version() { #ifdef IAPWS_UNITS std::string VSTRING(IF97VERSION); @@ -4412,6 +4488,65 @@ namespace IF97 return IF97VERSION; #endif }; + inline double hmass_pQ(double p,double Q){ + return X_pQ(IF97_HMASS, p, Q); + }; + inline double umass_pQ(double p,double Q){ + return X_pQ(IF97_UMASS, p, Q); + }; + inline double smass_pQ(double p,double Q){ + return X_pQ(IF97_SMASS, p, Q); + }; + inline double v_pQ(double p,double Q){ + return 1.0/X_pQ(IF97_DMASS, p, Q); + }; + inline double rhomass_pQ(double p,double Q){ + return X_pQ(IF97_DMASS, p, Q); + }; + inline double Q_phmass(double p,double h){ + return Q_pX(p, h, IF97_HMASS); + }; + inline double Q_pumass(double p,double u){ + return Q_pX(p, u, IF97_UMASS); + }; + inline double Q_psmass(double p,double s){ + return Q_pX(p, s, IF97_SMASS); + }; + inline double Q_prhomass(double p,double rho){ + return Q_pX(p, rho, IF97_DMASS); + }; + inline double Q_pv(double p,double v){ + return Q_pX(p, 1.0/v, IF97_DMASS); + }; +/*************************************************************************/ +/* Vapor Quality as a function of H and S cannot be implemented at this */ +/* time as there IAPWS has not released a backward formula that covers */ +/* the entire vapor dome. T(H,S) is only currently defined for the */ +/* range of s > s"(T23sat). Leaving this code here in case IAPWS */ +/* releases a fit for the entire vapor dome. */ +/*************************************************************************/ +/* inline double Q_hsmass(double h, double s){ + double hliq, hvap; + if ((s < Smin) || (s > Smax)) { + throw std::out_of_range("Entropy out of range"); + } else if ((h < Hmin(s)) || (h > Hmax(s))) { + throw std::out_of_range("Enthalpy out of range"); + } + double p = BackwardOutputHS(IF97_P, h, s); + double t = RegionOutputBackward( p, h, IF97_HMASS); + if ((p > Pcrit) && (t > Tcrit)) { + throw std::out_of_range("Temperature out of range"); + } else if (BackwardRegion(p, h, IF97_HMASS) == 4) { + hliq = RegionOutput( IF97_HMASS, Tsat97(p), p, LIQUID); + hvap = RegionOutput( IF97_HMASS, Tsat97(p), p, VAPOR); + return std::min(1.0,std::max(0.0,(h-hliq)/(hvap-hliq))); + } else if (p > Pcrit) { + return 0.0; + } else { + return 1.0; + } + }; */ +/*************************************************************************/ }; /* namespace IF97 */ diff --git a/README.md b/README.md index ac92c4e..4c8276a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -============= CoolProp IF97 ============= @@ -58,6 +57,10 @@ Transport property functions have been implemented for temperature/pressure stat - Surface Tension: ``sigma97(t)`` - Prandtl Number: ``prandtl_Tp(T,p)``, ``prandtlliq_p(p)``, and ``prandtlvap_p(p)`` +Utility functions provide forward and backward evaluations using vapor quality in the steam dome. These include: +- Forward functions: ``Q_phmass(p,h)``, ``Q_pumass(p,u)``, ``Q_psmass(p,s)``, ``Q_prhomass(p,rho)``, ``Q_pv(p,v)`` +- Backward functions: ``hmass_pQ(p,Q)``, ``umass_pQ(p,Q)``, ``smass_pQ(p,Q)``, ``rhomass_pQ(p,Q)``, ``vmass_pQ(p,Q)`` + As of IF97 v2.0.0, a utility function ``get_if97_version()`` will return the official version string for this IF97 implementation. License @@ -72,5 +75,5 @@ You are strongly requested, but not required, to cite both this repository and t Wrappers -------- -Wrappers directory started for 3rd Party Apps, including: -- Mathcad 15 (Jeff Henning main contributor) +Wrappers directory for 3rd Party Apps, including: +- Mathcad 15 and Prime (Jeff Henning main contributor) diff --git a/wrapper/Mathcad/IF97.cpp b/wrapper/Mathcad/IF97.cpp index 80cf143..7b8e00c 100644 --- a/wrapper/Mathcad/IF97.cpp +++ b/wrapper/Mathcad/IF97.cpp @@ -19,11 +19,11 @@ enum { MC_STRING = STRING }; // substitute enumeration variable MC_STRING for S #define REGION3_ITERATE // #define IAPWS_UNITS // Set to use IAPWS Units of [MPa] and [kJ] (instead of [Pa] and [J] ) -#include "../../IF97.h" +#include "IF97.h" // Mathcad Error Codes enum EC {MUST_BE_REAL = 1, INSUFFICIENT_MEMORY, INTERRUPTED, T_OUT_OF_RANGE, P_OUT_OF_RANGE, SATURATED, NO_SOLUTION_FOUND, - D_OUT_OF_RANGE, H_OUT_OF_RANGE, S_OUT_OF_RANGE, REGION_NOT_FOUND, UNKNOWN, NUMBER_OF_ERRORS}; + D_OUT_OF_RANGE, H_OUT_OF_RANGE, S_OUT_OF_RANGE, Q_OUT_OF_RANGE, REGION_NOT_FOUND, UNKNOWN, NUMBER_OF_ERRORS}; // Table of Error Messages // These message strings MUST be in the order of the Error Code enumeration above, with the last being a dummy value for error count @@ -39,6 +39,7 @@ enum EC {MUST_BE_REAL = 1, INSUFFICIENT_MEMORY, INTERRUPTED, T_OUT_OF_RANGE, P_ "Density out of Range", "Enthalpy out of Range", "Entropy out of Range", + "Quality out of Range", "Region not found", "Exception thrown - Error Unknown", "Error Count - Not Used" @@ -49,83 +50,99 @@ enum EC {MUST_BE_REAL = 1, INSUFFICIENT_MEMORY, INTERRUPTED, T_OUT_OF_RANGE, P_ // ************************************************************* // Basic function stubs // ************************************************************* - #include ".\includes\tsatp.h" - #include ".\includes\ttrip.h" - #include ".\includes\tcrit.h" - #include ".\includes\psatt.h" - #include ".\includes\ptrip.h" - #include ".\includes\pcrit.h" - #include ".\includes\rhotp.h" - #include ".\includes\vtp.h" - #include ".\includes\htp.h" - #include ".\includes\utp.h" - #include ".\includes\stp.h" - #include ".\includes\cptp.h" - #include ".\includes\cvtp.h" - #include ".\includes\wtp.h" + #include "tsatp.h" + #include "ttrip.h" + #include "tcrit.h" + #include "psatt.h" + #include "ptrip.h" + #include "pcrit.h" + #include "rhotp.h" + #include "vtp.h" + #include "htp.h" + #include "utp.h" + #include "stp.h" + #include "cptp.h" + #include "cvtp.h" + #include "wtp.h" // ************************************************************* // Saturation function stubs // ************************************************************* - #include ".\includes\rhof.h" - #include ".\includes\rhog.h" - #include ".\includes\vf.h" - #include ".\includes\vg.h" - #include ".\includes\hf.h" - #include ".\includes\hg.h" - #include ".\includes\uf.h" - #include ".\includes\ug.h" - #include ".\includes\sf.h" - #include ".\includes\sg.h" - #include ".\includes\cpf.h" - #include ".\includes\cpg.h" - #include ".\includes\cvf.h" - #include ".\includes\cvg.h" - #include ".\includes\wf.h" - #include ".\includes\wg.h" + #include "rhof.h" + #include "rhog.h" + #include "vf.h" + #include "vg.h" + #include "hf.h" + #include "hg.h" + #include "uf.h" + #include "ug.h" + #include "sf.h" + #include "sg.h" + #include "cpf.h" + #include "cpg.h" + #include "cvf.h" + #include "cvg.h" + #include "wf.h" + #include "wg.h" // ************************************************************* // Transport Property Stubs // ************************************************************* - #include ".\includes\sigma.h" - #include ".\includes\mutp.h" - #include ".\includes\mutrho.h" // this function provided for validation work only - #include ".\includes\muf.h" - #include ".\includes\mug.h" - #include ".\includes\ktp.h" - #include ".\includes\kf.h" - #include ".\includes\kg.h" - #include ".\includes\prtp.h" - #include ".\includes\prf.h" - #include ".\includes\prg.h" + #include "sigma.h" + #include "mutp.h" + #include "mutrho.h" // this function provided for validation work only + #include "muf.h" + #include "mug.h" + #include "ktp.h" + #include "kf.h" + #include "kg.h" + #include "prtp.h" + #include "prf.h" + #include "prg.h" // ************************************************************* // Test Functions // ************************************************************* - #include ".\includes\p23.h" - #include ".\includes\t23.h" - #include ".\includes\regionph.h" - #include ".\includes\regionps.h" - #include ".\includes\h3ab.h" - #include ".\includes\h2ab.h" - #include ".\includes\h2bc.h" - #include ".\includes\h13.h" - #include ".\includes\hsats.h" - #include ".\includes\hmaxs.h" - #include ".\includes\hmins.h" - #include ".\includes\drhodp.h" - #include ".\includes\version.h" + #include "p23.h" + #include "t23.h" + #include "regionph.h" + #include "regionps.h" + #include "h3ab.h" + #include "h2ab.h" + #include "h2bc.h" + #include "h13.h" + #include "hsats.h" + #include "hmaxs.h" + #include "hmins.h" + #include "drhodp.h" + #include "version.h" // ************************************************************* // Reverse Functions // ************************************************************* - #include ".\includes\tph.h" - #include ".\includes\tps.h" - #include ".\includes\phs.h" - #include ".\includes\ths.h" - #include ".\includes\rhoph.h" - #include ".\includes\rhops.h" + #include "tph.h" + #include "tps.h" + #include "phs.h" + #include "ths.h" + #include "rhoph.h" + #include "rhops.h" + // ************************************************************* + // Quality Functions + // ************************************************************* + #include "xph.h" + #include "xprho.h" + #include "xps.h" + #include "xpu.h" + #include "xpv.h" + #include "hpx.h" + #include "rhopx.h" + #include "spx.h" + #include "upx.h" + #include "vpx.h" + // ************************************************************************************ + // DLL entry point code. + // ************************************************************************************ + // The _CRT_INIT function is needed if you are using Microsoft's 32 bit compiler - // DLL entry point code. the _CRT_INIT function is needed - // if you are using Microsoft's 32 bit compiler - +#ifdef _WIN32 extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved); +#endif extern "C" BOOL WINAPI DllEntryPoint (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) { @@ -229,6 +246,19 @@ enum EC {MUST_BE_REAL = 1, INSUFFICIENT_MEMORY, INTERRUPTED, T_OUT_OF_RANGE, P_ CreateUserFunction( hDLL, &if97_ths ); CreateUserFunction( hDLL, &if97_rhoph ); CreateUserFunction( hDLL, &if97_rhops ); + // ************************************************************* + // Quality functions + // ************************************************************* + CreateUserFunction( hDLL, &if97_xph ); + CreateUserFunction( hDLL, &if97_xprho ); + CreateUserFunction( hDLL, &if97_xps ); + CreateUserFunction( hDLL, &if97_xpu ); + CreateUserFunction( hDLL, &if97_xpv ); + CreateUserFunction( hDLL, &if97_hpx ); + CreateUserFunction( hDLL, &if97_rhopx ); + CreateUserFunction( hDLL, &if97_spx ); + CreateUserFunction( hDLL, &if97_upx ); + CreateUserFunction( hDLL, &if97_vpx ); break; } diff --git a/wrapper/Mathcad/README.md b/wrapper/Mathcad/README.md deleted file mode 100644 index 5f75888..0000000 --- a/wrapper/Mathcad/README.md +++ /dev/null @@ -1,35 +0,0 @@ -Wrapper of IF97 for MathCAD 15 -================================== - -Has been developed and tested on Mathcad 15.0 (any maintenance release). May work on earlier versions, but it has not been tested there. - -To Use -====== - -* Compile in VS2010 or later using the solution and project files - -* Copy the if97.dll file to C:\\Program Files (x86)\\Mathcad\\Mathcad 15\\userefi or equivalent for your version (this will be done automatically by the project) - -* Copy the IF97_EN.xml to C:\\Program Files (x86)\\Mathcad\\Mathcad 15\\doc\\funcdoc. Functions and descriptions will then be available in the Mathcad 15 interface under Insert|Function or the Functions button on the toolbar. - -* View if97_verification.xmcdz or if97_verification.pdf for examples of using the functions. - -To Build -======== - -* You will need to have Visual Studio 2008 installed (Express version is fine). Alternatively newer versions of Microsoft Visual Studio C++ should be fine, you'll just have to update the solution and project files - -* Build the if97 DLL in Visual Studio. The project will automatically copy the DLL and function documentation to the appropriate Mathcad installation directory. You may have to allow user write access to both: - - ``C:\Program Files (x86)\Mathcad\Mathcad 15\userefi`` - - and - - ``C:\Program Files (x86)\Mathcad\Mathcad 15\doc\funcdoc`` - -* Follow the above instructions for use. - -Compiler Flags -============== - -The Mathcad wrapper code uses the ``REGION3_ITERATE`` flag to provide more accurate (but slightly slower) calculation of density in Region 3 (mostly super-critical) and does not use the ``IAPWS_UNITS`` flag, leaving all input/output values in SI units. diff --git a/wrapper/Mathcad/README.rst b/wrapper/Mathcad/README.rst new file mode 100644 index 0000000..7ec8db1 --- /dev/null +++ b/wrapper/Mathcad/README.rst @@ -0,0 +1,108 @@ +Wrapper of IF97 for MathCAD 15 and Mathcad Prime +================================================ + +This wrapper will provide User Defined (Custom) Functions in Mathcad 15 (or Prime) that provide thermodynamic and transport properties for water/steam at specified state points based on the IAPWS Industrial Formulation for the Properties of Water and Steam. While these properties can also be accessed through the CoolProp add-in, this wrapper provides **_only_** these properties without the overhead of CoolProp. + +This wrapper been developed and tested on Mathcad 15.0 (any maintenance release) and Mathcad Prime 3.0/3.1. It May work on earlier versions of Mathcad and Mathcad Prime, but it has not been tested there. + +------ + +To Use +====== + +* Build the Add-in DLL in VS2008 or later using the build instructions below. + +* Install the Add-in files by copying them to the appropriate Mathcad 15/Prime Installation directories. + +* View ``if97_verification.xmcdz`` or ``if97_verification.pdf`` for examples of using the functions. + +------ + +To Build +======== + +Follow the build procedures below to ceate the IF97 add-in DLL files for either Mathcad 15 or Mathcad Prime. + +Pre-Requisites +-------------- + +* You will need to have at least Visual Studio 2008 installed (Express version is fine). Alternatively newer versions of Microsoft Visual Studio C++ should be fine; Builds have be tested on Visual Studio 2010 and 2015. +* You will need CMake version 2.8.12 or later from https://cmake.org/download/ +* You will need to install Git-SCM for Windows. You can install this from https://git-for-windows.github.io + +Download the IF97 Repository +---------------------------- + +* Open a Git window at the drive location where you want to create your local IF97 repository + +* Clone the CoolProp/IF97 repository to a local repository (If you haven't already cloned it recursively with CoolProp).:: + + git clone https://github.com/CoolProp/IF97 + +* Change directory (cd) to the IF97 directory you just created.:: + + cd IF97 + +Make the Build for Mathcad 15 +----------------------------- + +* Go to the top level IF97 directory and make a build directory (something like \build15):: + + mkdir build15 + cd build15 + +* Build the makefile using CMake (Note: Mathcad 15 is 32-bit):: + + cmake .. -DIF97_MATHCAD15_MODULE=ON + -DIF97_MATHCAD15_ROOT="C:/Program Files (x86)/Mathcad/Mathcad 15" + -G "Visual Studio 10 2010" + -DCMAKE_VERBOSE_MAKEFILE=ON + + (Insert your version of Visual Studio for the -G option.) + +Make the Build for Mathcad Prime +-------------------------------- + +* Go to the top level IF97 directory and make a build directory (something like \buildPrime):: + + mkdir buildPrime + cd buildPrime + +* Build the makefile using CMake (Note: Mathcad Prime is 64-bit):: + + cmake .. -DIF97_PRIME_MODULE=ON + -DIF97_PRIME_ROOT="C:/Program Files (x86)/Mathcad/Mathcad 15" + -G "Visual Studio 10 2010 -Win64" + -DCMAKE_VERBOSE_MAKEFILE=ON + + (Insert your version of Visual Studio for the -G option.) + (Note that Prime is 64-bit and requires the -Win64 switch on this command) + +Build the Project +----------------- + +* Open the resulting IF97.sln file in Visual Studio and build the IF97 project, making sure that ``Release`` configuration is selected and the the configuration and platform. Alternatively, you can make the dynamic library (DLL) from the command line:: + + cmake --build . --config Release + +------ + +Installing +========== + +* Build the IF97 DLL as indicated above and then copy the wrapper files to the appropriate Mathcad 15 or Prime directories as follows. + +Mathcad 15 +---------- +* Copy the ``Release\IF97.dll`` file to ``C:\Program Files (x86)\Mathcad\Mathcad 15\userefi`` or equivalent for your version of Mathcad. +* **Mathcad 15 Only:** Copy the ``IF97_EN.xml`` to ``C:\Program Files (x86)\Mathcad\Mathcad 15\doc\funcdoc``. Functions and descriptions will then be available in the Mathcad 15 interface under Insert|Function or the Functions button on the toolbar. + +Mathcad Prime +---------- +* Copy the ``Release\IF97.dll`` file to ``C:\Program Files\PTC\Mathcad Prime 3.1\Custom Functions`` or equivalent for your version of Mathcad Prime. + +------ + +Compiler Flags +============== +The Mathcad wrapper code uses the ``REGION3_ITERATE`` flag to provide more accurate (but slightly slower) calculation of density in Region 3 (mostly super-critical) and does not use the ``IAPWS_UNITS`` flag, leaving all input/output values in SI units. \ No newline at end of file diff --git a/wrapper/Mathcad/if97_EN.xml b/wrapper/Mathcad/if97_EN.xml index 9880d50..8ff615b 100644 --- a/wrapper/Mathcad/if97_EN.xml +++ b/wrapper/Mathcad/if97_EN.xml @@ -314,5 +314,75 @@ if97 (Water Properties) Returns the version of the IF97 implementation code. Takes a "dummy" parameter that can be (0). + + if97_xph + if97_xph + p,h + if97 (Water Properties) + Returns the steam quality, x, as a function of pressure, p [Pa], and mass enthalpy, h [J/kg]. + + + if97_xps + if97_xps + p,s + if97 (Water Properties) + Returns the steam quality, x, as a function of pressure, p [Pa], and mass entropy, s [J/kg-K]. + + + if97_xpu + if97_xpu + p,u + if97 (Water Properties) + Returns the steam quality, x, as a function of pressure, p [Pa], and mass internal energy, u [J/kg]. + + + if97_xpv + if97_xpv + p,v + if97 (Water Properties) + Returns the steam quality, x, as a function of pressure, p [Pa], and specific volume, v [m³/kg]. + + + if97_xprho + if97_xprho + p,rho + if97 (Water Properties) + Returns the steam quality, x, as a function of pressure, p [Pa], and mass density, rho [kg/m³]. + + + if97_hpx + if97_hpx + p,x + if97 (Water Properties) + Returns the mass enthalpy, h [J/kg], as a function of pressure, p [Pa], and steam quality, x, within the vapor dome. + + + if97_spx + if97_spx + p,x + if97 (Water Properties) + Returns the mass entropy, s [J/kg-K], as a function of pressure, p [Pa], and steam quality, x, within the vapor dome. + + + if97_upx + if97_upx + p,x + if97 (Water Properties) + Returns the mass internal engergy, u [J/kg], as a function of pressure, p [Pa], and steam quality, x, within the vapor dome. + + + if97_vpx + if97_vpx + p,x + if97 (Water Properties) + Returns the specific volume, v [m³/kg], as a function of pressure, p [Pa], and steam quality, x, within the vapor dome. + + + if97_rhopx + if97_rhopx + p,x + if97 (Water Properties) + Returns the mass density, rho [kg/m³], as a function of pressure, p [Pa], and steam quality, x, within the vapor dome. + diff --git a/wrapper/Mathcad/includes/hpx.h b/wrapper/Mathcad/includes/hpx.h new file mode 100644 index 0000000..34d69d5 --- /dev/null +++ b/wrapper/Mathcad/includes/hpx.h @@ -0,0 +1,43 @@ +// if97_hpx stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_hpx(p,x), which is a wrapper for +// the CoolProp-IF97 function, hmass_pQ(p,Q). +LRESULT if97_HPX( + LPCOMPLEXSCALAR h, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR x) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( x->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + h->real = IF97::hmass_pQ(p->real,x->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'Q') + return MAKELRESULT(Q_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_hpx = +{ + "if97_hpx", // name by which Mathcad will recognize the function + "p,x", // if97_hpx will be called as if97_hpx(p,x) + // description of if97_hpx(p,x) + "Obtains the mass enthalpy [J/kg] as a function of pressure, p [Pa], and steam quality, x.", + (LPCFUNCTION)if97_HPX, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/rhopx.h b/wrapper/Mathcad/includes/rhopx.h new file mode 100644 index 0000000..15dd942 --- /dev/null +++ b/wrapper/Mathcad/includes/rhopx.h @@ -0,0 +1,43 @@ +// if97_rhopx stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_rhopx(p,x), which is a wrapper for +// the CoolProp-IF97 function, rhomass_pQ(p,Q). +LRESULT if97_RHOPX( + LPCOMPLEXSCALAR rho, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR x) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( x->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + rho->real = IF97::rhomass_pQ(p->real,x->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'Q') + return MAKELRESULT(Q_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_rhopx = +{ + "if97_rhopx", // name by which Mathcad will recognize the function + "p,x", // if97_rhopx will be called as if97_rhopx(p,x) + // description of if97_rhopx(p,x) + "Obtains the mixture density [kg/m³] as a function of pressure, p [Pa], and steam quality, x.", + (LPCFUNCTION)if97_RHOPX, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/spx.h b/wrapper/Mathcad/includes/spx.h new file mode 100644 index 0000000..7d524d4 --- /dev/null +++ b/wrapper/Mathcad/includes/spx.h @@ -0,0 +1,43 @@ +// if97_spx stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_spx(p,x), which is a wrapper for +// the CoolProp-IF97 function, smass_pQ(p,Q). +LRESULT if97_SPX( + LPCOMPLEXSCALAR s, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR x) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( x->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + s->real = IF97::smass_pQ(p->real,x->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'Q') + return MAKELRESULT(Q_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_spx = +{ + "if97_spx", // name by which Mathcad will recognize the function + "p,x", // if97_spx will be called as if97_spx(p,x) + // description of if97_spx(p,x) + "Obtains the mass entropy [J/kg-K] as a function of pressure, p [Pa], and steam quality, x.", + (LPCFUNCTION)if97_SPX, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/upx.h b/wrapper/Mathcad/includes/upx.h new file mode 100644 index 0000000..2a15981 --- /dev/null +++ b/wrapper/Mathcad/includes/upx.h @@ -0,0 +1,43 @@ +// if97_upx stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_upx(p,x), which is a wrapper for +// the CoolProp-IF97 function, umass_pQ(p,Q). +LRESULT if97_UPX( + LPCOMPLEXSCALAR u, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR x) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( x->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + u->real = IF97::umass_pQ(p->real,x->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'Q') + return MAKELRESULT(Q_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_upx = +{ + "if97_upx", // name by which Mathcad will recognize the function + "p,x", // if97_upx will be called as if97_upx(p,x) + // description of if97_upx(p,x) + "Obtains the mass internal energy [J/kg] as a function of pressure, p [Pa], and steam quality, x.", + (LPCFUNCTION)if97_UPX, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/version.h b/wrapper/Mathcad/includes/version.h index 6e2e3da..47e739d 100644 --- a/wrapper/Mathcad/includes/version.h +++ b/wrapper/Mathcad/includes/version.h @@ -8,12 +8,13 @@ LRESULT IF97_Version( LPCCOMPLEXSCALAR dummy) // pointer to the dummy parameter received from Mathcad // Unfortunately Mathcad functions have to pass at least // one parameter and it cannot be void. -{ +{ + // Note: we don't care what gets passed in. // call IF97's get_if97_version() routine; std::string s = IF97::get_if97_version(); - char * c = new char [s.size()+1]; //create a c-string (pointer) with same size as s + char * c = MathcadAllocate(static_cast(s.size())+1); //create a c-string (pointer) with same size as s // copy s into c, this process avoids the const-cast type which would result // from instead converting the string using s.c_str() std::copy(s.begin(), s.end(), c); diff --git a/wrapper/Mathcad/includes/vpx.h b/wrapper/Mathcad/includes/vpx.h new file mode 100644 index 0000000..f7216a3 --- /dev/null +++ b/wrapper/Mathcad/includes/vpx.h @@ -0,0 +1,43 @@ +// if97_vpx stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_vpx(p,x), which is a wrapper for +// the CoolProp-IF97 function, v_pQ(p,Q). +LRESULT if97_VPX( + LPCOMPLEXSCALAR v, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR x) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( x->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + v->real = IF97::v_pQ(p->real,x->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'Q') + return MAKELRESULT(Q_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_vpx = +{ + "if97_vpx", // name by which Mathcad will recognize the function + "p,x", // if97_vpx will be called as if97_vpx(p,x) + // description of if97_vpx(p,x) + "Obtains the specific volume [m³/kg] as a function of pressure, p [Pa], and steam quality, x.", + (LPCFUNCTION)if97_VPX, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/xph.h b/wrapper/Mathcad/includes/xph.h new file mode 100644 index 0000000..b0b9ff4 --- /dev/null +++ b/wrapper/Mathcad/includes/xph.h @@ -0,0 +1,43 @@ +// if97_xph stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_xph(p,h), which is a wrapper for +// the CoolProp-IF97 function, Q_phmass(p,h). +LRESULT if97_XPH( + LPCOMPLEXSCALAR x, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR h) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "h" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( h->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + x->real = IF97::Q_phmass(p->real,h->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if ((e.what()[0] == 'E') && (e.what()[3] == 'h')) + return MAKELRESULT(H_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_xph = +{ + "if97_xph", // name by which Mathcad will recognize the function + "p,h", // if97_xph will be called as if97_xph(p,h) + // description of if97_xph(p,h) + "Obtains the steam quality, x, as a function of pressure, p [Pa], and mass enthalpy [J/kg].", + (LPCFUNCTION)if97_XPH, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/xprho.h b/wrapper/Mathcad/includes/xprho.h new file mode 100644 index 0000000..2069a77 --- /dev/null +++ b/wrapper/Mathcad/includes/xprho.h @@ -0,0 +1,43 @@ +// if97_xprho stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_xprho(p,rho), which is a wrapper for +// the CoolProp-IF97 function, Q_prhomass(p,rho). +LRESULT if97_XPRHO( + LPCOMPLEXSCALAR x, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR rho) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "rho" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( rho->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + x->real = IF97::Q_prhomass(p->real,rho->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'D') + return MAKELRESULT(D_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_xprho = +{ + "if97_xprho", // name by which Mathcad will recognize the function + "p,rho", // if97_xprho will be called as if97_xprho(p,rho) + // description of if97_xprho(p,rho) + "Obtains the steam quality, x, as a function of pressure, p [Pa], and mass density [kg/m³].", + (LPCFUNCTION)if97_XPRHO, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/xps.h b/wrapper/Mathcad/includes/xps.h new file mode 100644 index 0000000..e1c91af --- /dev/null +++ b/wrapper/Mathcad/includes/xps.h @@ -0,0 +1,43 @@ +// if97_xps stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_xps(p,s), which is a wrapper for +// the CoolProp-IF97 function, Q_psmass(p,s). +LRESULT if97_XPS( + LPCOMPLEXSCALAR x, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR s) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "s" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( s->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + x->real = IF97::Q_psmass(p->real,s->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if ((e.what()[0] == 'E') && (e.what()[3] == 'r')) + return MAKELRESULT(S_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_xps = +{ + "if97_xps", // name by which Mathcad will recognize the function + "p,s", // if97_xps will be called as if97_xps(p,s) + // description of if97_xps(p,s) + "Obtains the steam quality, x, as a function of pressure, p [Pa], and mass entropy [J/kg-K].", + (LPCFUNCTION)if97_XPS, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/xpu.h b/wrapper/Mathcad/includes/xpu.h new file mode 100644 index 0000000..d44750c --- /dev/null +++ b/wrapper/Mathcad/includes/xpu.h @@ -0,0 +1,41 @@ +// if97_xpu stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_xpu(p,u), which is a wrapper for +// the CoolProp-IF97 function, Q_pumass(p,u). +LRESULT if97_XPU( + LPCOMPLEXSCALAR x, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR u) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "x" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( u->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + x->real = IF97::Q_pumass(p->real,u->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_xpu = +{ + "if97_xpu", // name by which Mathcad will recognize the function + "p,u", // if97_xpu will be called as if97_xpu(p,u) + // description of if97_xpu(p,u) + "Obtains the steam quality, x, as a function of pressure, p [Pa], and mass internal energy [J/kg].", + (LPCFUNCTION)if97_XPU, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file diff --git a/wrapper/Mathcad/includes/xpv.h b/wrapper/Mathcad/includes/xpv.h new file mode 100644 index 0000000..df7a18a --- /dev/null +++ b/wrapper/Mathcad/includes/xpv.h @@ -0,0 +1,43 @@ +// if97_xpv stub - Interfaces CoolProp IF97 function to Mathcad +// + +// this code executes the user function if97_xpv(p,v), which is a wrapper for +// the CoolProp-IF97 function, Q_prhomass(p,v). +LRESULT if97_XPV( + LPCOMPLEXSCALAR x, // pointer to the result + LPCCOMPLEXSCALAR p, + LPCCOMPLEXSCALAR v) // pointer to the parameter received from Mathcad +{ + // first check to make sure "p" and "rho" have no imaginary component + if ( p->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,1); + if ( v->imag != 0.0 ) + return MAKELRESULT(MUST_BE_REAL,2); + + //otherwise, all is well, evaluate function + try { + x->real = IF97::Q_pv(p->real,v->real); + } + catch (const std::out_of_range& e) { + if (e.what()[0] == 'P') + return MAKELRESULT(P_OUT_OF_RANGE,1); + else if (e.what()[0] == 'D') + return MAKELRESULT(D_OUT_OF_RANGE,2); + else + return MAKELRESULT(UNKNOWN,1); + } + // normal return + return 0; +} + +FUNCTIONINFO if97_xpv = +{ + "if97_xpv", // name by which Mathcad will recognize the function + "p,v", // if97_xpv will be called as if97_xpv(p,v) + // description of if97_xpv(p,v) + "Obtains the steam quality, x, as a function of pressure, p [Pa], and specific volume [m³/kg].", + (LPCFUNCTION)if97_XPV, // pointer to executable code + COMPLEX_SCALAR, // the return type is a complex scalar + 2, // there are two input parameters + { COMPLEX_SCALAR, COMPLEX_SCALAR } // that are both complex scalars +}; \ No newline at end of file