mirror of
https://github.com/CoolProp/CoolProp.git
synced 2026-04-23 03:00:17 -04:00
Working on the docs...
This commit is contained in:
131
Web/Makefile
131
Web/Makefile
@@ -1,5 +1,100 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
# Generate and copy the include files for the documetation #
|
||||
############################################################
|
||||
#
|
||||
INCOMP_INCLUDES_SOURCE:=$(realpath $(CURDIR)/../dev/incompressible_liquids )
|
||||
#INCOMP_INCLUDES_TARGET:=$(realpath $(CURDIR)/fluid_properties )
|
||||
INCOMP_INCLUDES_TARGET:=fluid_properties
|
||||
# JSON, PDF and JPG all depend on Python, regenerate all of them if Python sources change
|
||||
INCOMP_INCLUDES_PYTHON:=$(shell find $(INCOMP_INCLUDES_SOURCE)/CPIncomp -iname '*.py') # recursively
|
||||
INCOMP_INCLUDES_JSONLI:=$(shell find $(INCOMP_INCLUDES_SOURCE)/json -iname '*.json') # recursively
|
||||
INCOMP_INCLUDES_FNAMES:=$(basename $(notdir $(INCOMP_INCLUDES_JSONLI) ) ) # all fluid IDs
|
||||
# All the required files
|
||||
INCOMP_INCLUDES_PDFREP:=$(addprefix $(INCOMP_INCLUDES_TARGET)/report/, $(addsuffix _fitreport.pdf, $(INCOMP_INCLUDES_FNAMES) ) )
|
||||
INCOMP_INCLUDES_PDFEXT:= all_pure-pdf all_solutions.pdf
|
||||
INCOMP_INCLUDES_PDFEXT:=$(addprefix $(INCOMP_INCLUDES_TARGET)/, $(INCOMP_INCLUDES_PDFEXT) )
|
||||
INCOMP_INCLUDES_TXTTAB:= pure-fluids.txt mass-based-fluids.txt mole-based-fluids.txt volume-based-fluids.txt
|
||||
INCOMP_INCLUDES_TXTTAB:=$(addprefix $(INCOMP_INCLUDES_TARGET)/, $(INCOMP_INCLUDES_TXTTAB) )
|
||||
#
|
||||
# Define one single target to be referenced
|
||||
.PHONY: incompressible_includes
|
||||
incompressible_includes: $(INCOMP_INCLUDES_PDFREP) $(INCOMP_INCLUDES_PDFEXT) $(INCOMP_INCLUDES_TXTTAB)
|
||||
#
|
||||
# Now we split it up again and maps dependencies to their generators
|
||||
$(INCOMP_INCLUDES_TXTTAB):: $(INCOMP_INCLUDES_SOURCE)/Incompressibles_include_generator.py
|
||||
cd $(<D); \
|
||||
python $(<F)
|
||||
|
||||
|
||||
$(INCOMP_INCLUDES_TARGET)/report/%.pdf: $(INCOMP_INCLUDES_SOURCE)/report/%.pdf
|
||||
mkdir -p $(@D); \
|
||||
cp $< $@
|
||||
|
||||
#%.foo: $$(addsuffix .bar, $$(DATA_$$*))
|
||||
|
||||
|
||||
$(INCOMP_INCLUDES_SOURCE)/report/%.pdf: $(INCOMP_INCLUDES_SOURCE)/all_incompressibles.py $(INCOMP_INCLUDES_PYTHON)
|
||||
cd $(<D); \
|
||||
python $(<F)
|
||||
|
||||
#$(INCOMP_INCLUDES_PDFREP):: $(INCOMP_INCLUDES_SOURCE)/all_incompressibles.py $(INCOMP_INCLUDES_PYTHON)
|
||||
# cd $(<D); \
|
||||
# python $(<F)
|
||||
|
||||
|
||||
#$(INCOMP_INCLUDES_TARGET)/Incompressibles_Fluids.txt: $(addprefix $(PYGEN_DIR)/, Incompressibles_include_generator.py)
|
||||
# cd $(PYGEN_DIR); \
|
||||
# python Incompressibles_include_generator.py
|
||||
#
|
||||
#fluid_properties/all_pure.pdf: $(addprefix $(PYGEN_DIR)/, all_incompressibles.py)
|
||||
# cd $(PYGEN_DIR); \
|
||||
# python all_incompressibles.py
|
||||
# cp $(PYGEN_DIR)/all_pure.pdf fluid_properties/
|
||||
# cp $(PYGEN_DIR)/all_solutions.pdf fluid_properties/
|
||||
#
|
||||
## general rules for the fit reports
|
||||
#PYGEN_FILES=$(shell echo $(COOLPROPDIR)*.cpp)
|
||||
#
|
||||
#
|
||||
## Make the .pdf report files, they all come from the same script
|
||||
#$(INCOMP_INCLUDES_FOLDER)/%.pdf : $(INCOMP_INCLUDES_DIR)/all_incompressibles.py $(INCOMP_INCLUDES_PYTHON)
|
||||
# cd $(INCOMP_INCLUDES_FOLDER); \
|
||||
# python all_incompressibles.py
|
||||
#
|
||||
### Make the .pdf report files, they all come from the same script
|
||||
##$(INCOMP_INCLUDES_FOLDER)/report/%.pdf : $(INCOMP_INCLUDES_PYTHON)
|
||||
## cd $(INCOMP_INCLUDES_FOLDER); \
|
||||
## python all_incompressibles.py
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY : check_incomp_flags
|
||||
check_incomp_flags:
|
||||
@printf "\nMakefile variables:\n\
|
||||
INCOMP_INCLUDES_SOURCE=$(INCOMP_INCLUDES_SOURCE)\n\
|
||||
INCOMP_INCLUDES_TARGET=$(INCOMP_INCLUDES_TARGET)\n\
|
||||
INCOMP_INCLUDES_PYTHON=$(INCOMP_INCLUDES_PYTHON)\n\
|
||||
INCOMP_INCLUDES_JSONLI=$(INCOMP_INCLUDES_JSONLI)\n\
|
||||
INCOMP_INCLUDES_FNAMES=$(INCOMP_INCLUDES_FNAMES)\n\
|
||||
INCOMP_INCLUDES_PDFREP=$(INCOMP_INCLUDES_PDFREP)\n\
|
||||
INCOMP_INCLUDES_PDFEXT=$(INCOMP_INCLUDES_PDFEXT)\n\
|
||||
INCOMP_INCLUDES_TXTTAB=$(INCOMP_INCLUDES_TXTTAB)\n"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
@@ -106,40 +201,4 @@ rst: FluidInfoGenerator.py
|
||||
|
||||
|
||||
|
||||
############################################################
|
||||
# Generate and copy the include files for the documetation
|
||||
############################################################
|
||||
#
|
||||
INCOMP_INCLUDES_DIR:=$(CURDIR)/../dev/incompressible_liquids
|
||||
INCOMP_INCLUDES_PDF:=$(shell find $(INCOMP_INCLUDES_DIR) -name '*.pdf')
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY: incompressible_includes
|
||||
incompressible_includes: fluid_properties/all_pure.pdf fluid_properties/Incompressibles_Fluids.txt
|
||||
|
||||
fluid_properties/Incompressibles_Fluids.txt: $(addprefix $(PYGEN_DIR)/, Incompressibles_include_generator.py)
|
||||
cd $(PYGEN_DIR); \
|
||||
python Incompressibles_include_generator.py
|
||||
|
||||
fluid_properties/all_pure.pdf: $(addprefix $(PYGEN_DIR)/, all_incompressibles.py)
|
||||
cd $(PYGEN_DIR); \
|
||||
python all_incompressibles.py
|
||||
cp $(PYGEN_DIR)/all_pure.pdf fluid_properties/
|
||||
cp $(PYGEN_DIR)/all_solutions.pdf fluid_properties/
|
||||
|
||||
# general rules for the fit reports
|
||||
PYGEN_FILES=$(shell echo $(COOLPROPDIR)*.cpp)
|
||||
|
||||
# Make the .pdf report files
|
||||
$(PYGEN_DIR)/report/%.pdf : %.cpp
|
||||
$(CC) $(_CPPFLAGS) -c $(_INCLUDES) $< -o $@
|
||||
|
||||
|
||||
|
||||
.PHONY : check_incomp_flags
|
||||
check_incomp_flags:
|
||||
@printf "\nMakefile variables:\n\
|
||||
INCOMP_INCLUDES_DIR=$(INCOMP_INCLUDES_DIR)\n\
|
||||
INCOMP_INCLUDES_PDF=$(INCOMP_INCLUDES_PDF)\n"
|
||||
|
||||
@@ -3,17 +3,84 @@
|
||||
Incompressible Fluids
|
||||
=====================
|
||||
|
||||
here is the generated file with the table of incompressibles
|
||||
In CoolProp, the incompressible fluids are divided into four major groups.
|
||||
|
||||
.. include:: Incompressibles_Fluids.txt
|
||||
* :ref:`Pure fluids <Pure>`.
|
||||
* :ref:`Mass-based binary mixtures <MassMix>`.
|
||||
* :ref:`Mole-based binary mixtures <MoleMix>`.
|
||||
* :ref:`Volume-based binary mixtures <VoluMix>`.
|
||||
|
||||
The pure fluids and mass-based binary mixtures are by far the most common fluids
|
||||
in this library. While the pure fluids contain data for many different kinds of
|
||||
incompressible liquids, almost all of the binary mixtures are aqueous solutions.
|
||||
For these liquids, the concentration always refers to the added component ranging
|
||||
from 0.0 for pure water to 1.0 for no water at all. Please refer to the tables
|
||||
below to find the allowed minimum and maximum concentrations. Those are likely
|
||||
to be above 0.0 and below 1.0, respectively.
|
||||
|
||||
The first entry in the tables below is the fluid ID that can be used to call the
|
||||
fluid from the high-level interface. A single PDF page showing the fit quality is
|
||||
linked to that ID in case you would like to see a few more details about any
|
||||
specific fluid. To get an overview over all the fits, there are also combined
|
||||
documents with all the :download:`pure fluids <all_pure.pdf>` and all the
|
||||
:download:`aqueous solutions <all_solutions.pdf>`.
|
||||
|
||||
Incompressible fluids only allow These only allow for calls with
|
||||
temperature and pressure as input and provide only a subset of thermophysical properties, namely:
|
||||
density, heat capacity, internal energy, enthalpy, entropy, viscosity and thermal conductivity.
|
||||
Hence, the available output keys for the ``Props`` function are: "D", "C", "U", "H", "S", "V", "L",
|
||||
"Tmin", "Tmax" and "Psat". An internal iteration allows us to use enthalpy and pressure as inputs,
|
||||
but be aware of the reduced computational efficiency.
|
||||
|
||||
.. ipython::
|
||||
|
||||
In [1]: from CoolProp.CoolProp import PropsSI
|
||||
|
||||
#Density of HFE-7100 at 300 K and 1 atm.
|
||||
In [1]: PropsSI('D','T',300,'P',101325,'INCOMP::HFE')
|
||||
|
||||
.. _Pure:
|
||||
|
||||
Pure Fluids
|
||||
-----------
|
||||
.. include:: pure-fluids.txt
|
||||
|
||||
|
||||
|
||||
.. _MassMix:
|
||||
|
||||
Mass-based binary mixtures
|
||||
--------------------------
|
||||
|
||||
.. include:: mass-based-fluids.txt
|
||||
|
||||
|
||||
|
||||
.. _MoleMix:
|
||||
|
||||
Mole-based binary mixtures
|
||||
--------------------------
|
||||
|
||||
.. include:: mole-based-fluids.txt
|
||||
|
||||
|
||||
.. _VoluMix:
|
||||
|
||||
Volume-based binary mixtures
|
||||
----------------------------
|
||||
|
||||
.. include:: volume-based-fluids.txt
|
||||
|
||||
|
||||
|
||||
.. _FittingReports:
|
||||
|
||||
Fitting Reports
|
||||
=====================
|
||||
|
||||
here is a pdf file for all pure fluids :download:`pdf <all_pure.pdf>`
|
||||
|
||||
here is a pdf file for all solutions :download:`pdf <all_solutions.pdf>`
|
||||
|
||||
|
||||
|
||||
Incompressible Liquids
|
||||
|
||||
@@ -6,13 +6,13 @@ import sys
|
||||
|
||||
# Here we define the types. This is done to keep the definitions at one
|
||||
# central place instead of hiding them somewhere in the data.
|
||||
|
||||
|
||||
class IncompressibleData(object):
|
||||
"""
|
||||
The work horse of the incompressible classes.
|
||||
Implements both data structures and fitting
|
||||
"""
|
||||
The work horse of the incompressible classes.
|
||||
Implements both data structures and fitting
|
||||
procedures.
|
||||
"""
|
||||
"""
|
||||
INCOMPRESSIBLE_NOT_SET = 'notdefined'
|
||||
INCOMPRESSIBLE_POLYNOMIAL = 'polynomial'
|
||||
INCOMPRESSIBLE_EXPPOLYNOMIAL = 'exppolynomial'
|
||||
@@ -20,19 +20,19 @@ class IncompressibleData(object):
|
||||
INCOMPRESSIBLE_LOGEXPONENTIAL= 'logexponential'
|
||||
INCOMPRESSIBLE_POLYOFFSET = 'polyoffset'
|
||||
INCOMPRESSIBLE_CHEBYSHEV = 'chebyshev'
|
||||
|
||||
|
||||
SOURCE_DATA = 'data'
|
||||
SOURCE_EQUATION = 'equation'
|
||||
SOURCE_COEFFS = 'coefficients'
|
||||
SOURCE_NOT_SET = 'notdefined'
|
||||
|
||||
|
||||
maxLin = np.finfo(np.float64).max-1
|
||||
minLin = -maxLin
|
||||
|
||||
|
||||
maxLog = np.log(maxLin)
|
||||
minLog = -maxLog
|
||||
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self):
|
||||
self.source = self.SOURCE_NOT_SET
|
||||
self.type = self.INCOMPRESSIBLE_NOT_SET
|
||||
self.coeffs = None #np.zeros((4,4))
|
||||
@@ -41,34 +41,34 @@ class IncompressibleData(object):
|
||||
self.yData = None # In case you need a customised second data set (concentration?)
|
||||
self.sErr = None # Coefficient of determination
|
||||
self.DEBUG = False
|
||||
|
||||
|
||||
@staticmethod
|
||||
def baseFunc(x, y=0.0, xbase=0.0, ybase=0.0, eqnType=None, c=None):
|
||||
|
||||
if eqnType==None: raise ValueError("You did not provide data for eqnType.")
|
||||
if c==None: raise ValueError("You did not provide data for the coefficients.")
|
||||
|
||||
|
||||
if eqnType is None: raise ValueError("You did not provide data for eqnType.")
|
||||
if c is None: raise ValueError("You did not provide data for the coefficients.")
|
||||
|
||||
if eqnType==IncompressibleData.INCOMPRESSIBLE_POLYNOMIAL:
|
||||
return np.polynomial.polynomial.polyval2d(x-xbase, y-ybase, c)
|
||||
|
||||
|
||||
elif eqnType==IncompressibleData.INCOMPRESSIBLE_POLYOFFSET:
|
||||
#if y!=0.0: raise ValueError("This is 1D only, use x not y.")
|
||||
return IncompressibleData.basePolyOffset(c, x) # offset included in coeffs
|
||||
|
||||
|
||||
elif eqnType==IncompressibleData.INCOMPRESSIBLE_EXPONENTIAL:
|
||||
#if y!=0.0: raise ValueError("This is 1D only, use x not y.")
|
||||
return IncompressibleData.baseExponential(c, x)
|
||||
|
||||
|
||||
elif eqnType==IncompressibleData.INCOMPRESSIBLE_LOGEXPONENTIAL:
|
||||
#if y!=0.0: raise ValueError("This is 1D only, use x not y.")
|
||||
return IncompressibleData.baseLogexponential(c, x)
|
||||
|
||||
|
||||
elif eqnType==IncompressibleData.INCOMPRESSIBLE_EXPPOLYNOMIAL:
|
||||
return np.exp(np.polynomial.polynomial.polyval2d(x-xbase, y-ybase, c))
|
||||
|
||||
|
||||
else:
|
||||
raise ValueError("Unknown function: {0}.".format(eqnType))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def baseExponential(co, x):
|
||||
r,c,coeffs = IncompressibleFitter.shapeArray(co)
|
||||
@@ -76,7 +76,7 @@ class IncompressibleData(object):
|
||||
raise ValueError("You have to provide a 3,1 matrix of coefficients, not ({0},{1}).".format(r,c))
|
||||
coeffs_tmp = np.array(coeffs.flat)
|
||||
return np.exp(np.clip( (coeffs_tmp[0]/ ( x+coeffs_tmp[1] ) - coeffs_tmp[2]),IncompressibleData.minLog,IncompressibleData.maxLog))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def baseLogexponential(co, x):
|
||||
r,c,coeffs = IncompressibleFitter.shapeArray(co)
|
||||
@@ -93,36 +93,36 @@ class IncompressibleData(object):
|
||||
offset = coeffs[0][0]
|
||||
coeffs = np.array(coeffs.flat)[1:]
|
||||
return np.polynomial.polynomial.polyval(x-offset, coeffs)
|
||||
|
||||
|
||||
|
||||
|
||||
### Base functions that handle the custom data type, just a place holder to show the structure.
|
||||
def baseFunction(self, x, y=0.0, xbase=0.0, ybase=0.0, c=None):
|
||||
if c==None: c = self.coeffs
|
||||
if c is None: c = self.coeffs
|
||||
return self.baseFunc(x, y, xbase, ybase, self.type, c)
|
||||
|
||||
|
||||
def fitCoeffs(self, xbase, ybase, x=None, y=None):
|
||||
|
||||
if (x!=None and self.xData!=None and not IncompressibleFitter.allClose(x, self.xData)) \
|
||||
or (x==None and self.xData==None): raise ValueError("I do not know which x-value you would like to use. Define either x or self.xData.")
|
||||
if (y!=None and self.yData!=None and not IncompressibleFitter.allClose(y, self.yData)) \
|
||||
or (y==None and self.yData==None): raise ValueError("I do not know which y-value you would like to use. Define either y or self.yData.")
|
||||
|
||||
if x==None and self.xData!=None: x=self.xData
|
||||
if y==None and self.yData!=None: y=self.yData
|
||||
|
||||
|
||||
if (not x is None and not self.xData is None and not IncompressibleFitter.allClose(x, self.xData)) \
|
||||
or (x is None and self.xData is None): raise ValueError("I do not know which x-value you would like to use. Define either x or self.xData.")
|
||||
if (not y is None and not self.yData is None and not IncompressibleFitter.allClose(y, self.yData)) \
|
||||
or (y is None and self.yData is None): raise ValueError("I do not know which y-value you would like to use. Define either y or self.yData.")
|
||||
|
||||
if x is None and not self.xData is None: x=self.xData
|
||||
if y is None and not self.yData is None: y=self.yData
|
||||
|
||||
#res = None
|
||||
#r2 = None
|
||||
|
||||
|
||||
res,sErr = IncompressibleFitter.fitter(x=x, y=y, z=self.data, \
|
||||
xbase=xbase, ybase=ybase, \
|
||||
eqnType=self.type, \
|
||||
coeffs=self.coeffs, DEBUG=self.DEBUG)
|
||||
|
||||
|
||||
bestCoeffs = np.copy(res)
|
||||
bestType = self.type
|
||||
bestsErr = np.copy(sErr)
|
||||
bestRMS = np.sqrt(np.square(bestsErr).mean()).sum()
|
||||
|
||||
|
||||
count = 0
|
||||
while bestRMS>0.03 and count<2:
|
||||
#if self.DEBUG: print("Poor solution found, trying once more with more coefficients.")
|
||||
@@ -134,7 +134,7 @@ class IncompressibleData(object):
|
||||
xbase=xbase, ybase=ybase, \
|
||||
eqnType=self.type, \
|
||||
coeffs=self.coeffs, DEBUG=self.DEBUG)
|
||||
|
||||
|
||||
elif self.type==IncompressibleData.INCOMPRESSIBLE_LOGEXPONENTIAL and self.data.size>10:
|
||||
if self.DEBUG: print("Poor solution found with log exponential, trying once more with exponential polynomial.")
|
||||
self.type=IncompressibleData.INCOMPRESSIBLE_EXPPOLYNOMIAL
|
||||
@@ -143,7 +143,7 @@ class IncompressibleData(object):
|
||||
xbase=xbase, ybase=ybase, \
|
||||
eqnType=self.type, \
|
||||
coeffs=self.coeffs, DEBUG=self.DEBUG)
|
||||
|
||||
|
||||
# elif self.type==IncompressibleData.INCOMPRESSIBLE_EXPPOLYNOMIAL:
|
||||
# if self.DEBUG: print("Poor solution found with exponential polynomial, trying once more with normal polynomial.")
|
||||
# self.type=IncompressibleData.INCOMPRESSIBLE_POLYNOMIAL
|
||||
@@ -159,53 +159,53 @@ class IncompressibleData(object):
|
||||
bestType = self.type
|
||||
bestsErr = np.copy(sErr)
|
||||
bestRMS = RMS
|
||||
|
||||
|
||||
count += 1
|
||||
|
||||
if bestCoeffs==None:
|
||||
|
||||
if bestCoeffs is None:
|
||||
if self.DEBUG: print("There was a fitting error, no solution found.")
|
||||
elif IncompressibleFitter.allClose(bestCoeffs, self.coeffs):
|
||||
if self.DEBUG: print("Coefficients did not change.")
|
||||
else:
|
||||
if self.DEBUG: print("Best fit for: {0}".format(bestType))
|
||||
self.coeffs = bestCoeffs
|
||||
self.type = bestType
|
||||
self.type = bestType
|
||||
self.sErr = bestsErr
|
||||
|
||||
|
||||
#if self.DEBUG: print("Fitting statistics:")
|
||||
#SSE = np.square(self.sErr).sum() # Sum of squares due to error
|
||||
#SST = ((zData-zData.mean())**2).sum()
|
||||
#R2 = 1-(ssErr/ssTot )
|
||||
|
||||
|
||||
|
||||
def setxData(self, xData):
|
||||
if self.xData==None:
|
||||
if self.xData is None:
|
||||
self.xData = xData
|
||||
else:
|
||||
if self.DEBUG: print("Cannot update xData, value is set already.")
|
||||
|
||||
|
||||
else:
|
||||
if self.DEBUG: print("Cannot update xData, value is set already.")
|
||||
|
||||
|
||||
def setyData(self, yData):
|
||||
if self.yData==None:
|
||||
if self.yData is None:
|
||||
self.yData = yData
|
||||
else:
|
||||
if self.DEBUG: print("Cannot update yData, value is set already.")
|
||||
|
||||
else:
|
||||
if self.DEBUG: print("Cannot update yData, value is set already.")
|
||||
|
||||
def setxyData(self, xData, yData):
|
||||
self.setxData(xData)
|
||||
self.setyData(yData)
|
||||
|
||||
|
||||
|
||||
|
||||
def toJSON(self):
|
||||
j = {}
|
||||
try:
|
||||
j['coeffs'] = self.coeffs.tolist()
|
||||
except:
|
||||
j['coeffs'] = 'null'
|
||||
|
||||
|
||||
j['type'] = self.type
|
||||
return j
|
||||
|
||||
|
||||
def fromJSON(self, j):
|
||||
try:
|
||||
self.coeffs = np.array(j['coeffs'])
|
||||
@@ -213,22 +213,22 @@ class IncompressibleData(object):
|
||||
except:
|
||||
self.coeffs = None
|
||||
self.type = IncompressibleData.INCOMPRESSIBLE_NOT_SET
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
class IncompressibleFitter(object):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def allClose(a,b):
|
||||
if np.array(a).shape==np.array(b).shape:
|
||||
return np.allclose(a, b)
|
||||
else: return False
|
||||
|
||||
|
||||
@staticmethod
|
||||
def shapeArray(array, axs=0):
|
||||
"""
|
||||
A function that promotes a 1D array to 2D and
|
||||
A function that promotes a 1D array to 2D and
|
||||
also returns the columns and rows.
|
||||
1D vectors are interpreted as column vectors.
|
||||
"""
|
||||
@@ -254,14 +254,14 @@ class IncompressibleFitter(object):
|
||||
print(array)
|
||||
raise ValueError("You have to provide a 1D-vector or a 2D-matrix.")
|
||||
return (r,c,np.reshape(array,(r,c)))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def fitter(x=None, y=None, z=None, \
|
||||
xbase=0.0, ybase=0.0, \
|
||||
eqnType=None, \
|
||||
coeffs=None, DEBUG=False):
|
||||
""" The entry point to the fitting routines
|
||||
|
||||
|
||||
:param x : a 1D array in x direction or 2D with one column, most likely temperature
|
||||
:param y : a 1D array in y direction or 2D with one row, most likely cocentration
|
||||
:param z : a 2D array of data, rows = len(x[:,0]) and cols = len(y[0])
|
||||
@@ -270,46 +270,46 @@ class IncompressibleFitter(object):
|
||||
:param eqnType : an instance of IncompressibleData.INCOMPRESSIBLE_ ...
|
||||
:param coeffs : the initial guess and shape (!) for the desired coefficients, can be zeros
|
||||
:param DEBUG : message to display
|
||||
|
||||
:returns : None if failed or coeffs filled with the right values
|
||||
|
||||
|
||||
|
||||
:returns : None if failed or coeffs filled with the right values
|
||||
|
||||
|
||||
A function that selects the correct equations and
|
||||
fits coefficients. Some functions require a start
|
||||
guess for the coefficients to work properly.
|
||||
"""
|
||||
|
||||
if x==None: raise ValueError("You did not provide data for the x-values.")
|
||||
if y==None: raise ValueError("You did not provide data for the y-values.")
|
||||
if z==None: raise ValueError("You did not provide data for the z-values.")
|
||||
if xbase==None: raise ValueError("You did not provide data for xbase.")
|
||||
if ybase==None: raise ValueError("You did not provide data for ybase.")
|
||||
if eqnType==None: raise ValueError("You did not provide data for eqnType.")
|
||||
if coeffs==None: raise ValueError("You did not provide data for the coefficients.")
|
||||
if DEBUG==None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
|
||||
if x is None: raise ValueError("You did not provide data for the x-values.")
|
||||
if y is None: raise ValueError("You did not provide data for the y-values.")
|
||||
if z is None: raise ValueError("You did not provide data for the z-values.")
|
||||
if xbase is None: raise ValueError("You did not provide data for xbase.")
|
||||
if ybase is None: raise ValueError("You did not provide data for ybase.")
|
||||
if eqnType is None: raise ValueError("You did not provide data for eqnType.")
|
||||
if coeffs is None: raise ValueError("You did not provide data for the coefficients.")
|
||||
if DEBUG is None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
zr,zc,_ = IncompressibleFitter.shapeArray(z)
|
||||
xr,xc,x = IncompressibleFitter.shapeArray(x)
|
||||
yr,yc,y = IncompressibleFitter.shapeArray(y, axs=1)
|
||||
|
||||
|
||||
if DEBUG: print("Data : ({0},{1})".format(zr,zc))
|
||||
if DEBUG: print("x-axis : ({0},{1})".format(xr,xc))
|
||||
if DEBUG: print("y-axis : ({0},{1})".format(yr,yc))
|
||||
|
||||
if zr==1 and zc==1: #
|
||||
|
||||
if zr==1 and zc==1: #
|
||||
if DEBUG: print("Data no set, we cannot fit the coefficients")
|
||||
return None,None
|
||||
|
||||
|
||||
if (xc!=1): raise ValueError("The first input has to be a 2D array with one column.")
|
||||
if (yr!=1): raise ValueError("The second input has to be a 2D array with one row.")
|
||||
if (xr!=zr): raise ValueError("First independent vector and result vector have to have the same number of rows, {0} is not {1}.".format(xr,zr))
|
||||
if (yc!=zc): raise ValueError("Second independent vector and result vector have to have the same number of columns, {0} is not {1}.".format(yc,zc))
|
||||
|
||||
|
||||
if DEBUG: print("Coefficients before fitting: \n{0}".format(coeffs))
|
||||
|
||||
|
||||
# Polynomial fitting works for both 1D and 2D functions
|
||||
if eqnType==IncompressibleData.INCOMPRESSIBLE_POLYNOMIAL or eqnType==IncompressibleData.INCOMPRESSIBLE_EXPPOLYNOMIAL:
|
||||
|
||||
|
||||
cr,cc,_ = IncompressibleFitter.shapeArray(coeffs)
|
||||
if DEBUG: print("Coefficients: ({0},{1})".format(cr,cc))
|
||||
if (xr==1 and xc==1 and cr>1):
|
||||
@@ -321,16 +321,16 @@ class IncompressibleFitter(object):
|
||||
coeffs = coeffs.T[0]
|
||||
coeffs = coeffs.reshape((cr,1))
|
||||
cr,cc,_ = IncompressibleFitter.shapeArray(coeffs)
|
||||
|
||||
|
||||
if DEBUG: print("polynomial detected, fitting {0}".format(eqnType))
|
||||
if cr==1 and cc==1:
|
||||
if cr==1 and cc==1:
|
||||
if DEBUG: print("No coefficients left to fit, aborting procedure.")
|
||||
coeffs = np.array([[0.0]])
|
||||
return coeffs, None
|
||||
if (xr<cr):
|
||||
return coeffs, None
|
||||
if (xr<cr):
|
||||
if DEBUG: print("Less data points than coefficients in first dimension ({0} < {1}), reducing coefficient matrix.".format(xr,cr))
|
||||
coeffs = coeffs[:xr,:]
|
||||
if (yc<cc):
|
||||
if (yc<cc):
|
||||
if DEBUG: print("Less data points than coefficients in second dimension ({0} < {1}), reducing coefficient matrix.".format(yc,cc))
|
||||
coeffs = coeffs[:,:yc]
|
||||
cr,cc,_ = IncompressibleFitter.shapeArray(coeffs)
|
||||
@@ -345,18 +345,18 @@ class IncompressibleFitter(object):
|
||||
if DEBUG: print("Sum of squared errors: {0}".format(np.square(sErr).sum()))
|
||||
if DEBUG: print("Root mean squared errors: {0}".format(np.sqrt(np.square(sErr).mean()).sum()))
|
||||
return coeffs,sErr
|
||||
|
||||
|
||||
|
||||
|
||||
# Select if 1D or 2D fitting
|
||||
if yc==1 or xr==1: # 1D fitting, only one input
|
||||
if DEBUG: print("1D function detected.")
|
||||
if yc==1:
|
||||
if yc==1:
|
||||
if DEBUG: print("Fitting {0} in x-direction.".format(eqnType))
|
||||
coeffs,sErr = IncompressibleFitter.getCoeffsIterative1D(x, z, eqnType=eqnType, coeffs=coeffs, DEBUG=DEBUG)
|
||||
elif xr==1:
|
||||
elif xr==1:
|
||||
if DEBUG: print("Fitting {0} in y-direction.".format(eqnType))
|
||||
coeffs,sErr = IncompressibleFitter.getCoeffsIterative1D(y, z, eqnType=eqnType, coeffs=coeffs, DEBUG=DEBUG)
|
||||
else: raise ValueError("Unknown error in matrix shapes.")
|
||||
else: raise ValueError("Unknown error in matrix shapes.")
|
||||
if DEBUG: print("Coefficients after fitting: \n{0}".format(coeffs))
|
||||
if DEBUG: print("Standard deviation: {0}".format(np.nanstd(sErr)))
|
||||
if DEBUG: print("Sum of squared errors: {0}".format(np.square(sErr).sum()))
|
||||
@@ -365,13 +365,13 @@ class IncompressibleFitter(object):
|
||||
|
||||
elif yc>1: # 2D fitting
|
||||
raise ValueError("There are no other 2D fitting functions than polynomials, cannot use {0}.".format(eqnType))
|
||||
|
||||
else:
|
||||
raise ValueError("Unknown function.")
|
||||
|
||||
|
||||
else:
|
||||
raise ValueError("Unknown function.")
|
||||
|
||||
|
||||
# def getCoeffs1d(self, x, z, order):
|
||||
# if (len(x)<order+1):
|
||||
# if (len(x)<order+1):
|
||||
# raise ValueError("You have only {0} elements and try to fit {1} coefficients, please reduce the order.".format(len(x),order+1))
|
||||
# A = np.vander(x,order+1)[:,::-1]
|
||||
# #Anew = np.dot(A.T,A)
|
||||
@@ -379,17 +379,17 @@ class IncompressibleFitter(object):
|
||||
# #coeffs = np.linalg.solve(Anew, znew)
|
||||
# coeffs, resids, rank, singulars = np.linalg.lstsq(A, z)
|
||||
# return np.reshape(coeffs, (len(x),1))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def getCoeffs2d(x_in, y_in, z_in, x_order, y_order, DEBUG=False):
|
||||
|
||||
if x_in==None: raise ValueError("You did not provide data for the x-values.")
|
||||
if y_in==None: raise ValueError("You did not provide data for the y-values.")
|
||||
if z_in==None: raise ValueError("You did not provide data for the z-values.")
|
||||
if x_order==None: raise ValueError("You did not provide data for x_order.")
|
||||
if y_order==None: raise ValueError("You did not provide data for y_order.")
|
||||
if DEBUG==None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
|
||||
if x_in is None: raise ValueError("You did not provide data for the x-values.")
|
||||
if y_in is None: raise ValueError("You did not provide data for the y-values.")
|
||||
if z_in is None: raise ValueError("You did not provide data for the z-values.")
|
||||
if x_order is None: raise ValueError("You did not provide data for x_order.")
|
||||
if y_order is None: raise ValueError("You did not provide data for y_order.")
|
||||
if DEBUG is None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
x_order += 1
|
||||
y_order += 1
|
||||
#To avoid overfitting, we only use the upper left triangle of the coefficient matrix
|
||||
@@ -397,105 +397,105 @@ class IncompressibleFitter(object):
|
||||
y_exp = range(y_order)
|
||||
limit = max(x_order,y_order)
|
||||
xy_exp = []
|
||||
# Construct the upper left triangle of coefficients
|
||||
# Construct the upper left triangle of coefficients
|
||||
for i in x_exp:
|
||||
for j in y_exp:
|
||||
if(i+j<limit): xy_exp.append((i,j))
|
||||
|
||||
# Construct input pairs
|
||||
|
||||
# Construct input pairs
|
||||
xx, yy = np.meshgrid(x_in,y_in,indexing='ij')
|
||||
xx = np.array(xx.flat)
|
||||
yy = np.array(yy.flat)
|
||||
zz = np.array(z_in.flat)
|
||||
|
||||
|
||||
# TODO: Check for rows with only nan values
|
||||
x_num = len(x_in)
|
||||
y_num = len(y_in)
|
||||
|
||||
y_num = len(y_in)
|
||||
|
||||
cols = len(xy_exp)
|
||||
eqns = x_num * y_num
|
||||
#if (eqns<cols):
|
||||
# raise ValueError("You have only {0} equations and try to fit {1} coefficients, please reduce the order.".format(eqns,cols))
|
||||
# raise ValueError("You have only {0} equations and try to fit {1} coefficients, please reduce the order.".format(eqns,cols))
|
||||
if (x_num<x_order):
|
||||
raise ValueError("You have only {0} x-entries and try to fit {1} x-coefficients, please reduce the x_order.".format(x_num,x_order))
|
||||
if (y_num<y_order):
|
||||
raise ValueError("You have only {0} y-entries and try to fit {1} y-coefficients, please reduce the y_order.".format(y_num,y_order))
|
||||
|
||||
|
||||
# Build the functional matrix
|
||||
A = np.zeros((eqns,cols))
|
||||
for i in range(eqns): # row loop
|
||||
for j, (xj,yj) in enumerate(xy_exp): # makes columns
|
||||
A[i][j] = xx[i]**xj * yy[i]**yj
|
||||
|
||||
|
||||
# Remove np.nan elements
|
||||
mask = np.isfinite(zz)
|
||||
A = A[mask]
|
||||
xx = xx[mask]
|
||||
yy = yy[mask]
|
||||
zz = zz[mask]
|
||||
|
||||
|
||||
if (len(A) < cols):
|
||||
raise ValueError("Your matrix has only {0} valid rows and you try to fit {1} coefficients, please reduce the order.".format(len(A),cols))
|
||||
|
||||
|
||||
coeffs, resids, rank, singulars = np.linalg.lstsq(A, zz)
|
||||
if DEBUG: print("Linear algebra solver returned:")
|
||||
if DEBUG: print(coeffs)
|
||||
if DEBUG: print(resids)
|
||||
if DEBUG: print(rank)
|
||||
if DEBUG: print(singulars)
|
||||
|
||||
|
||||
#if resids.size>0:
|
||||
# r2 = 1 - resids / (zz.size * zz.var())
|
||||
#else:
|
||||
# r2 = 0
|
||||
#print("\n r2 2d: ",r2.shape,r2,"\n")
|
||||
|
||||
|
||||
#Rearrange coefficients to a matrix shape
|
||||
C = np.zeros((x_order,y_order))
|
||||
for i, (xi,yi) in enumerate(xy_exp): # makes columns
|
||||
C[xi][yi] = coeffs[i]
|
||||
|
||||
|
||||
sErr = zz - np.polynomial.polynomial.polyval2d(xx, yy, C)
|
||||
return C, sErr
|
||||
|
||||
|
||||
@staticmethod
|
||||
def getCoeffsIterative1D(x_in, z_in, eqnType, coeffs, DEBUG=False):
|
||||
|
||||
if x_in==None: raise ValueError("You did not provide data for the x-values.")
|
||||
if z_in==None: raise ValueError("You did not provide data for the z-values.")
|
||||
if eqnType==None: raise ValueError("You did not provide data for eqnType.")
|
||||
if coeffs==None: raise ValueError("You did not provide data for the coefficients.")
|
||||
if DEBUG==None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
sErr = None
|
||||
|
||||
|
||||
if x_in is None: raise ValueError("You did not provide data for the x-values.")
|
||||
if z_in is None: raise ValueError("You did not provide data for the z-values.")
|
||||
if eqnType is None: raise ValueError("You did not provide data for eqnType.")
|
||||
if coeffs is None: raise ValueError("You did not provide data for the coefficients.")
|
||||
if DEBUG is None: raise ValueError("You did not provide data for DEBUG.")
|
||||
|
||||
sErr = None
|
||||
|
||||
#fit = "Powell" # use Powell's algorithm
|
||||
#fit = "BFGS" # use Broyden-Fletcher-Goldfarb-Shanno
|
||||
#fit = "LMA" # use the Levenberg-Marquardt algorithm from curve_fit
|
||||
#fit = "LMA" # use the Levenberg-Marquardt algorithm from curve_fit
|
||||
fit = ["LMA","Powell","BFGS"] # First try LMA, use others as fall-back
|
||||
|
||||
|
||||
# make sure that we use other routines for polynomials
|
||||
if (eqnType==IncompressibleData.INCOMPRESSIBLE_POLYNOMIAL) or \
|
||||
(eqnType==IncompressibleData.INCOMPRESSIBLE_EXPPOLYNOMIAL) :
|
||||
raise ValueError("Please use the specific polynomial functions, they are much better.")
|
||||
|
||||
|
||||
expLog = False
|
||||
# Fitting the logarithm of z_in?
|
||||
if (eqnType==IncompressibleData.INCOMPRESSIBLE_EXPONENTIAL or eqnType==IncompressibleData.INCOMPRESSIBLE_LOGEXPONENTIAL):
|
||||
expLog = True
|
||||
|
||||
|
||||
xData = np.array(x_in.flat)
|
||||
if expLog: zData = np.log(z_in.flat)
|
||||
else: zData = np.array(z_in.flat)
|
||||
|
||||
|
||||
# Remove np.nan elements
|
||||
mask = np.isfinite(zData)
|
||||
xData = xData[mask]
|
||||
zData = zData[mask]
|
||||
|
||||
# The residual function
|
||||
|
||||
# The residual function
|
||||
def fun(coefficients,xArray,yArray):
|
||||
"""
|
||||
"""
|
||||
This function takes the coefficient array and
|
||||
x and y data. It evaluates the function and returns
|
||||
the sum of the squared residuals if yArray is not
|
||||
@@ -504,24 +504,24 @@ class IncompressibleFitter(object):
|
||||
# No offset and no Tbase etc for 1D functions!
|
||||
calculated = IncompressibleData.baseFunc(xArray, y=0.0, xbase=0.0, ybase=0.0, eqnType=eqnType, c=coefficients)
|
||||
if expLog: calculated = np.log(calculated)
|
||||
if yArray==None: return calculated
|
||||
if yArray is None: return calculated
|
||||
data = yArray
|
||||
res = np.sum(np.square(calculated-data))
|
||||
res = np.sum(np.square(calculated-data))
|
||||
return res
|
||||
|
||||
|
||||
# Loop through the list of algorithms with basic settings to keep track of our efforts
|
||||
success = False
|
||||
counter = 0
|
||||
tolerance = 1e-16
|
||||
while (not success):
|
||||
algorithm = fit[counter]
|
||||
#fit = "LMA" # use the Levenberg-Marquardt algorithm from curve_fit
|
||||
if algorithm=="LMA":
|
||||
|
||||
#fit = "LMA" # use the Levenberg-Marquardt algorithm from curve_fit
|
||||
if algorithm=="LMA":
|
||||
|
||||
def func(xVector, *coefficients):
|
||||
return fun(np.array(coefficients), xVector, None)
|
||||
#return self.baseFunction(xVector, 0.0, 0.0, 0.0, np.array(coefficients)) #np.array([self._PropsFit(coefficients,xName,T=Ti) for Ti in T])
|
||||
|
||||
|
||||
try:
|
||||
#print func(xData, coeffs_start)
|
||||
# Do the actual fitting
|
||||
@@ -543,19 +543,19 @@ class IncompressibleFitter(object):
|
||||
else:
|
||||
if DEBUG: print("Fit failed for {0}.".format(algorithm))
|
||||
if DEBUG: sys.stdout.flush()
|
||||
success = False
|
||||
|
||||
success = False
|
||||
|
||||
except RuntimeError as e:
|
||||
if DEBUG: print("Exception using "+algorithm+": "+str(e))
|
||||
if DEBUG: sys.stdout.flush()
|
||||
success = False
|
||||
|
||||
|
||||
#fit = "MIN" # use a home-made minimisation with Powell and Broyden-Fletcher-Goldfarb-Shanno
|
||||
elif algorithm=="Powell" or algorithm=="BFGS":
|
||||
|
||||
|
||||
arguments = (xData,zData)
|
||||
#options = {'maxiter': 1e2, 'maxfev': 1e5}
|
||||
|
||||
|
||||
try:
|
||||
res = minimize(fun, coeffs, method=algorithm, args=arguments, tol=tolerance)
|
||||
if res.success:
|
||||
@@ -566,7 +566,7 @@ class IncompressibleFitter(object):
|
||||
#ssErr = (res['fvec']**2).sum()
|
||||
#ssTot = ((zData-zData.mean())**2).sum()
|
||||
#r2 = 1-(ssErr/ssTot )
|
||||
#print("\n r2 : ",r2.shape,r2,algorithm,"\n")
|
||||
#print("\n r2 : ",r2.shape,r2,algorithm,"\n")
|
||||
return res.x,sErr
|
||||
else:
|
||||
if DEBUG: print("Fit failed for {0}.".format(algorithm))
|
||||
@@ -580,7 +580,7 @@ class IncompressibleFitter(object):
|
||||
# Something went wrong, probably a typo in the algorithm selector
|
||||
else:
|
||||
raise (ValueError("Error: You used an unknown fit method."))
|
||||
|
||||
|
||||
if counter<len(fit)-1:
|
||||
#print("Fit did not succeed with {0}, reducing tolerance to {1}.".format(algorithm,tol))
|
||||
success = False
|
||||
@@ -589,14 +589,13 @@ class IncompressibleFitter(object):
|
||||
tolerance *= 1e2
|
||||
if DEBUG: print("Fit did not succeed, reducing tolerance to {0}.".format(tolerance))
|
||||
success = False
|
||||
counter = 0
|
||||
counter = 0
|
||||
else:
|
||||
if DEBUG: print("--------------------------------------------------------------")
|
||||
if DEBUG: print("Fit failed for {0}. ".format(fit))
|
||||
if DEBUG: print("--------------------------------------------------------------")
|
||||
return coeffs,1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ class SolutionData(object):
|
||||
|
||||
def rho (self, T, p=0.0, x=0.0, c=None):
|
||||
if not self.checkTPX(T, p, x): return np.NAN
|
||||
if c==None:
|
||||
if c is None:
|
||||
c=self.density.coeffs
|
||||
if self.density.type==self.density.INCOMPRESSIBLE_POLYNOMIAL:
|
||||
return np.polynomial.polynomial.polyval2d(T-self.Tbase, x-self.xbase, c)
|
||||
@@ -154,7 +154,7 @@ class SolutionData(object):
|
||||
|
||||
def c (self, T, p=0.0, x=0.0, c=None):
|
||||
if not self.checkTPX(T, p, x): return np.NAN
|
||||
if c==None:
|
||||
if c is None:
|
||||
c = self.specific_heat.coeffs
|
||||
if self.specific_heat.type==self.specific_heat.INCOMPRESSIBLE_POLYNOMIAL:
|
||||
return np.polynomial.polynomial.polyval2d(T-self.Tbase, x-self.xbase, c)
|
||||
@@ -168,7 +168,7 @@ class SolutionData(object):
|
||||
|
||||
def u (self, T, p=0.0, x=0.0, c=None):
|
||||
if not self.checkTPX(T, p, x): return np.NAN
|
||||
if c==None:
|
||||
if c is None:
|
||||
c = self.specific_heat.coeffs
|
||||
if self.specific_heat.type==self.specific_heat.INCOMPRESSIBLE_POLYNOMIAL:
|
||||
c_tmp = np.polynomial.polynomial.polyint(c)
|
||||
@@ -192,7 +192,7 @@ class SolutionData(object):
|
||||
return self.saturation_pressure.baseFunction(T, x, self.Tbase, self.xbase, c=c)
|
||||
|
||||
def Tfreeze(self, T, p=0.0, x=0.0, c=None):
|
||||
if c==None:
|
||||
if c is None:
|
||||
c = self.T_freeze.coeffs
|
||||
|
||||
if self.T_freeze.type==self.T_freeze.INCOMPRESSIBLE_POLYNOMIAL:
|
||||
@@ -327,7 +327,7 @@ class DigitalData(SolutionData):
|
||||
z = None
|
||||
|
||||
# First we try to read the file
|
||||
if (dataID!=None and os.path.isfile(self.getFile(dataID))): # File found
|
||||
if (not dataID is None and os.path.isfile(self.getFile(dataID))): # File found
|
||||
fileArray = self.getFromFile(dataID)
|
||||
x = np.copy(fileArray[1:,0 ])
|
||||
y = np.copy(fileArray[0 ,1:])
|
||||
@@ -377,7 +377,7 @@ class DigitalData(SolutionData):
|
||||
z = np.zeros( (len(x)+1,len(y)+1) )
|
||||
r,c = z.shape
|
||||
|
||||
if func==None: raise ValueError("Need a function to update the data file.")
|
||||
if func is None: raise ValueError("Need a function to update the data file.")
|
||||
|
||||
for i in range(r-1):
|
||||
for j in range(c-1):
|
||||
@@ -386,7 +386,7 @@ class DigitalData(SolutionData):
|
||||
z[1:,0] = x
|
||||
z[0,1:] = y
|
||||
|
||||
if dataID!=None:
|
||||
if not dataID is None:
|
||||
self.writeToFile(dataID, z)
|
||||
else:
|
||||
if DEBUG: print("Not updating data file, dataID is missing.")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@ from __future__ import division, absolute_import, print_function
|
||||
import os
|
||||
from CPIncomp import getCoefficientFluids, getDigitalFluids, getMelinderFluids,\
|
||||
getPureFluids, getSecCoolFluids
|
||||
from CPIncomp.DataObjects import SolutionData
|
||||
from CPIncomp.BaseObjects import IncompressibleData
|
||||
|
||||
# See http://stackoverflow.com/questions/11347505/what-are-some-approaches-to-outputting-a-python-data-structure-to-restructuredte
|
||||
def make_table(grid):
|
||||
@@ -36,6 +38,7 @@ def table_div(max_cols, header_flag=1):
|
||||
|
||||
|
||||
def writeTextToFile(path,text):
|
||||
print("Writing to file: {0}".format(path))
|
||||
f = open(path, "w")
|
||||
f.write(text)
|
||||
f.close()
|
||||
@@ -56,9 +59,12 @@ def normalize_row(row, max_cols):
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
FLUID_INFO_FOLDER=os.path.join("..","..","Web","fluid_properties")
|
||||
FLUID_INFO_FOLDER=os.path.abspath(os.path.join("..","..","Web","fluid_properties"))
|
||||
|
||||
FLUID_INFO_INCOMP_LIST=os.path.join(FLUID_INFO_FOLDER,"Incompressibles_Fluids.txt")
|
||||
FLUID_INFO_MASS_LIST=os.path.join(FLUID_INFO_FOLDER,"mass-based-fluids.txt")
|
||||
FLUID_INFO_MOLE_LIST=os.path.join(FLUID_INFO_FOLDER,"mole-based-fluids.txt")
|
||||
FLUID_INFO_VOLU_LIST=os.path.join(FLUID_INFO_FOLDER,"volume-based-fluids.txt")
|
||||
FLUID_INFO_PURE_LIST=os.path.join(FLUID_INFO_FOLDER,"pure-fluids.txt")
|
||||
|
||||
|
||||
|
||||
@@ -75,11 +81,60 @@ if __name__ == '__main__':
|
||||
allObjs += pureFObjs[:]
|
||||
allObjs += secCoObjs[:]
|
||||
|
||||
testTable = []
|
||||
testTable.append(['Name', 'Description', 'Reference']) # Headline
|
||||
# Parse the objects and make lists according to the data sources
|
||||
dataSourceObjs = []
|
||||
equaSourceObjs = []
|
||||
coefSourceObjs = []
|
||||
unknSourceObjs = []
|
||||
|
||||
# Make other lists for pure solution fluids
|
||||
massBasedObjs = []
|
||||
moleBasedObjs = []
|
||||
voluBasedObjs = []
|
||||
pureBasedObjs = []
|
||||
unknBasedObjs = []
|
||||
|
||||
for fluid in allObjs:
|
||||
testTable.append([fluid.name, fluid.description, fluid.reference])
|
||||
|
||||
if fluid.density.source==IncompressibleData.SOURCE_DATA:
|
||||
dataSourceObjs += [fluid]
|
||||
elif fluid.density.source==IncompressibleData.SOURCE_EQUATION:
|
||||
equaSourceObjs += [fluid]
|
||||
elif fluid.density.source==IncompressibleData.SOURCE_COEFFS:
|
||||
coefSourceObjs += [fluid]
|
||||
else:
|
||||
unknSourceObjs += [fluid]
|
||||
|
||||
if fluid.xid==SolutionData.ifrac_mass:
|
||||
massBasedObjs += [fluid]
|
||||
elif fluid.xid==SolutionData.ifrac_mole:
|
||||
moleBasedObjs += [fluid]
|
||||
elif fluid.xid==SolutionData.ifrac_volume:
|
||||
voluBasedObjs += [fluid]
|
||||
elif fluid.xid==SolutionData.ifrac_pure:
|
||||
pureBasedObjs += [fluid]
|
||||
else:
|
||||
unknBasedObjs += [fluid]
|
||||
|
||||
# After all the list got populated, we can process the entries
|
||||
# and generate some tables
|
||||
|
||||
header = ['Name', 'Description', 'Reference']
|
||||
|
||||
#
|
||||
objLists = [pureBasedObjs,massBasedObjs,moleBasedObjs,voluBasedObjs]
|
||||
filLists = [FLUID_INFO_PURE_LIST,FLUID_INFO_MASS_LIST]
|
||||
filLists +=[FLUID_INFO_MOLE_LIST,FLUID_INFO_VOLU_LIST]
|
||||
|
||||
for i in range(len(objLists)):
|
||||
testTable = []
|
||||
testTable.append(header) # Headline
|
||||
|
||||
for fluid in objLists[i]:
|
||||
testTable.append([fluid.name, fluid.description, fluid.reference])
|
||||
|
||||
writeTableToFile(filLists[i], testTable)
|
||||
|
||||
|
||||
|
||||
|
||||
writeTableToFile(FLUID_INFO_INCOMP_LIST, testTable)
|
||||
|
||||
@@ -5,17 +5,16 @@ from CPIncomp import getExampleNames, getPureFluids, getCoefficientFluids,\
|
||||
import sys
|
||||
from CPIncomp.DataObjects import SolutionData
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
runTest = False
|
||||
runTest = False
|
||||
runFitting = True
|
||||
runReports = True
|
||||
runSummary = True
|
||||
|
||||
|
||||
writer = SolutionDataWriter()
|
||||
doneObjs = []
|
||||
|
||||
|
||||
# To debug single fluids
|
||||
if runTest:
|
||||
solObjs = []
|
||||
@@ -41,11 +40,11 @@ if __name__ == '__main__':
|
||||
writer.writeFluidList(solObjs)
|
||||
writer.writeReportList(solObjs)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# treat the examples first
|
||||
fluidObjs = getExampleNames(obj=True)
|
||||
examplesToFit = ["ExamplePure","ExampleSolution","ExampleDigital","ExampleDigitalPure"]
|
||||
|
||||
|
||||
print("\nProcessing example fluids")
|
||||
for obj in fluidObjs:
|
||||
if obj.name in examplesToFit:
|
||||
@@ -54,11 +53,11 @@ if __name__ == '__main__':
|
||||
doneObjs += fluidObjs[:]
|
||||
if runFitting: writer.writeFluidList(doneObjs)
|
||||
if runReports: writer.writeReportList(doneObjs, pdfFile="all_examples.pdf")
|
||||
|
||||
# If the examples did not cause any errors,
|
||||
|
||||
# If the examples did not cause any errors,
|
||||
# we can proceed to the real data.
|
||||
doneObjs = []
|
||||
|
||||
|
||||
print("\nProcessing fluids with given coefficients")
|
||||
fluidObjs = getCoefficientFluids()
|
||||
doneObjs += fluidObjs[:]
|
||||
@@ -68,11 +67,11 @@ if __name__ == '__main__':
|
||||
if runFitting: writer.fitFluidList(fluidObjs)
|
||||
else: writer.readFluidList(fluidObjs)
|
||||
doneObjs += fluidObjs[:]
|
||||
|
||||
|
||||
print("\nProcessing Melinder fluids")
|
||||
fluidObjs = getMelinderFluids()
|
||||
doneObjs += fluidObjs[:]
|
||||
|
||||
|
||||
print("\nProcessing pure fluids")
|
||||
fluidObjs = getPureFluids()
|
||||
if runFitting: writer.fitFluidList(fluidObjs)
|
||||
@@ -84,12 +83,12 @@ if __name__ == '__main__':
|
||||
if runFitting: writer.fitSecCoolList(fluidObjs)
|
||||
else: writer.readFluidList(fluidObjs)
|
||||
doneObjs += fluidObjs[:]
|
||||
|
||||
|
||||
print("\nAll {0} fluids processed, all coefficients should be set.".format(len(doneObjs)))
|
||||
print("Checking the list of fluid objects.")
|
||||
#doneObjs += getCoefficientObjects()[:]
|
||||
doneObjs = sorted(doneObjs, key=lambda x: x.name)
|
||||
|
||||
|
||||
purefluids = []
|
||||
solMass = []
|
||||
solMole = []
|
||||
@@ -108,16 +107,16 @@ if __name__ == '__main__':
|
||||
solVolu += [doneObjs[i]]
|
||||
elif doneObjs[i].xid==SolutionData.ifrac_pure:
|
||||
purefluids += [doneObjs[i]]
|
||||
else:
|
||||
else:
|
||||
errors += [doneObjs[i]]
|
||||
solutions = solMass
|
||||
solutions += solMole
|
||||
solutions += solVolu
|
||||
|
||||
|
||||
if runFitting: print("All checks passed, going to write parameters to disk.")
|
||||
if runFitting: writer.writeFluidList(doneObjs)
|
||||
|
||||
if runReports:
|
||||
|
||||
if runReports:
|
||||
print("Creating the fitting reports for the different groups.")
|
||||
#writer.writeReportList(doneObjs)
|
||||
#doneObjs.sort(key=lambda x: (x.xid ,x.name))
|
||||
@@ -126,15 +125,14 @@ if __name__ == '__main__':
|
||||
writer.writeReportList(purefluids, pdfFile="all_pure.pdf")
|
||||
if len(solutions)>0 and runReports:
|
||||
print("Processing {0:2d} solutions - ".format(len(solutions)), end="")
|
||||
writer.writeReportList(solutions, pdfFile="all_solutions.pdf")
|
||||
writer.writeReportList(solutions, pdfFile="all_solutions.pdf")
|
||||
if len(errors)>0 and runReports:
|
||||
print("Processing {0:2d} faulty fluids - ".format(len(errors)), end="")
|
||||
writer.writeReportList(errors, pdfFile="all_errors.pdf")
|
||||
|
||||
|
||||
if runSummary:
|
||||
writer.makeSolutionPlots(solObjs=doneObjs, pdfObj=None)
|
||||
|
||||
print("All done, bye")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user