Removed some obsolete documentation
This commit is contained in:
parent
0783630204
commit
0d991f5251
13 changed files with 1 additions and 540 deletions
|
|
@ -6,17 +6,8 @@ the menu at the top to view detailed documentation of the code.
|
|||
</p>
|
||||
<ul>
|
||||
<li>\subpage languages</li>
|
||||
<li>\subpage cantera-build</li>
|
||||
<li>Working with %Cantera in MATLAB</li>
|
||||
<ul><li>\subpage matlab-tutorial</li></ul>
|
||||
<li>Working with %Cantera in C++</li>
|
||||
<ul><li>\subpage start</li>
|
||||
<li> \subpage cxx-ctnew</li>
|
||||
</ul>
|
||||
<li>Computing Properties of Matter</li>
|
||||
<ul><li>\subpage thermopage</li>
|
||||
<li>\subpage transportpage</li>
|
||||
</ul>
|
||||
<li>\subpage thermopage</li>
|
||||
</ul>
|
||||
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
|
|
@ -1,169 +0,0 @@
|
|||
namespace Cantera {
|
||||
/**
|
||||
|
||||
\page writebindings Writing Python and MATLAB Bindings for your C++ Cantera Extensions
|
||||
|
||||
\section bindintro Introduction
|
||||
|
||||
Suppose you have developed some useful extensions to %Cantera for a particular application. Your code probably consists of a library of C++ classes and functions, and one or more C++ application programs that use the library. Since you are the developer of the library, you are most likely comfortable working in C++, but even so, for solving problems quickly you may wish you could knock out a short Python script or MATLAB m-file, instead of having to write, compile, and link a C++ driver program every time. Or perhaps you are happy to work in C++, but you have shown your work to others, and now they want to use your extensions too, but they are not C++ programmers.
|
||||
|
||||
Since %Cantera provides bindings for Python, MATLAB, and Fortran, you can create interfaces for your library by following the same procedures used for the rest of %Cantera. Here we'll describe step-by-step how to do this.
|
||||
|
||||
|
||||
\section notools Why not use automated tools?
|
||||
|
||||
Before we start, we should say upfront that this process is a bit involved, and is not automated. The main reason for the complexity is that %Cantera supports multiple user environments. If we only wanted to generate Python bindings for C++ classes, we could use SWIG (http://www.swig.org), which reads in a C++ class definition, and writes out a corresponding Python "wrapper" class and C++ interfacing code so that the methods of the Python class invoke those of the C++ class.
|
||||
|
||||
There are two problems with using SWIG, however. The first is that while SWIG supports multiple output languages, MATLAB and Fortran 90 are not among them. The second problem is that the SWIG-generated Python classes function (by design) very much like the C++ classes. They do not take advantage of things you can do in Python that are not possible in C++.
|
||||
|
||||
For example, %Cantera classes that represent phases of matter have a method called getMoleFractions that can be used like this:
|
||||
|
||||
\verbatim
|
||||
ThermoPhase* gas = importPhase("gas.cti");
|
||||
...
|
||||
int nsp = gas.nSpecies();
|
||||
double x[nsp];
|
||||
gas.getMoleFractions(x); \endverbatim
|
||||
|
||||
Since C++ cannot return arrays as return values, the array x must first be created with an appropriate size, and then the method gtMoleFractions is called to write the mole fraction values into x. Mole fraction values are written to the aray for all species, in the order in which they were declared in the input file. If only selected values are desired, several lines of additional code would be required to find and select the desired species:
|
||||
|
||||
\verbatim
|
||||
int i_H2 = has.speciesIndex("H2");
|
||||
int i_CO = has.speciesIndex("CO");
|
||||
int i_CH3 = has.speciesIndex("CH3")
|
||||
double xh2 = x[i_H2];
|
||||
double xco = x[i_CO];
|
||||
double xch3 = x[i_CH3]; \endverbatim
|
||||
|
||||
But in Python, this can all be done much more compactly:
|
||||
|
||||
\verbatim
|
||||
gas = importPhase("gas.cti")
|
||||
...
|
||||
x = gas.moleFractions(["H2", "CO", "CH3"])
|
||||
\endverbatim
|
||||
|
||||
In the Python class, there is a method moleFractions that returns an array of mole fractions, so there is no need to manually allocate the array as in C++ - Python takes care of the memory allocation, and deletes it when it is no longer used. The moleFractions method takes an optional argument that is a list of species names, in which case the array returned contains mole fractions for just those species, in the order listed.
|
||||
|
||||
This example illustrates why %Cantera Python classes are not copies of the underlying C++ class. Instead, they are designed to operate in a way that uses features of Python to enhance usability. This means that the task of writing the interfacing code is more complex, however, since it requires though and judgement, which automated tools are not very good at.
|
||||
|
||||
|
||||
\section binexample An Example
|
||||
|
||||
|
||||
To see how this works, consider the class Droplet, shown below, that models a single evaporating droplet. This class is intentionally simplified for use as an example, but all of the essential features are the same as for more complex classes.
|
||||
|
||||
\verbatim
|
||||
#ifndef DROPLET_H
|
||||
#define DROPLET_H
|
||||
|
||||
// parameters taken from Example 3.2, p. 103, in "An Introduction to
|
||||
// Combustion" by S.R. Turns
|
||||
|
||||
namespace DropletNamespace {
|
||||
|
||||
const double Dab_0 = 8.1e-6; // m2/s
|
||||
const double Tboil = 489.5; //
|
||||
const double molWt = 170.337;
|
||||
const double hfg = 2.56e5; // J/kg
|
||||
const double rho_vapor = 0.4267;
|
||||
const double rho_liquid = 749.0;
|
||||
|
||||
class Droplet {
|
||||
public:
|
||||
|
||||
Droplet(double D=-1.0, double T=300.0) : m_diam(D),
|
||||
m_temp(T),
|
||||
m_yinf(0.0) {}
|
||||
virtual ~Droplet() {}
|
||||
|
||||
void setTemperature(double T) { m_temp = T; }
|
||||
void setYinf(double yinf = 0.0) { m_yinf = yinf; }
|
||||
|
||||
double diam() const { return m_diam; }
|
||||
double mass() const { return rho_liquidPi*m_diam*m_diam*m_diam/6.0}
|
||||
void evaporate(double time) {
|
||||
if (m_diam > 0.0) {
|
||||
double d2 = m_diam*m_diam - evapConstant*time;
|
||||
if (d2 < 0.0) m_diam = 0.0;
|
||||
else m_diam = sqrt(d2);
|
||||
}
|
||||
}
|
||||
|
||||
double evapRate() const {
|
||||
return 4.0*Pi*rho_vapor*Dab()*log(1.0+B());
|
||||
}
|
||||
|
||||
double B() const {
|
||||
double ys = surfaceMassFraction();
|
||||
return (ys - m_yinf)/(1.0 - ys);
|
||||
}
|
||||
double surfaceMassFraction() const {
|
||||
double ps = Psat();
|
||||
return ps*molWt/(ps*molWt + (OneAtm - ps)*28.014);
|
||||
}
|
||||
double Psat() const { return OneAtm*exp(-hfg*molWt*
|
||||
(1.0/m_temp - 1.0/Tboil)/GasConstant); }
|
||||
double evapConstant() const { return (8.0*rho_vapor*Dab()/rho_liquid)
|
||||
*log(1.0 + B());}
|
||||
double lifetime() const { return m_diam*m_diam/evapConstant();}
|
||||
|
||||
protected:
|
||||
|
||||
double Dab() { return Dab_0*pow(800.0/399.0, 1.5); }
|
||||
|
||||
double m_diam, m_temp, m_yinf;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
\endverbatim
|
||||
|
||||
|
||||
|
||||
We would like to write bindings for Python, MATLAB, and Fortran,so that we can do thigs like this:
|
||||
|
||||
\verbatim
|
||||
class Spray:
|
||||
|
||||
def __init__(self):
|
||||
self._drops = []
|
||||
|
||||
def addDroplet(self, d):
|
||||
self._drops.append(d)
|
||||
|
||||
def evaporate(self, time):
|
||||
for d in self._drops:
|
||||
d.evaporate(time)
|
||||
|
||||
def mass(self):
|
||||
m = 0.0
|
||||
for d in self._drops:
|
||||
m += d.mass()
|
||||
|
||||
def d32(self):
|
||||
sumd3 = 0.0
|
||||
sumd2 = 0.0
|
||||
for drop in self._drops:
|
||||
d = drop.diam()
|
||||
sumd3 += d*d*d
|
||||
sumd2 += d*d
|
||||
return sumd3/sumd2
|
||||
|
||||
|
||||
dbar = 1.0e-4
|
||||
sigma = 1.0e-5
|
||||
cloud = []
|
||||
for i in range(20):
|
||||
d = random.gauss(dbar, sigma)
|
||||
d = Droplet(d, T)
|
||||
cloud.append(d)
|
||||
print T, d.lifetime()
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
namespace cantera {
|
||||
|
||||
/**
|
||||
|
||||
\page buildcygwin Building Cantera on a Windows PC with cygwin
|
||||
|
||||
|
||||
\section whatcygwin What is cygwin?
|
||||
|
||||
Cygwin is a collection of programs that run under MS-Windows and
|
||||
provide a unix-like environment, including all of the gnu utilities
|
||||
and compilers, as well as X11R6 graphics. You can get it here:
|
||||
http://www.cygwin.com.
|
||||
|
||||
|
||||
\section notescygwin A few things to note
|
||||
|
||||
|
||||
%Cantera can be built with cygwin in much the same way it is built on any other unix-like platform. You can have on the same machine a Windows %Cantera installation, and a separate cygwin %Cantera installation. These are stored in different places on your disk, and don't conflict with one another.
|
||||
|
||||
- <B>Required components.</B> The cygwin installer installs only a very basic set of utilities by default. To build %Cantera, you need at a minimum gcc, g++, python, make, and bash. I would suggest getting a good editor too, like xemacs. All of these may be installed by simply checking the appropriate boxes in the cygwin network installer. (While you're at it, you might as well get everything. If you have a fast network connection and a reasonable-size disk, you can have a complete unix-like environment up and running in just a few minutes.)
|
||||
|
||||
- <B>About Python.</B> Note that even if you have Python installed on your system for use from Windows, you need to separately install Python for cygwin from the cygwin installer script. Python for Windows is built with Microsoft Visual C++ (not compatible with GNU g++), and expects path names to be "Windows-style", (C:\\PYTHON24\\PYTHON.EXE) instead of "unix-style" (/usr/local/python). Also, the %Cantera Python package under Windows builds as a Windows DLL, and under cygwin as a unix-like shared library (.so). As a result, your Windows Python is not compatible with cygwin, which is why you need to install a separate Python for use in cygwin. Note that installing python for cygwin does not in any way affect your Windows Python installation, and visa-versa: they are completely separate, and don't even know if the other one is present or not. If you install the %Cantera Python package using cygwin, it will be installed only on the cygwin Python, not on the Windows Python (and visa versa). So all this means is that you need to install Python, %Cantera, and everything else twice, assuming you want to use %Cantera both from Windows and cygwin.
|
||||
|
||||
- <B>MATLAB.</B> There is no MATLAB version for cygwin, and the Windows
|
||||
version is not compatible with cygwin. So if you want to use
|
||||
MATLAB with %Cantera, you should build %Cantera under Windows,
|
||||
linux, or some other OS for which a version of MATLAB exists.
|
||||
.
|
||||
|
||||
Other than these points, the %Cantera build procedure under cygwin is essentially just like that on any other unix-like platform.
|
||||
|
||||
\see \ref cantera-build
|
||||
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
|
||||
\page cxx-ctnew Compiling and Linking your C++ Program
|
||||
|
||||
\section cxx-demo Building the C++ demo program
|
||||
|
||||
When you installed Cantera, a script named "ctnew" was added to the
|
||||
bin directory within the Cantera installation directory. This script
|
||||
generates a demo C++ program and a Makefile to build it that is
|
||||
already configured correctly for your system. If you have run setup_cantera, then the bin directory should be on your PATH, so you can just type
|
||||
\verbatim
|
||||
ctnew
|
||||
\endverbatim
|
||||
After ctnew runs, you will find two new files in the current directory: demo.cpp and demo.mak. To build the demo, type
|
||||
\verbatim
|
||||
make -f demo.mak
|
||||
\endverbatim
|
||||
To run the demo, type:
|
||||
\verbatim
|
||||
./demo
|
||||
\endverbatim
|
||||
|
||||
\section cxx-app Building your application
|
||||
|
||||
To build your own C++ program, simply replace demo.o in the list of object files near the top of demo.mak with the object files for your application. You may want to rename demo.mak to Makefile or some other name. Now you should be able to simply type "make" to build your application!
|
||||
|
||||
*/
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
#include "cantera/IdealGasMix.h" // defines class IdealGasMix
|
||||
#include "cantera/equilibrium.h" // chemical equilibrium
|
||||
#include "cantera/transport.h" // transport properties
|
||||
|
||||
using namespace Cantera;
|
||||
|
||||
void demoprog()
|
||||
{
|
||||
|
||||
// construct a gas mixture object from the specification in
|
||||
// fileh2o2.cti, which defines a reacting hydrogen/oxygen mixture.
|
||||
IdealGasMix gas("h2o2.cti","ohmech");
|
||||
|
||||
// set its state by specifying the temperature, pressure,
|
||||
// and mole fractions
|
||||
double temp = 1200.0;
|
||||
double pres = OneAtm;
|
||||
gas.setState_TPX(temp, pres, "H2:1, O2:1, AR:2");
|
||||
|
||||
// Print some thermodynamic properties
|
||||
|
||||
printf("\n\nInitial state:\n\n");
|
||||
printf(
|
||||
"Temperature: %14.5g K\n"
|
||||
"Pressure: %14.5g Pa\n"
|
||||
"Density: %14.5g kg/m3\n"
|
||||
"Molar Enthalpy: %14.5g J/kmol\n"
|
||||
"Molar Entropy: %14.5g J/kmol-K\n"
|
||||
"Molar cp: %14.5g J/kmol-K\n",
|
||||
gas.temperature(), gas.pressure(), gas.density(),
|
||||
gas.enthalpy_mole(), gas.entropy_mole(), gas.cp_mole());
|
||||
|
||||
// set the gas to the equilibrium state with the same specific
|
||||
// enthalpy and pressure
|
||||
equilibrate(gas,"HP");
|
||||
|
||||
// Print them again for the new equilibrium state
|
||||
|
||||
printf("\n\nEquilibrium state:\n\n");
|
||||
printf(
|
||||
"Temperature: %14.5g K\n"
|
||||
"Pressure: %14.5g Pa\n"
|
||||
"Density: %14.5g kg/m3\n"
|
||||
"Molar Enthalpy: %14.5g J/kmol\n"
|
||||
"Molar Entropy: %14.5g J/kmol-K\n"
|
||||
"Molar cp: %14.5g J/kmol-K\n",
|
||||
gas.temperature(), gas.pressure(), gas.density(),
|
||||
gas.enthalpy_mole(), gas.entropy_mole(), gas.cp_mole());
|
||||
|
||||
|
||||
// Reaction information
|
||||
|
||||
int irxns = gas.nReactions();
|
||||
double* qf = new double[irxns];
|
||||
double* qr = new double[irxns];
|
||||
double* q = new double[irxns];
|
||||
|
||||
// since the gas has been set to an equilibrium state, the forward
|
||||
// and reverse rates of progress should be equal for all
|
||||
// reversible reactions, and the net rates should be zero.
|
||||
// We'll print them to check this.
|
||||
gas.getFwdRatesOfProgress(qf);
|
||||
gas.getRevRatesOfProgress(qr);
|
||||
gas.getNetRatesOfProgress(q);
|
||||
|
||||
printf("\n\n");
|
||||
for (int i = 0; i < irxns; i++) {
|
||||
printf("%30s %14.5g %14.5g %14.5g kmol/m3/s\n",
|
||||
gas.reactionString(i).c_str(), qf[i], qr[i], q[i]);
|
||||
}
|
||||
|
||||
|
||||
// transport properties
|
||||
|
||||
Transport* tr = newTransportMgr("Mix", &gas, 1);
|
||||
|
||||
printf("\n\nViscosity: %14.5g Pa-s\n", tr->viscosity());
|
||||
printf("Thermal conductivity: %14.5g W/m/K\n", tr->thermalConductivity());
|
||||
|
||||
int nsp = gas.nSpecies();
|
||||
double* diff = new double[nsp];
|
||||
tr->getMixDiffCoeffs(diff);
|
||||
int k;
|
||||
printf("\n\n%20s %26s\n", "Species","Diffusion Coefficient");
|
||||
for (k = 0; k < nsp; k++) {
|
||||
printf("%20s %14.5g m2/s \n", gas.speciesName(k).c_str(), diff[k]);
|
||||
}
|
||||
|
||||
// clean up
|
||||
delete qf;
|
||||
delete qr;
|
||||
delete q;
|
||||
delete diff;
|
||||
delete tr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
demoprog();
|
||||
} catch (CanteraError& err) {
|
||||
std::cout << err.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#include "cantera/base/ctexceptions.h"
|
||||
|
||||
void demoprog()
|
||||
{
|
||||
// Calls Cantera
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
demoprog();
|
||||
} catch (Cantera::CanteraError& err) {
|
||||
std::cout << err.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#include "cantera/thermo.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Cantera::ThermoPhase* gas = Cantera::newPhase("h2o2.cti","ohmech");
|
||||
std::cout << gas->temperature() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#include "cantera/thermo.h"
|
||||
//
|
||||
// artifical example of throwing and catching a CanteraError exception.
|
||||
//
|
||||
|
||||
using namespace Cantera;
|
||||
|
||||
void mycode()
|
||||
{
|
||||
ThermoPhase* gas = newPhase("h2o2.cti","ohmech");
|
||||
if (gas->temperature() < 3000.0) {
|
||||
throw CanteraError("mycode","test of exception throwing and catching");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
mycode();
|
||||
} catch (CanteraError& err) {
|
||||
std::cout << err.what() << std::endl;
|
||||
error("program terminating.");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
|
||||
\page cxx-exceptions Exception Handling
|
||||
|
||||
%Cantera throws exceptions of type CanteraError when an error is encountered. Your program should always catch these. You can throw CanteraError exceptions too, if you like, or you can use your own application-specific exception classes.
|
||||
|
||||
\include except.cpp
|
||||
|
||||
The function \c showErrors is a convenient way to display the error
|
||||
message in the \c catch block. The \c error function prints an error
|
||||
and terminates execution. Note that both of these functions are
|
||||
environment-specific; i.e. they behave differently if you are running
|
||||
your Cantera code embedded in a MATLAB application than if you run it
|
||||
as a stand-alone C++ application. \see textlogs
|
||||
|
||||
The output generated when this program is run is shown below.
|
||||
\verbatim
|
||||
************************************************
|
||||
Cantera Error!
|
||||
************************************************
|
||||
|
||||
|
||||
Procedure: mycode
|
||||
Error: test of exception throwing and catching
|
||||
|
||||
|
||||
program terminating.
|
||||
\endverbatim
|
||||
*/
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
|
||||
\page initthermo Initializing Thermodynamics objects
|
||||
|
||||
This note will go through
|
||||
some of the details with instantiating Thermodynamics objects within Cantera
|
||||
by reading their data in from XML files.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
\page installnumarray Installing numarray
|
||||
|
||||
If you plan to use %Cantera from Python, or want to run any of the Python demo scripts, or use the graphical MixMaster application, then you need to install the 'numarray' package.
|
||||
|
||||
Numarray provides capabilities for Python to work efficiently work large matrices, and is
|
||||
used by the %Cantera Python package.
|
||||
|
||||
\section numWin Installing numarray on Windows
|
||||
|
||||
If you are using a PC running Windows, go to http://sourceforge.net/projects/numpy and download the Windows binary installer for numarray. All you need to do is to execute this installer to install numarray.
|
||||
|
||||
\section numUnix Building and Installing numarray on a unix-like platform
|
||||
|
||||
On a unix-like (linux, Mac OS X) platform, you need to build numarray from source code. The procedure to do this is largely automated, and takes only a few minutes. Here's what you do:
|
||||
|
||||
- Get the source code from http://sourceforge.net/projects/numpy. This file should have a
|
||||
name like numarray-1.x.x.tar.gz.
|
||||
- Unpack the compresssed tar archive:
|
||||
\verbatim
|
||||
gunzip numarray-1.x.x.tar.gz
|
||||
tar xvf numarray-1.x.x.tar \endverbatim
|
||||
- Go into the directory created by unpacking the archive, and type at a shell prompt
|
||||
\verbatim
|
||||
python setup.py build \endverbatim
|
||||
This compiles everything, and puts the files in a temporary directory, ready to be
|
||||
installed wherever you specify in the next step.
|
||||
.
|
||||
|
||||
\section numAll Installing numarray for all users
|
||||
|
||||
If your are the system administrator and want to install numaray so that every user can access it, then simply type
|
||||
|
||||
\verbatim
|
||||
python setup.py install
|
||||
\endverbatim
|
||||
|
||||
You will probably have to run this command as super-user. Doing the install step this way will put
|
||||
the numarray module in the 'site-packages' subdirectory within the python 'lib' directory. This
|
||||
has the advantage that Python always looks in this directory for modules -- there is no need to
|
||||
set PYTHONPATH for the interpreter to find numarray. But it does require write access to the
|
||||
Python 'lib' directory, which typically only the system administrator has.
|
||||
|
||||
\section numLocal Installing a local version of numarray
|
||||
|
||||
If you are not the system administrator, then you can install a local version of numarray in your
|
||||
home directory by adding the --home option to the 'install' step. For example, if you want to
|
||||
install all numarray files within a directory named 'python_modules' in your home directory, then do this:
|
||||
|
||||
\verbatim
|
||||
python setup.py build
|
||||
python setup.py install --home=$HOME/python_modules
|
||||
\endverbatim
|
||||
|
||||
Note that if you use the --home option, you will need to configure %Cantera so that it knows where to
|
||||
find numarray. To do this, you can either set environment variable NUMARRAY_HOME to the directory
|
||||
you specified with the --home option (e.g. $HOME/python_modules), or edit the
|
||||
cantera 'preconfig' script to set this variable there.
|
||||
|
||||
*/
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
|
||||
\page transportpage Transport Properties
|
||||
|
||||
%Cantera can be used to compute transport properties
|
||||
|
||||
|
||||
\section nest Non-Equilibrium Statistical Thermodynamics
|
||||
|
||||
|
||||
\section tbase Base Class for Transport Properties
|
||||
|
||||
|
||||
The base class \link Cantera::Transport Transport \endlink is used for all
|
||||
transport classes within Cantera.
|
||||
|
||||
|
||||
|
||||
There is a list of classes which handle transport for species (see
|
||||
\ref tranprops " Transport Properties for Species in Phases").
|
||||
|
||||
|
||||
*/
|
||||
Loading…
Add table
Reference in a new issue