Skip to content

Commit

Permalink
Updated Build Scripts to support Mathcad 15 and Prime wrappers (#21)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
henningjp authored and ibell committed Apr 10, 2017
1 parent a97fc3b commit 90cfa1e
Show file tree
Hide file tree
Showing 19 changed files with 938 additions and 112 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
/wrapper/Mathcad/Release
/wrapper/Mathcad/Debug
/wrapper/Mathcad/ipch
/wrapper/Mathcad/if97_validation.xmcd
/wrapper/Mathcad/if97_validation.xmcd
/wrapper/Mathcad/Prime

88 changes: 86 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
143 changes: 139 additions & 4 deletions IF97.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -4094,6 +4094,81 @@ namespace IF97
}
}

inline double Q_pX(double p, double X, IF97parameters inkey){
double Xliq, Xvap;
if ((p<Pmin) || (p>Pmax)) {
throw std::out_of_range("Pressure out of range");
} else if (p<Ptrip) {
return 0; //Liquid, at all temperatures
} else if (p>Pcrit) {
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 (t<Tcrit)
return 1.0; // Vapor, at all pressures above critical point
else
// Supercritical Region (p>Pcrit) && (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 ((p<Ptrip) || (p>Pcrit))
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,
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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 //
// ******************************************************************************** //
Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
=============
CoolProp IF97
=============

Expand Down Expand Up @@ -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
Expand All @@ -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)
Loading

0 comments on commit 90cfa1e

Please sign in to comment.