diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 42e2a5491..395bd50ca 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -1,25 +1,35 @@
name: CI
on: [push]
+
jobs:
- Build:
+ tests_and_coverage:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
- gcc_v: [10] # Version of GFortran we want to use.
python-version: [3.9]
- env:
- FC: gfortran-${{ matrix.gcc_v }}
- GCC_V: ${{ matrix.gcc_v }}
-
+ toolchain:
+ - {compiler: gcc, version: 10}
+ - {compiler: gcc, version: 11}
+ - {compiler: gcc, version: 12}
+ - {compiler: gcc, version: 13}
+ - {compiler: intel, version: '2024.1'}
+ - {compiler: intel, version: '2023.2'}
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
submodules: false
+ - name: Setup Fortran Compiler
+ uses: fortran-lang/setup-fortran@v1
+ id: setup-fortran
+ with:
+ compiler: ${{ matrix.toolchain.compiler }}
+ version: ${{ matrix.toolchain.version }}
+
- name: Install Python
uses: actions/setup-python@v1 # Use pip to install latest CMake, & FORD/Jin2For, etc.
with:
@@ -33,39 +43,69 @@ jobs:
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- - name: Install Python dependencies
- if: contains( matrix.os, 'ubuntu')
+ - name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ford numpy matplotlib gcovr numpy scipy
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
-
- - name: Install GFortran Linux
- if: contains( matrix.os, 'ubuntu')
- run: |
- sudo apt-get install lcov
- sudo update-alternatives \
- --install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.gcc_v }} 100 \
- --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${{ matrix.gcc_v }} \
- --slave /usr/bin/gcov gcov /usr/bin/gcov-${{ matrix.gcc_v }}
-
- - name: Install NLopt
- run:
sudo apt-get install libnlopt-dev
- - name: Compile
- run: fpm build --profile release
+ - name: Run tests without coverage
+ if: ${{ env.FC != 'gfortran' }}
+ run: |
+ fpm test --profile debug --compiler ${{ env.FC }} --c-compiler gcc
- - name: Run tests
+ - name: Run tests with coverage
+ if: ${{ env.FC == 'gfortran' }}
run: |
- fpm test --profile debug --flag -coverage
+ fpm test --profile debug --flag -coverage --compiler ${{ env.FC }} --c-compiler gcc
bash ci/ci.sh
-
+
- name: Coverage
run: bash ci/ci.sh coverage
+ if: ${{ env.FC == 'gfortran' }}
- name: Upload coverage reports to Codecov
+ if: ${{ env.FC == 'gfortran' }}
uses: codecov/codecov-action@v4.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: ipqa-research/yaeos
+
+ Python-API:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest]
+ gcc_v: [10] # Version of GFortran we want to use.
+ python-version: [3.9]
+ env:
+ FC: gfortran-${{ matrix.gcc_v }}
+ GCC_V: ${{ matrix.gcc_v }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ submodules: false
+
+ - name: Install Python
+ uses: actions/setup-python@v1 # Use pip to install latest CMake, & FORD/Jin2For, etc.
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ working-directory: ./python
+ run: |
+ sudo apt-get install libnlopt-dev meson
+ pip install meson tox
+
+ - name: Install yaeos
+ working-directory: ./python
+ run:
+ pip install .
+
+# - name: tox
+# working-directory: ./python
+# run: tox -r
diff --git a/.gitignore b/.gitignore
index 90b2de1a8..5ede0ddcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,10 +8,12 @@ doc/ford_site
*.smod
*mypy*
*.so
+*.egg-info
tools/uml
tools/uml.png
tools/uml.svg
python/yaeos/script.py
+__pycache__
iso
log
coverage.xml
@@ -44,3 +46,23 @@ log_srk-hv
srk
srk_hv
fort.2
+*.egg-info
+*ipynb_checkpoints
+chulia
+flang.rsp
+flash
+flash_log_para
+flash_log_sequ
+fort.4
+log2
+para.py
+tools/plotting/pt_envel_2ph.gnu
+tools/notebooks/other.ipynb
+dist
+.tox
+.coverage
+tmp_editable
+hsprpxy
+iters
+n2c8data
+prpxy
diff --git a/README.md b/README.md
index eb8306229..467026fed 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
[](https://fortran-lang.org)
[](https://fpm.fortran-lang.org)
[](https://ipqa-research.github.io/yaeos/)
@@ -6,7 +5,6 @@
[](https://github.com/ipqa-research/yaeos/actions/workflows/CI.yml)
[](https://codecov.io/gh/ipqa-research/yaeos)
-
@@ -36,15 +34,39 @@ derivatives so both options are easily available.
We focus mainly on that the addition of a new thermodynamic model as easily as
possible. Also providing our models too!
-For now, we only include residual Helmholtz model (like Cubic or Saft Equations
-of State). But we'll be adding other models like $G^E$ (UNIFAC for example).
+For now, we only include residual Helmholtz model (like Cubic or SAFT Equations
+of State).
+
+## Available models
+- CubicEoS
+ - SoaveRedlichKwong
+ - PengRobinson76
+ - PengRobinson78
+- ExcessGibbs models
+ - NRTL
+ - UNIFAC VLE
+
+## Available properties
+- Bulk Properties
+ - Volume(n, P, T)
+ - Pressure(n, V, T)
+- Residual Properties
+ - H^R(n, V, T)
+ - S^R(n, V, T)
+ - G^R(n, V, T)
+ - Cv^R(n, V, T)
+ - Cp^R(n, V, T)
+- Phase-Equilibria
+ - FlashPT, FlashVT
+ - Saturation points (bubble, dew and liquid-liquid)
+ - Phase Envelope PT (isopleths)
# A little taste of `yaeos`
A lot of users get the bad picture of Fortran being old and archaic since most
of the codes they've seen are written in ancient `F77`.
```fortran
-use yaeos, only: PengRobinson76, pressure, ArModel
+use yaeos, only: PengRobinson76, ArModel
integer, parameter :: n=2 ! Number of components
real(8) :: V, T, P, dPdN(n) ! variables to calculate
@@ -64,7 +86,7 @@ model = PengRobinson76(tc, pc, w, kij, lij)
V = 1
T = 150
-call pressure(model, z, V, T, P)
+call model%pressure(z, V, T, P)
print *, P
! Obtain derivatives adding them as optional arguments!
@@ -83,30 +105,42 @@ with:
Not providing any example will show all the possible examples that can be run.
# How to install/run it
-`yaeos` is intended to use as a [`fpm`](fpm.fortran-lang.org)
-You can either:
-
-- Generate a new project that uses `yaeos` as a dependency
+## Dependencies
+`yaeos` needs to have both `lapack` and `nlopt` libraries on your system.
+### Debian/Ubuntu-like
```bash
-fpm new my_project
+sudo apt install libnlopt-dev libblas-dev liblapack-dev
```
-In the `fpm.toml` file add:
+## Installing `yaeos`
+`yaeos` is intended to use as a [`fpm`](fpm.fortran-lang.org) package. `fpm`
+is the Fortran Package Manager, which automates the compilation and running
+process of Fortran libraries/programs.
-```toml
-[dependencies]
-yaeos = {git="https://github.com/ipqa-research/yaeos"}
-```
+You can either:
+
+- Generate a new project that uses `yaeos` as a dependency with:
+
+> ```bash
+> fpm new my_project
+> ```
+>
+> In the `fpm.toml` file add:
+>
+> ```toml
+> [dependencies]
+> yaeos = {git="https://github.com/ipqa-research/yaeos"}
+> ```
- Clone this repository and just modify the executables in the `app` directory
-```bash
-git clone https://github.com/ipqa-research/yaeos
-cd yaeos
-fpm run
-```
+> ```bash
+> git clone https://github.com/ipqa-research/yaeos
+> cd yaeos
+> fpm run
+> ```
## Developing with vscode
If your intention is either to develop for `yaeos` or to explore in more detail
@@ -131,6 +165,8 @@ fpm run --example
```
# Including new models with Automatic Differentiation.
+
+## Hyperdual Numbers autodiff
We are using the `hyperdual` module developed by
[Philipp Rehner](https://github.com/prehner)
and [Gernot Bauer](https://github.com/g-bauer)
@@ -138,56 +174,15 @@ and [Gernot Bauer](https://github.com/g-bauer)
> The automatic differentiation API isn't fully optimized yet so performance is
> much slower than it should be.
-```fortran
-type, extends(ArModelAdiff) :: YourNewModel
- type(Substances) :: composition
- real(8), allocatable :: parameters(:) ! A vector of parameters
-contains
- procedure :: Ar => arfun
- procedure :: get_v0 => v0
-end type
-```
-
-```fortran
-subroutine arfun(self, n, v, t, Ar)
- class(YourNewModel), intent(in) :: self
- type(hyperdual), intent(in) :: n(:) ! Number of moles
- type(hyperdual), intent(in) :: v ! Volume [L]
- type(hyperdual), intent(in) :: t ! Temperature [K]
- type(hyperdual), intent(out) :: ar_value ! Residual Helmholtz Energy
-
- ! A very complicated residual helmholtz function of a mixture
- Ar = sum(n) * v * t / self%parameters(1)
-end subroutine
-
-function v0(self, n, p, t)
- class(YourNewModel), intent(in) :: self
- real(pr), intent(in) :: n(:) ! Number of moles
- real(pr), intent(in) :: p ! Pressure [bar]
- real(pr), intent(in) :: t ! Temperature [K]
- real(pr) :: v0
-
- v0 = self%parameters(3)
-end function
-```
-
A complete implementation of the PR76 Equation of State can me found in
-`example/adiff/adiff_pr76.f90`.
-
-All the thermodynamic properties can be found in `yaeos_thermoprops` and called
-like:
+`example/adiff/adiff_pr76.f90`. Or in the documentation pages.
-```fortran
-use yaeos_thermoprops, only: fugacity_vt
-use my_new_model, only: YourNewModel
-...
-type(YourNewModel) :: eos
-eos%parameters = [1, 2, 3]
-call fugacity_vt(eos, n, v, t, lnfug=lnfug, dlnphidn=dlnphidn)
-```
+## Tapenade-based autodiff
+It is also possible to differentiate with `tapenade`. Examples can be seen
+in the documentation pages or in [The tools directory](tools/tapenade_diff/)
# Documentation
The latest API documentation for the `main` branch can be found
[here](https://ipqa-research.github.io/yaeos). This was generated from the source
code using [FORD](https://github.com/Fortran-FOSS-Programmers/ford). We're
-working in extending it more.
+working in extending it more.
\ No newline at end of file
diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md
index ef7ed19af..c0f180ff0 100644
--- a/STYLE_GUIDE.md
+++ b/STYLE_GUIDE.md
@@ -8,13 +8,28 @@ This style guide is a living document and proposed changes may be adopted after
## Use (modern) standard Fortran
-* Do not use obsolescent or deleted language features
+* Do **not** use obsolescent or deleted language features
E.g., `common`, `pause`, `entry`, arithmetic `if` and computed `goto`
-* Do not use vendor extensions in the form of non-standard syntax and vendor supplied intrinsic procedures
+* Do **not** use vendor extensions in the form of non-standard syntax and vendor supplied intrinsic procedures
E.g., `real*8` or `etime()`, use `real(pr)`
-## File naming conventions
+## Naming of variables and constructs
+- Variable and procedure names, as well as Fortran keywords, should be written in lowercase
+- All constants (like the `R` gas constant) should be upper case
+- All variables should be in lowercase unless they are represented in uppercase in the bibliography.
+ for example, the molar volume would be `v` and the total volume would be `V`.
+- In the case of derivatives, for general properties they should be written as `dXdy` for first derivatives and `dXdyz` or `dXdy2` for second order derivatives. The only exception is with energetic properties, like `Ar`, where derivatives are written like `ArV`, `ArVn`, etc.
+- All thermodynamic variables that are input of a subroutine/function should
+ have the order:
+ - `n, V, T`
+ - `n, P, T`
+- Variable and procedure names should be made up of one or more full words separated by an underscore,
+ for example `has_failed` is preferred over `hasfailed`
+- Where conventional and appropriate shortening of a word is used then the underscore may be omitted,
+ for example `linspace` is preferred over `lin_space`
+- For derived types use CamelCase, like `ArModel`
+## File naming conventions
* Source files should contain at most one `program`, `module`, or `submodule`
* The filename should match the program or module name and have the file extension `.f90` or `.F90` if preprocessing is required
* `module` names should include it's subdirectory, using `yaeos__` for the parent
@@ -34,18 +49,11 @@ than style and formatting.
We recommend ~~enforce~~ the use of `findent` to format your files.
-* The body of every Fortran construct should be indented by __four (4) spaces__
+* The body of every Fortran construct should be indented by __three (3) spaces__
* Line length *should be limited to 80 characters* and __must not exceed 132__
* **Do not** use Tab characters for indentation
* **Remove** trailing white space before committing code
-## Variable and procedure naming
-
-* Variable and procedure names, as well as Fortran keywords, should be written in lowercase
-* Variable and procedure names should be made up of one or more full words separated by an underscore,
- for example `has_failed` is preferred over `hasfailed`
-* Where conventional and appropriate shortening of a word is used then the underscore may be omitted,
- for example `linspace` is preferred over `lin_space`
## Attributes
diff --git a/app/fit.f90 b/app/fit.f90
index 148c267e2..d12a5309f 100644
--- a/app/fit.f90
+++ b/app/fit.f90
@@ -1,101 +1,11 @@
-module yaeos__fitting_fit_nrtl
- use yaeos__constants, only: pr
- use yaeos__fitting, only: FittingProblem
- use yaeos__models, only: ArModel, NRTL, CubicEoS, MHV
- use forsus, only: Substance
- implicit none
-
- integer, parameter :: nc = 2
-
- type, extends(FittingProblem) :: FitMHVNRTL
- contains
- procedure :: get_model_from_X => model_from_X
- end type
-
-contains
-
- subroutine init_model(problem, sus)
- use yaeos, only: R, ArModel, CubicEoS, PengRobinson78, RKPR, SoaveRedlichKwong
- class(FitMHVNRTL), intent(in out) :: problem
- type(Substance), intent(in) :: sus(2)
- type(MHV) :: mixrule
- type(NRTL) :: ge
- real(pr) :: tc(nc), pc(nc), w(nc), vc(nc), zc(nc)
- real(pr) :: a(nc, nc), b(nc, nc), c(nc, nc), bi(nc)
-
- a=0; b=0; c=0
-
- tc = sus%critical%critical_temperature%value
- pc = sus%critical%critical_pressure%value/1e5
- w = sus%critical%acentric_factor%value
- vc = sus%critical%critical_volume%value
- zc = pc*vc/(R*tc)
-
- ge = NRTL(a, b, c)
-
- ! problem%model = RKPR(tc, pc, w, zc)
- allocate(CubicEoS :: problem%model)
- problem%model = SoaveRedlichKwong(tc, pc, w)
-
- associate(m => problem%model)
- select type(m)
- type is (CubicEoS)
- bi = m%b
- mixrule = MHV(ge=ge, q=-0.593_pr, b=bi)
- deallocate(m%mixrule)
- m%mixrule = mixrule
- end select
- end associate
- end subroutine init_model
-
- function model_from_X(problem, X) result(model)
- use yaeos, only: R, RKPR, PengRobinson78, ArModel, QMR, CubicEoS
- use yaeos__models_ar_cubic_quadratic_mixing, only: RKPR_D1mix
- real(pr), intent(in) :: X(:)
- class(FitMHVNRTL), intent(in) :: problem
- class(ArModel), allocatable :: model
- type(NRTL) :: ge
-
- real(pr) :: a(nc, nc), b(nc, nc), c(nc, nc)
-
- a=0; b=0; c=0
-
- a(1, 2) = x(1)
- a(2, 1) = x(2)
-
- b(1, 2) = x(3)
- b(2, 1) = x(4)
-
- c(1, 2) = x(5)
- c(2, 1) = x(6)
-
- ge = NRTL(a, b, c)
-
- model = problem%model
-
- select type(model)
- class is (CubicEoS)
- associate(mr => model%mixrule)
- select type (mr)
- class is (MHV)
- mr%l(1, 2) = x(7)
- mr%l(2, 1) = x(7)
- mr%ge = ge
- model%del1 = x(8:)
- model%del2 = (1._pr - model%del1)/(1._pr + model%del1)
- end select
- end associate
- end select
- end function model_from_X
-end module
-
program main
!! Binary system parameter optimization
- use yaeos, only: EquilibriaState, pr, ArModel, PengRobinson78, CubicEoS, saturation_pressure
+ use yaeos, only: EquilibriaState, pr, ArModel, SoaveRedlichKwong, CubicEoS, saturation_pressure
+ use yaeos, only: MHV
use forsus, only: Substance, forsus_dir
use yaeos__fitting, only: FittingProblem, fobj, optimize
- use yaeos__fitting_fit_nrtl, only: FitMHVNRTL, init_model
- integer, parameter :: nc = 2, np=7 + nc
+ use yaeos__fitting_fit_nrtl_mhv, only: FitMHVNRTL
+ integer, parameter :: nc = 2, np=7
integer :: i, infile, iostat
type(EquilibriaState), allocatable :: exp_points(:)
@@ -135,15 +45,21 @@ program main
! ==========================================================================
! Setup optimization problem and call the optimization function
! --------------------------------------------------------------------------
- call init_model(prob, sus)
-
+ model = SoaveRedlichKwong(&
+ sus%critical%critical_temperature%value, &
+ sus%critical%critical_pressure%value/1e5, &
+ sus%critical%acentric_factor%value &
+ )
+
+ prob%model = model
+
prob%experimental_points = exp_points
X = 0
X(1:2) = [0.1, 0.3]
X(5:6) = [0.1, 0.2]
- X(8:) = [1, 1]
+ prob%fit_nrtl = .true.
prob%parameter_step = [(0.5_pr, i=1,size(x))]
prob%solver_tolerance = 1e-7
prob%verbose = .true.
@@ -153,8 +69,8 @@ program main
print *, "FO:", error
print *, "Xf:", X
- if (allocated(model)) deallocate (model)
- model = prob%get_model_from_X(X)
+ call prob%get_model_from_X(X)
+ model = prob%model
! ===========================================================================
! Write out results and experimental values
diff --git a/app/flash.f90 b/app/flash.f90
index 1907c4f86..1f6a83502 100644
--- a/app/flash.f90
+++ b/app/flash.f90
@@ -3,7 +3,7 @@ program flasher
!! EoS model.
! Import the relevant
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
implicit none
! Variables definition:
diff --git a/app/isotherm.f90 b/app/isotherm.f90
index 952cae11c..7fd13a43d 100644
--- a/app/isotherm.f90
+++ b/app/isotherm.f90
@@ -1,6 +1,9 @@
program main
- use yaeos, only: pr, ArModel, PengRobinson76, volume, pressure, SoaveRedlichKwong
+ use yaeos, only: pr, ArModel, PengRobinson76, SoaveRedlichKwong
+ use yaeos__models_ar, only: nvolume => volume
+ use yaeos__models_solvers, only: volume_michelsen
use forsus, only: Substance, forsus_dir
+ use fortime, only: timer
implicit none
class(ArModel), allocatable :: eos
@@ -8,52 +11,39 @@ program main
real(pr), dimension(nc) :: n, tc, pc, w
real(pr), dimension(nc, nc) :: kij, lij
+ type(timer) :: tim
+
type(Substance) :: sus(2)
- real(pr) :: v
- real(pr) :: p0, pf, dp, p
- real(pr) :: t0, tf, dt, t
- integer :: i, j, n_p_points=500, n_t_points=5
+ real(pr) :: v, T, P
+ real(pr) :: lnphip(nc)
+
+ integer :: i, nevals=100000
forsus_dir = "build/dependencies/forsus/data/json"
sus(1) = Substance("propane", only=["critical"])
sus(2) = Substance("n-butane", only=["critical"])
- n = [0.7, 0.3]
+ n = [0.99, 0.01]
tc = sus%critical%critical_temperature%value
pc = sus%critical%critical_pressure%value/1e5
w = sus%critical%acentric_factor%value
- kij = reshape([0., 0.0, 0.0, 0.], [nc,nc])
- lij = kij / 2
- eos = SoaveRedlichKwong(tc, pc, w, kij, lij)
+ eos = SoaveRedlichKwong(tc, pc, w)
+ T = 350
+ P = 500
- p0 = 100
- pf = 0.1
- dp = (pf-p0)/n_p_points
+ do i=1,10000
+ P = real(i, pr)/10
+ call eos%volume(n, P, T, V, "stable")
+ print *, V, P
+ end do
- t0 = 150
- tf = 350
- dt = (tf-t0)/n_t_points
+ print "(/)"
- T = 300
do i=1,1000
- V = real(i, pr)/1000._pr
- call pressure(eos, n, V, T, P=P)
+ P = real(i, pr)/10
+ call volume_michelsen(eos, n, P, T, V, "stable")
print *, V, P
end do
-
-
-
- ! do j=0, n_t_points - 1
- ! t = t0 + dt * j
- ! print *, "# ", t
- ! do i=0,n_p_points-1
- ! p = p0 + dp * i
- ! call volume(eos, n, p, t, v, root_type="stable")
- ! print *, v, p
- ! end do
- ! print *, ""
- ! print *, ""
- ! end do
end program main
diff --git a/app/main.f90 b/app/main.f90
index 49ffcbe57..c225cf06a 100644
--- a/app/main.f90
+++ b/app/main.f90
@@ -1,17 +1,12 @@
program main
- use yaeos, only: pr, R, Substances, AlphaSoave, CubicEoS, GenericCubic_Ar, fugacity_vt, fugacity_tp, volume, QMR
+ use yaeos, only: pr, R, Substances, AlphaSoave, CubicEoS, GenericCubic_Ar
use yaeos, only: ArModel, PengRobinson76
implicit none
- type(Substances) :: compos
- type(CubicEoS), target :: eos, eos2
- type(AlphaSoave) :: alpha
- type(QMR) :: mixrule
-
- class(ArModel), pointer :: this
+ type(CubicEoS), target :: eos
integer, parameter :: n=2
- real(pr) :: z(n), b, dbi(n), dbij(n,n)
+ real(pr) :: z(n)
real(pr) :: v=1.0, t=150.0, p
real(pr) :: ar
@@ -19,12 +14,9 @@ program main
real(pr) :: arn(n), arvn(n), artn(n), arn2(n,n)
real(pr) :: lnfug(n), dlnphidp(n), dlnphidt(n), dlnphidn(n, n)
- class(ArModel), allocatable :: models(:)
real(pr) :: tc(n), pc(n), w(n), kij(n, n), lij(n, n)
- integer :: i
-
z = [0.3_pr, 0.7_pr]
tc = [190._pr, 310._pr]
pc = [14._pr, 30._pr]
@@ -38,7 +30,7 @@ program main
v = 1
t = 150
- call fugacity_vt(eos, &
+ call eos%lnphi_vt(&
z, V, T, P, lnfug, dlnPhidP, dlnphidT, dlnPhidn &
)
diff --git a/app/phase_diagram.f90 b/app/phase_diagram.f90
index 3250b5ff9..3b59e559c 100644
--- a/app/phase_diagram.f90
+++ b/app/phase_diagram.f90
@@ -1,53 +1,58 @@
program phase_diagram
+ !! Program for calculation of phase diagrams.
use forsus, only: Substance, forsus_dir, forsus_default_dir
- use yaeos
+ use yaeos, only: pr, &
+ SoaveRedlichKwong, PengRobinson76, PengRobinson78, RKPR, &
+ EquilibriaState, ArModel, PTEnvel2, &
+ pt_envelope_2ph, saturation_pressure, saturation_temperature
use yaeos__phase_equilibria_auxiliar, only: k_wilson
implicit none
- class(ArModel), allocatable :: model
- type(EquilibriaState) :: init
- type(PTEnvel2) :: envelope
-
- integer, parameter :: nc=2
- integer :: i
- real(pr) :: n(nc), tc(nc), pc(nc), w(nc), kij(nc, nc), lij(nc, nc), T
- type(Substance) :: sus(nc)
-
+ ! ===========================================================================
+ ! Variables definition
+ ! ---------------------------------------------------------------------------
+ integer, parameter :: nc=2
+ class(ArModel), allocatable :: model ! Thermodynamic model to be used
+ type(EquilibriaState) :: sat_point ! Init
+ type(PTEnvel2) :: envelope ! PT Phase envelope
+ real(pr) :: tc(nc), pc(nc), w(nc) ! Component's critical constants
+ real(pr) :: n(nc) ! Termodynamic variables
+ type(Substance) :: sus(nc) ! Substances to use
+ ! ===========================================================================
+
+ ! forsus database directory
forsus_dir = "build/dependencies/forsus/" // forsus_default_dir
+
+ ! Find the selected substances on the database and extract their
+ ! critical constants
sus(1) = Substance("methane")
sus(2) = Substance("n-hexane")
+ call get_critical_constants(sus, tc, pc, w)
- n = [0.9_pr, 0.1_pr] ! Composition
- tc = sus%critical%critical_temperature%value
- pc = sus%critical%critical_pressure%value/1e5
- w = sus%critical%acentric_factor%value
-
- kij = 0
- kij(1, 2) = 0.0
- kij(2, 1) = kij(1, 2)
-
- lij = 0
+ ! Model definition
+ model = PengRobinson76(tc, pc, w)
- model = PengRobinson76(tc, pc, w, kij, lij)
+ ! Composition vector
+ n = [0.9_pr, 0.1_pr]
+
+ ! Calculate a dew point at low pressure to later
+ ! initialize the phase envelope
+ sat_point = saturation_temperature(model, n, P=1._pr, kind="dew", t0=150._pr)
- ! Calculate a dew point
- T = 150
- do i=0, 6
- kij(1, 2) = 0._pr + real(i,pr)/10
- kij(2, 1) = kij(1, 2)
- lij = kij/10
+ ! Calculate phase envelope
+ envelope = pt_envelope_2ph(model, n, sat_point)
- model = PengRobinson78(tc, pc, w, kij, lij)
+ ! Write the phase envelope to screen
+ write(*, *) envelope
- init = saturation_temperature(model, n, P=1._pr, kind="dew", t0=150._pr)
- init%x = 1/k_wilson(model, init%T, init%P) * init%y
- envelope = pt_envelope_2ph(model, n, init, delta_0=0.01_pr, points=1000)
- write(1, *) envelope
+contains
- init = saturation_pressure(model, n, T=150._pr, kind="bubble", p0=40._pr)
- envelope = pt_envelope_2ph(model, n, init, points=1000)
- write(1, *) envelope
+ subroutine get_critical_constants(subs, tc_in, pc_in, w_in)
+ type(Substance) :: subs(:)
+ real(pr), intent(out) :: tc_in(:), pc_in(:), w_in(:)
- end do
-
+ tc_in = subs%critical%critical_temperature%value
+ pc_in = subs%critical%critical_pressure%value/1e5
+ w_in = subs%critical%acentric_factor%value
+ end subroutine
end program phase_diagram
diff --git a/app/saturation.f90 b/app/saturation.f90
new file mode 100644
index 000000000..a186c0dec
--- /dev/null
+++ b/app/saturation.f90
@@ -0,0 +1,64 @@
+program main
+ use yaeos
+ integer, parameter :: nc=2
+ type(NRTL) :: ge_model
+
+ real(pr), dimension(nc,nc) :: a, b, c
+ real(pr), dimension(nc) :: tc, pc, w
+ type(MHV) :: mixrule
+ type(CubicEOS) :: eos
+ type(EquilibriaState) :: eq
+ real(pr) :: n(nc)
+
+ integer :: i
+
+ tc = [647.13999999999999, 513.91999999999996]
+ pc = [220.63999999999999, 61.479999999999997]
+ w = [0.34399999999999997, 0.64900000000000002]
+ a = 0; b = 0; c = 0
+
+ ! NRTL model parameters
+ a(1, 2) = 3.458
+ a(2, 1) = -0.801
+
+ b(1, 2) = -586.1
+ b(2, 1) = 246.2
+
+ c(1, 2) = 0.3
+ c(2, 1) = 0.3
+
+ eos = PengRobinson76(tc, pc, w)
+ ge_model = NRTL(a, b, c)
+ mixrule = MHV(ge=ge_model, q=-0.53_pr, b=eos%b)
+
+ deallocate(eos%mixrule)
+ eos%mixrule = mixrule
+
+ do i=1,99
+ n(1) = real(i, pr)/100
+ n(2) = 1 - n(1)
+ eq = saturation_pressure(eos, n, 273._pr + 100._pr, kind="bubble")
+ print *, eq%x(1), eq%y(1), eq%P
+ end do
+
+ call ge_model%ln_activity_coefficient([0.3_pr, 0.7_pr], 250._pr, n)
+ print *, n
+end program main
+
+
+! for i, T in enumerate(np.linspace(50+273, 200+273, 5)):
+! i=4
+! xs = np.linspace(0.001, 0.999, 100)
+! ys = []
+! ps = []
+!
+! for x1 in xs:
+! x = [x1, 1-x1]
+! p, x, y, vx, vy, beta = yaeos.yaeos_c.saturation_pressure(model.id, x, T, "bubble")
+! ps.append(p)
+! ys.append(y[0])
+!
+! plt.plot(xs, ps, color=colors[i])
+! plt.plot(ys, ps, color=colors[i])
+! end program
+!
diff --git a/app/tpd.f90 b/app/tpd.f90
new file mode 100644
index 000000000..efbb8615e
--- /dev/null
+++ b/app/tpd.f90
@@ -0,0 +1,39 @@
+program phase_diagram
+ use forsus, only: Substance, forsus_dir
+ use yaeos
+ use yaeos__phase_equilibria_stability, only: tm, min_tpd
+ use yaeos, only: flash
+ implicit none
+
+ integer, parameter :: nc=2
+
+ class(ArModel), allocatable :: model
+ type(Substance) :: sus(nc)
+ real(pr) :: tc(nc), pc(nc), ac(nc)
+ real(pr) :: z(nc), T, P
+ real(pr) :: w(nc), mintpd
+
+ forsus_dir = "build/dependencies/forsus/data/json"
+ sus(1) = Substance("methane")
+ sus(2) = Substance("hydrogen sulfide")
+
+ z = [0.13, 1-0.13]
+ z = z/sum(z)
+
+ P = 20.0_pr
+ T = 190._pr
+
+ tc = sus%critical%critical_temperature%value
+ pc = sus%critical%critical_pressure%value/1e5_pr
+ ac = sus%critical%acentric_factor%value
+
+ model = SoaveRedlichKwong(tc, pc, ac)
+
+ call min_tpd(model, z, P, T, mintpd, w)
+ print *, mintpd, w/sum(w)
+
+ P = 15
+ call min_tpd(model, z, P, T, mintpd, w)
+ print *, mintpd, w/sum(w)
+
+end program phase_diagram
diff --git a/ci/ci.sh b/ci/ci.sh
index 4b357b9b7..bbe297c11 100644
--- a/ci/ci.sh
+++ b/ci/ci.sh
@@ -71,6 +71,16 @@ run_coverage() {
--fail-under-line 90
}
+python_wrappers(){
+ BUILD_DIR="build/python"
+ fpm install --profile release --prefix "$BUILD_DIR"
+ cd python/yaeos
+ f2py \
+ -I ../../$BUILD_DIR/include \
+ -L ../../$BUILD_DIR/lib/libyaeos.a \
+ -m yaeos -c ../yaeos_c.f90 ../../$BUILD_DIR/lib/libyaeos.a
+}
+
resumee() {
[ $DID_TEST = 1 ] &&
echo There has been $NAMING_ERRORS test naming errors
@@ -86,9 +96,9 @@ case $1 in
"install") install_fpm;;
"test") run_test;;
"coverage") run_coverage;;
+ "python") python_wrappers;;
*)
run_test
run_coverage
resumee;;
-esac
-
+esac
\ No newline at end of file
diff --git a/doc/page/index.md b/doc/page/index.md
index da1b89dfb..d182fe490 100644
--- a/doc/page/index.md
+++ b/doc/page/index.md
@@ -1,7 +1,6 @@
---
title: User documentation
ordered_subpage: usage
- theory
contributing
---
@@ -31,4 +30,4 @@ model = setup_model()
! Once the model is set up, the user has access to the properties
call pressure(model, V, T, P, dPdN=dPdN)
-```
+```
\ No newline at end of file
diff --git a/doc/page/theory/index.md b/doc/page/theory/index.md
deleted file mode 100644
index 6d1f993ef..000000000
--- a/doc/page/theory/index.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: Theorical background
----
\ No newline at end of file
diff --git a/doc/page/usage/cubics.md b/doc/page/usage/cubics.md
deleted file mode 100644
index 539f5958e..000000000
--- a/doc/page/usage/cubics.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cubic Models
----
-
-
diff --git a/doc/page/usage/eos/cubics/alpha.md b/doc/page/usage/eos/cubics/alpha.md
new file mode 100644
index 000000000..b4cbf7cfd
--- /dev/null
+++ b/doc/page/usage/eos/cubics/alpha.md
@@ -0,0 +1,3 @@
+---
+title: alpha functions
+---
\ No newline at end of file
diff --git a/doc/page/usage/eos/cubics/index.md b/doc/page/usage/eos/cubics/index.md
new file mode 100644
index 000000000..08325e7be
--- /dev/null
+++ b/doc/page/usage/eos/cubics/index.md
@@ -0,0 +1,14 @@
+---
+title: Cubics
+---
+
+** Table of contents**
+[TOC]
+
+## SoaveRedlichKwong
+
+## PengRobinson76
+
+## PengRobinson78
+
+## RKPR
\ No newline at end of file
diff --git a/doc/page/usage/eos/cubics/mixing.md b/doc/page/usage/eos/cubics/mixing.md
new file mode 100644
index 000000000..e46c64ccf
--- /dev/null
+++ b/doc/page/usage/eos/cubics/mixing.md
@@ -0,0 +1,69 @@
+---
+title: Mixing Rules
+---
+
+# Cubic Mixing Rules
+All [[CubicEoS]] in `yaeos` include a [[CubicMixRule]] derived type, which
+handles how the \(D\) and \(B\) parameters in the CubicEoS are calculated.
+
+## Quadratic Mixing Rules (QMR)
+Quadratic mixing rules are the ussually most used mixing rules for cubic
+equations of state.
+
+\[
+ nB = \sum_i \sum_j n_i n_j \frac{b_i + b_j}{2} (1 - l_{ij})
+\]
+
+\[
+ D = \sum_i \sum_j n_i n_j a_{ij}
+\]
+
+QMR are handled by the [[QMR]] derived type. Which can be used like:
+
+```fortran
+use yaeos, only: pr, QMR
+
+type(QMR) :: mixrule
+real(pr) :: kij(2, 2), lij(2, 2)
+
+kij(1, :) = [0.0, 0.1]
+kij(2, :) = [0.1, 0.0]
+
+lij(1, :) = [0.0, 0.01]
+lij(2, :) = [0.01, 0.0]
+
+mixrule = QMR(k=kij, l=lij)
+```
+
+By default the \(a_{ij}\) matrix will be calculated with a constant \(k_{ij}\)
+value (as shown below). But this functionality can be modified by replacing
+the `get_aij` procedure
+
+```fortran
+use yaeos, only: pr, QMR
+
+type(QMR) :: mixrule
+real(pr) :: kij(2, 2), lij(2, 2)
+
+kij(1, :) = [0.0, 0.1]
+kij(2, :) = [0.1, 0.0]
+
+lij(1, :) = [0.0, 0.01]
+lij(2, :) = [0.01, 0.0]
+
+mixrule = QMR(k=kij, l=lij)
+mixrule%get_aij => my_aij_implementation
+
+subroutine my_aij_implementation(self, ai, daidt, daidt2, aij, daijdt, daijdt2)
+ class(QMR) :: self
+ real(pr), intent(in) :: ai(:), daidt(:), daidt2(:)
+ real(pr), intent(out) :: aij(:, :), daijdt(:, .), daijdt2(:, :)
+ ! Implementation here
+end subroutine
+```
+
+### Constant \(k_{ij}\)
+
+## \(G^E\) Models Mixing Rules
+
+### Michelsen's Modified Huron-Vidal Mixing Rules
\ No newline at end of file
diff --git a/doc/page/usage/eos/index.md b/doc/page/usage/eos/index.md
new file mode 100644
index 000000000..c828b5b17
--- /dev/null
+++ b/doc/page/usage/eos/index.md
@@ -0,0 +1,6 @@
+---
+title: Equations of State
+ordered_subpage: cubics
+---
+
+Explain ArModels thermoprops here
\ No newline at end of file
diff --git a/doc/page/usage/excessmodels/index.md b/doc/page/usage/excessmodels/index.md
new file mode 100644
index 000000000..397e3a111
--- /dev/null
+++ b/doc/page/usage/excessmodels/index.md
@@ -0,0 +1,5 @@
+---
+title: Gibbs Excess Models
+---
+
+Explain thermoprops of Ge models here
\ No newline at end of file
diff --git a/doc/page/usage/excessmodels/nrtl.md b/doc/page/usage/excessmodels/nrtl.md
new file mode 100644
index 000000000..59ebcbf4b
--- /dev/null
+++ b/doc/page/usage/excessmodels/nrtl.md
@@ -0,0 +1,3 @@
+---
+title: NRTL
+---
\ No newline at end of file
diff --git a/doc/page/usage/excessmodels/unifaclv.md b/doc/page/usage/excessmodels/unifaclv.md
new file mode 100644
index 000000000..384b0293c
--- /dev/null
+++ b/doc/page/usage/excessmodels/unifaclv.md
@@ -0,0 +1,106 @@
+---
+title: UNIFAC-LV
+---
+
+# UNIFAC
+
+[[UNIFAC]] (UNIQUAC Functional-group Activity Coefficients) is an Excess Gibbs
+free energy model used to estimate activity coefficients in non-ideal mixtures.
+It is particularly useful for predicting the phase behavior of chemical
+mixtures, including liquid-liquid equilibrium (LLE) and vapor-liquid
+equilibrium (VLE). In this model the Excess Gibbs free energy is calculated
+from the contribution of a combinatorial term and a residual term.
+
+$$ \frac{G^E}{RT} = \frac{G^{E,r}}{RT} + \frac{G^{E,c}}{RT} $$
+
+Being:
+
+- Combinatorial: Accounts for the size and shape of the molecules. The involved
+equations can be checked in the API documentation:
+[[yaeos__models_ge_group_contribution_unifac:Ge_combinatorial]]
+
+- Residual: Accounts for the energy interactions between different functional
+groups. The involved equations can be checked in the API documentation:
+[[yaeos__models_ge_group_contribution_unifac:Ge_residual]]
+
+Each substance of a mixture modeled with [[UNIFAC]] must be represented by a
+list a functional groups and other list with the ocurrence of each functional
+group on the substance. The list of the functional groups culd be accesed on
+the DDBST web page:
+[https://www.ddbst.com/published-parameters-unifac.html](https://www.ddbst.com/published-parameters-unifac.html)
+
+# Examples
+## Calculating activity coefficients
+We can instantiate a [[UNIFAC]] model with a mixture ethanol-water and
+evaluate the logarithm of activity coefficients of the model for a 0.5 mole
+fraction of each, and a temperature of 298.0 K.
+
+```fortran
+use yaeos__constants, only: pr
+use yaeos__models_ge_group_contribution_unifac, only: Groups, UNIFAC, setup_unifac
+
+! Variables declarations
+type(UNIFAC) :: model
+type(Groups) :: molecules(2)
+real(pr) :: ln_gammas(2)
+
+! Variables instances
+! Ethanol definition [CH3, CH2, OH]
+molecules(1)%groups_ids = [1, 2, 14] ! Subgroups ids
+molecules(1)%number_of_groups = [1, 1, 1] ! Subgroups occurrences
+
+! Water definition [H2O]
+molecules(2)%groups_ids = [16]
+molecules(2)%number_of_groups = [1]
+
+! Model setup
+model = setup_unifac(molecules)
+
+! Calculate ln_gammas
+call model%ln_activity_coefficient([0.5_pr, 0.5_pr], 298.0_pr, ln_gammas)
+
+print *, ln_gammas
+```
+
+You will obtain:
+
+```
+>>> 0.18534142000449058 0.40331395945417559
+```
+
+# References
+1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+.com/published-parameters-unifac.html)
+2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975). Group‐contribution
+estimation of activity coefficients in nonideal liquid mixtures. AIChE Journal,
+21(6), 1086–1099.
+[https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and Extension.
+Industrial & Engineering Chemistry Process Design and Development, 18(4),
+714–722.
+[https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+equilibriums by UNIFAC group contribution. Revision and extension. 2.
+Industrial & Engineering Chemistry Process Design and Development, 21(1),
+118–127.
+[https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+Vapor-liquid equilibriums by UNIFAC group contribution. Revision and extension.
+3. Industrial & Engineering Chemistry Process Design and Development, 22(4),
+676–678.
+[https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+[https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., & Gmehling, J.
+(1991). Vapor-liquid equilibria by UNIFAC group contribution. 5. Revision and
+extension. Industrial & Engineering Chemistry Research, 30 (10), 2352–2355.
+[https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria by
+UNIFAC Group Contribution. 6. Revision and Extension. Industrial & Engineering
+Chemistry Research, 42(1), 183–188.
+[https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+9. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
+
diff --git a/doc/page/usage/figs/PTEnvel2.png b/doc/page/usage/figs/PTEnvel2.png
new file mode 100644
index 000000000..6ce136c6d
Binary files /dev/null and b/doc/page/usage/figs/PTEnvel2.png differ
diff --git a/doc/page/usage/index.md b/doc/page/usage/index.md
index 190fdc552..4e421e8ac 100644
--- a/doc/page/usage/index.md
+++ b/doc/page/usage/index.md
@@ -1,5 +1,9 @@
---
title: Using yaeos
+ordered_subpage: eos
+ excessmodels
+ phase_equilibrium
+ newmodels
---
[TOC]
@@ -54,7 +58,7 @@ extening to a broader variety.
In this example we'll show how a model in `yaeos` can be used. We'll take
the `Peng-Robinson` equation of state as an example, but all the implemented
-models can be seen at [[yaeos_models(module)]]. Inside
+models can be seen at [[yaeos__models(module)]]. Inside
your `app/main.f90` file use
```fortran
@@ -119,6 +123,6 @@ call pressure(model, n, v, t, p, dpdv=dpdv) ! Calculate pressure and dPdV
```
The available thermodynamic properties to calculate can be seen at the
-[[yaeos_thermoprops(module)]] module.
+[[yaeos__thermoprops(module)]] module.
# Phase equilibria
diff --git a/doc/page/usage/newmodels/analtical.md b/doc/page/usage/newmodels/analtical.md
new file mode 100644
index 000000000..cd0960fa6
--- /dev/null
+++ b/doc/page/usage/newmodels/analtical.md
@@ -0,0 +1,3 @@
+---
+title: Analytical derivatives
+---
diff --git a/doc/page/usage/newmodels/autodiff.md b/doc/page/usage/newmodels/autodiff.md
new file mode 100644
index 000000000..e1424ae5e
--- /dev/null
+++ b/doc/page/usage/newmodels/autodiff.md
@@ -0,0 +1,153 @@
+---
+title: Automatic differentiation
+---
+# Autodiff
+The implementation of new models and all their required derivatives can be
+an endeavours and error-prone task. A tool that helps with this, at a small
+performance cost, can be automatic differentiation.
+
+Automatic differentiation can be implemented in two ways:
+
+- Forward Differentiation
+- Backward Differentiation
+
+With can be combined to obtain higher order derivatives.
+
+In `yaeos` it is possible to add new models via two different kind of
+implementations. Operator overloading with `hyperdual` numbers and
+source-to-source automatic differentiation with `tapenade`.
+
+@warn
+Remember to use the `R`constant from `yaeos__constants`, and all models
+should have a `type(Substances)` attribute!
+@endwarn
+
+## Hyperdual autodiff
+
+### ArModel
+Automatic differentiation with `hyperdual` numbers can be done with the
+[[ArModelAdiff]] derived type. This implementation requires just to extend
+that derived type with your own implementation and a volume initializer.
+
+```fortran
+module hyperdual_pr76
+ use yaeos__constants, only: pr, R
+ use yaeos__ar_models_hyperdual
+ use yaeos__substance, only: Substances
+ implicit none
+
+ type, extends(ArModelAdiff) :: PR76
+ !! PengRobinson 76 EoS
+ ! Composition
+ type(Substances) :: composition
+
+ ! Mixing rule Parameters
+ real(pr), allocatable :: kij(:, :), lij(:, :)
+
+ ! EoS parameters
+ real(pr), allocatable :: ac(:), b(:), k(:)
+ real(pr), allocatable :: tc(:), pc(:), w(:)
+ contains
+ procedure :: Ar => arfun
+ procedure :: get_v0 => v0
+ end type
+
+ real(pr), parameter :: del1 = 1._pr + sqrt(2._pr)
+ real(pr), parameter :: del2 = 1._pr - sqrt(2._pr)
+
+contains
+
+ type(PR76) function setup(tc, pc, w, kij, lij) result(self)
+ !! Function to obtain a defined PR76 model with setted up parameters
+ !! as function of Tc, Pc, and w
+ real(pr) :: tc(:)
+ real(pr) :: pc(:)
+ real(pr) :: w(:)
+ real(pr) :: kij(:, :)
+ real(pr) :: lij(:, :)
+
+ self%composition%tc = tc
+ self%composition%pc = pc
+ self%composition%w = w
+
+ self%ac = 0.45723553_pr * R**2 * tc**2 / pc
+ self%b = 0.07779607_pr * R * tc_in/pc_in
+ self%k = 0.37464_pr + 1.54226_pr * w - 0.26993_pr * w**2
+
+ self%kij = kij
+ self%lij = lij
+ end function
+
+ function arfun(self, n, v, t) result(ar)
+ !! Residual Helmholtz calculation for a generic cubic with
+ !! quadratic mixing rules.
+ class(PR76) :: self
+ type(hyperdual), intent(in) :: n(:), v, t
+ type(hyperdual) :: ar
+
+ type(hyperdual) :: amix, a(size(n)), ai(size(n)), n2(size(n))
+ type(hyperdual) :: bmix
+ type(hyperdual) :: b_v, nij
+
+ integer :: i, j
+
+ associate(&
+ pc => self%composition%pc, ac => self%ac, b => self%b, k => self%k,&
+ kij => self%kij, lij => self%lij, tc => self%compostion%tc &
+ )
+
+ ! Soave alpha function
+ a = 1.0_pr + k * (1.0_pr - sqrt(t/tc))
+ a = ac * a ** 2
+ ai = sqrt(a)
+
+ ! Quadratic Mixing Rule
+ amix = 0.0_pr
+ bmix = 0.0_pr
+
+ do i=1,size(n)-1
+ do j=i+1,size(n)
+ nij = n(i) * n(j)
+ amix = amix + 2 * nij * (ai(i) * ai(j)) * (1 - kij(i, j))
+ bmix = bmix + nij * (b(i) + b(j)) * (1 - lij(i, j))
+ end do
+ end do
+
+ amix = amix + sum(n**2*a)
+ bmix = bmix + sum(n**2 * b)
+
+ bmix = bmix/sum(n)
+
+ b_v = bmix/v
+
+ ! Generic Cubic Ar function
+ ar = (&
+ - sum(n) * log(1.0_pr - b_v) &
+ - amix / (R*T*bmix)*1.0_pr / (del1 - del2) &
+ * log((1.0_pr + del1 * b_v) / (1.0_pr + del2 * b_v)) &
+ ) * (R * T)
+
+ end associate
+ end function
+
+ function v0(self, n, p, t)
+ !! Initialization of liquid volume solving with covolume
+ class(PR76), intent(in) :: self
+ real(pr), intent(in) :: n(:)
+ real(pr), intent(in) :: p
+ real(pr), intent(in) :: t
+ real(pr) :: v0
+
+ v0 = sum(n * self%b) / sum(n)
+ end function
+end module
+```
+
+
+## Tapenade Adiff
+And alternative to `hyperdual` that takes a bit more work, but can end in a more
+performant model, is doing `tapenade` source-to-source differentiation. For
+this `tapenade` must be installed and accessible from a terminal
+[donwload link](https://tapenade.gitlabpages.inria.fr/userdoc/build/html/download.html).
+
+{!tools/tapenade_diff/README.md!}
\ No newline at end of file
diff --git a/doc/page/usage/newmodel.md b/doc/page/usage/newmodels/index.md
similarity index 62%
rename from doc/page/usage/newmodel.md
rename to doc/page/usage/newmodels/index.md
index b98547e77..459e2756f 100644
--- a/doc/page/usage/newmodel.md
+++ b/doc/page/usage/newmodels/index.md
@@ -3,11 +3,11 @@ title: Adding your own models
---
Most of thermodynamic properties calculated in `yaeos` heavily depend on
-different kind of models and their respective derivatives.
-Since obtaining the derivatives of complex models can be a tedious and
-error-prone task. We provide two different ways of getting them automatically
-(in some cases with some performance-cost), but there is also the possibility
-of using anallyitical obtained expressions instead.
+different kind of models and their respective derivatives. Since obtaining the
+derivatives of complex models can be a tedious and error-prone task. We provide
+two different ways of getting them automatically (in some cases with some
+performance-cost), but there is also the possibility of using analytical
+obtained expressions instead.
The calculation of thermodynamic properties heavily depends on
@@ -18,7 +18,8 @@ On `yaeos` there are three different ways of adding your own model:W
# Residual Helmholtz models
Residual Helmholtz models are the basis to obtain the residual properties.
-The main basis in `yaeos` to define a new object that extends the `abstract type` called `ArModel`. Which enforces the expected functionality of these
+The main basis in `yaeos` to define a new object that extends the `abstract
+type `called` [[ArModel]]. Which enforces the expected functionality of this
kind of models.
```fortran
@@ -30,8 +31,10 @@ end type
The definition of an `ArModel` expects that two procedures are defined:
-- [[abs_residual_helmholtz(interface)]]: Procedure to calculate residual Helmholtz energy and it's derivatives
-- [[abs_volume_initializer(interface)]]: Volume initializer to find a liquid root, given a pressure and temperature.
+- [[abs_residual_helmholtz(interface)]]: Procedure to calculate residual
+ Helmholtz energy and it's derivatives
+- [[abs_volume_initializer(interface)]]: Volume initializer to find a liquid
+ root, given a pressure and temperature.
```fortran
use yaeos, only: ArModel
@@ -53,10 +56,4 @@ type(MyNewModel) :: model
! Assuming model parameters are set-up
call pressure(model, n, V, T, P)
-```
-
-## Using operator overloading automatic differentiation with hyperdual numbers
-
-## Using source-to-source automatic differentiation with tapenade
-
-## Using analytical obtained expressions
+```
\ No newline at end of file
diff --git a/doc/page/usage/phase_equilibrium/envelopes.md b/doc/page/usage/phase_equilibrium/envelopes.md
new file mode 100644
index 000000000..422fe01cb
--- /dev/null
+++ b/doc/page/usage/phase_equilibrium/envelopes.md
@@ -0,0 +1,108 @@
+---
+title: Phase envelopes
+copy_subdir: ../figs
+---
+
+## Two-phase envelopes
+Two-phase envelopes show all the saturation points of a mixture, they can
+be seen as the boundary line of transition between monophasic regions to
+two-phase equilibria regions.
+
+In `yaeos` it is possible to calculate two-phase of different kinds.
+
+- Isoplets
+
+### Isoplets
+Isoplets are the phase boundaries at constant composition
+(the global composition) of the system. Here is a simple example with
+commentaries on how a phase boundary can be calculated:
+
+```fortran
+program phase_diagram
+ !! Program for calculation of phase diagrams.
+ use forsus, only: Substance, forsus_dir, forsus_default_dir
+ use yaeos, only: pr, &
+ SoaveRedlichKwong, PengRobinson76, PengRobinson78, RKPR, &
+ EquilibriaState, ArModel, PTEnvel2, &
+ pt_envelope_2ph, saturation_pressure, saturation_temperature
+ use yaeos__phase_equilibria_auxiliar, only: k_wilson
+ implicit none
+
+ ! ===========================================================================
+ ! Variables definition
+ ! ---------------------------------------------------------------------------
+ integer, parameter :: nc=2
+ class(ArModel), allocatable :: model ! Thermodynamic model to be used
+ type(EquilibriaState) :: sat_point ! Init
+ type(PTEnvel2) :: envelope ! PT Phase envelope
+ real(pr) :: tc(nc), pc(nc), w(nc) ! Component's critical constants
+ real(pr) :: n(nc) ! Termodynamic variables
+ type(Substance) :: sus(nc) ! Substances to use
+ ! ===========================================================================
+
+ ! forsus database directory
+ forsus_dir = "build/dependencies/forsus/" // forsus_default_dir
+
+ ! Find the selected substances on the database and extract their
+ ! critical constants
+ sus(1) = Substance("methane")
+ sus(2) = Substance("n-hexane")
+ call get_critical_constants(sus, tc, pc, w)
+
+ ! Model definition
+ model = PengRobinson76(tc, pc, w)
+
+ ! Composition vector
+ n = [0.9_pr, 0.1_pr]
+
+ ! Calculate a dew point at low pressure to later
+ ! initialize the phase envelope
+ sat_point = saturation_temperature(model, n, P=1._pr, kind="dew", t0=150._pr)
+
+ ! Calculate phase envelope
+ envelope = pt_envelope_2ph(model, n, sat_point)
+
+ ! Write the phase envelope to screen
+ write(*, *) envelope
+
+contains
+
+ subroutine get_critical_constants(subs, tc_in, pc_in, w_in)
+ type(Substance) :: subs(:)
+ real(pr), intent(out) :: tc_in(:), pc_in(:), w_in(:)
+
+ tc_in = subs%critical%critical_temperature%value
+ pc_in = subs%critical%critical_pressure%value/1e5
+ w_in = subs%critical%acentric_factor%value
+ end subroutine
+end program phase_diagram
+```
+
+The output of the `write` command will be pre-formatted. Showing in tabular
+data with this
+
+```
+# PTEnvel2
+
+# kind of sat point
+kind T P [liquid-phase composition vector] [gas-phase composition vector]
+
+# other kind of sat point
+kind T P [liquid-phase composition vector] [gas-phase composition vector]
+
+# Critical
+T P
+```
+
+Which when plotted with `gnuplot` with:
+
+```gnuplot
+plot "outfile" \
+ index "dew" u 2:3 w l title "Dew", \
+ "" index "bubble" u 2:3 w l t "Bubble", \
+ "" index "Critical" u 1:2 w p pt 7 lc rgb "black" t "CP"
+```
+
+Gives the following plot:
+
+
\ No newline at end of file
diff --git a/doc/page/usage/phase_equilibrium/flash.md b/doc/page/usage/phase_equilibrium/flash.md
new file mode 100644
index 000000000..8bb965438
--- /dev/null
+++ b/doc/page/usage/phase_equilibrium/flash.md
@@ -0,0 +1,3 @@
+---
+title: Flash calculations
+---
\ No newline at end of file
diff --git a/doc/page/usage/phase_equilibria.md b/doc/page/usage/phase_equilibrium/index.md
similarity index 52%
rename from doc/page/usage/phase_equilibria.md
rename to doc/page/usage/phase_equilibrium/index.md
index 260c1ed19..171b03891 100644
--- a/doc/page/usage/phase_equilibria.md
+++ b/doc/page/usage/phase_equilibrium/index.md
@@ -1,5 +1,6 @@
---
-title: Phase Equilibria
+title: Phase Equilibrium
+copy_subdir: ../figs
---
Phase Equilibria calculations are fundamental for the majority of EoS based
@@ -14,7 +15,27 @@ The implemented methods, and their usage are:
[TOC]
# Flash calculations
-Flash calcuations
+Flash calcuations are one of the most used phase-equilibria calculations during
+modelling of processes.
+
+In `yaeos` it is possible to make Flash calculations either specifying:
+
+- \( zPT \rightarrow x, y, \beta (V) \)
+- \( zVT \rightarrow x, y, \beta (P) \)
+
+```fortran
+type(EquilibriaState) :: result
+
+! zPT flash
+result = flash(model, z, p_spec=P, T=T)
+
+! zVT flash
+result = flash(model, z, v_spec=P, T=T)
+
+! It is possible to provide initialization compositions in terms of the
+! K-factors. Where k0=y/x
+result = flash(model, z, v_spec=P, T=T, k0=k0)
+```
# Saturation points
Single saturation point calculations are included with the procedures
@@ -28,6 +49,16 @@ f(T \lor P) = \sum ln K_i - 1 = 0
With a newton procedure with respect to the desired variable (either \(P\) or
\(T\).
+```fortran
+type(EquilibriaState) :: sat_point
+
+sat = saturation_pressure(model, z, T=T, kind="bubble")
+sat = saturation_pressure(model, z, T=T, kind="dew")
+
+sat = saturation_temperature(model, z, P=P, kind="bubble")
+sat = saturation_temperature(model, z, P=P, kind="dew")
+```
+
## Phase envelopes
Phase envelopes are the conection of all the saturation points of a system.
When the interest is in calculating a whole phase diagram instead of a single
@@ -35,3 +66,12 @@ point, or the point is hard to converge. It is better to use a robust
mathematical algorithm that eases the calcuation providing an easy-to-converge
point and using its information to initialize a next one and continue along the
whole phase-boundary. This can be done with the procedure [[pt_envelope_2ph]]
+
+```fortran
+type(PTEnvel2) :: env
+
+sat = saturation_pressure(model, z, T=150._pr, kind="bubble")
+env = pt_envelope_2ph(model, z, sat)
+```
+
+
\ No newline at end of file
diff --git a/doc/page/usage/phase_equilibrium/saturation_points.md b/doc/page/usage/phase_equilibrium/saturation_points.md
new file mode 100644
index 000000000..6c99bc5e5
--- /dev/null
+++ b/doc/page/usage/phase_equilibrium/saturation_points.md
@@ -0,0 +1,3 @@
+---
+title: Saturation Points
+---
\ No newline at end of file
diff --git a/example/extra/adiff_pr76.f90 b/example/extra/adiff_pr76.f90
index cea2cab5f..c7646047a 100644
--- a/example/extra/adiff_pr76.f90
+++ b/example/extra/adiff_pr76.f90
@@ -5,10 +5,8 @@ module hyperdual_pr76
implicit none
type, extends(ArModelAdiff) :: PR76
- type(Substances) :: composition
real(pr), allocatable :: kij(:, :), lij(:, :)
real(pr), allocatable :: ac(:), b(:), k(:)
- real(pr), allocatable :: tc(:), pc(:), w(:)
contains
procedure :: Ar => arfun
procedure :: get_v0 => v0
@@ -19,24 +17,24 @@ module hyperdual_pr76
contains
- type(PR76) function setup(tc_in, pc_in, w_in, kij_in, lij_in) result(self)
+ type(PR76) function setup(tc, pc, w, kij, lij) result(self)
!! Seup an Autodiff_PR76 model
- real(pr) :: tc_in(:)
- real(pr) :: pc_in(:)
- real(pr) :: w_in(:)
- real(pr) :: kij_in(:, :)
- real(pr) :: lij_in(:, :)
-
- self%tc = tc_in
- self%pc = pc_in
- self%w = w_in
-
- self%ac = 0.45723553_pr * R**2 * self%tc**2 / self%pc
- self%b = 0.07779607_pr * R * self%tc/self%pc
- self%k = 0.37464_pr + 1.54226_pr * self%w - 0.26993_pr * self%w**2
-
- self%kij = kij_in
- self%lij = lij_in
+ real(pr) :: tc(:)
+ real(pr) :: pc(:)
+ real(pr) :: w(:)
+ real(pr) :: kij(:, :)
+ real(pr) :: lij(:, :)
+
+ self%components%tc = tc
+ self%components%pc = pc
+ self%components%w = w
+
+ self%ac = 0.45723553_pr * R**2 * tc**2 / pc
+ self%b = 0.07779607_pr * R * tc/pc
+ self%k = 0.37464_pr + 1.54226_pr * w - 0.26993_pr * w**2
+
+ self%kij = kij
+ self%lij = lij
end function
function arfun(self, n, v, t) result(ar)
@@ -50,8 +48,8 @@ function arfun(self, n, v, t) result(ar)
integer :: i, j
- associate(pc => self%pc, ac => self%ac, b => self%b, k => self%k, &
- kij => self%kij, lij => self%lij, tc => self%tc &
+ associate(pc => self%components%pc, ac => self%ac, b => self%b, k => self%k, &
+ kij => self%kij, lij => self%lij, tc => self%components%tc &
)
a = 1.0_pr + k * (1.0_pr - sqrt(t/tc))
a = ac * a ** 2
diff --git a/example/extra/benchmark.f90 b/example/extra/benchmark.f90
index 3d4b7ee75..6cd8661f0 100644
--- a/example/extra/benchmark.f90
+++ b/example/extra/benchmark.f90
@@ -1,6 +1,6 @@
module bench
use yaeos, only: pr, R, Substances, AlphaSoave, CubicEoS, &
- fugacity_vt, QMR, PengRobinson76, ArModel, fugacity_tp
+ QMR, PengRobinson76, ArModel
use hyperdual_pr76, only: PR76, setup_adiff_pr76 => setup
use TapeRobinson, only: setup_taperobinson => setup_model
implicit none
@@ -49,14 +49,14 @@ subroutine yaeos__run(n, dn, f_p, model_name)
if (dn) then
if (f_p) then
- call fugacity_tp(&
- model, z, T, P, root_type="stable", &
- lnphip=lnfug, dlnphidp=dlnphidp, dlnphidn=dlnphidn)
+ call model%lnphi_pt(&
+ z, P, T, root_type="stable", &
+ lnPhi=lnfug, dlnphidp=dlnphidp, dlnphidn=dlnphidn)
else
- call fugacity_vt(model, z, V, T, P, lnfug, dlnPhidP, dlnphidT, dlnphidn)
+ call model%lnphi_vt(z, V, T, P, lnfug, dlnPhidP, dlnphidT, dlnphidn)
end if
else
- call fugacity_vt(model, z, V, T, lnphip=lnfug)
+ call model%lnphi_vt(z, V, T, lnPhi=lnfug)
end if
end subroutine
diff --git a/example/extra/flash.f90 b/example/extra/flash.f90
index cd1581367..cc1ddbe84 100644
--- a/example/extra/flash.f90
+++ b/example/extra/flash.f90
@@ -1,5 +1,5 @@
module flashing
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
implicit none
contains
diff --git a/example/extra/hard_spheres_mixing.f90 b/example/extra/hard_spheres_mixing.f90
new file mode 100644
index 000000000..14e7adf11
--- /dev/null
+++ b/example/extra/hard_spheres_mixing.f90
@@ -0,0 +1,209 @@
+module yaeos__HardSpheresCubicEoS
+ use yaeos, only: pr, R, Substances
+ use yaeos__ar_models_hyperdual, only: ArModelAdiff
+ use yaeos__autodiff
+ implicit none
+
+ type, extends(ArModelAdiff) :: HardSpheresCubicEoS
+ real(pr), allocatable :: ac(:), b(:), k(:), kij(:, :), lij(:, :)
+ contains
+ procedure :: Ar => arfun
+ procedure :: get_v0 => v0
+ end type HardSpheresCubicEoS
+
+ real(pr), parameter :: del1 = 1._pr + sqrt(2._pr)
+ real(pr), parameter :: del2 = 1._pr - sqrt(2._pr)
+
+contains
+
+ function arfun(self, n, v, t) result(Ar)
+ class(HardSpheresCubicEoS) :: self !! Model
+ type(hyperdual), intent(in) :: n(:) !! Number of moles vector
+ type(hyperdual), intent(in) :: v !! Volume [L/mol]
+ type(hyperdual), intent(in) :: t !! Temperature [K]
+ type(hyperdual) :: Ar !! Residual Helmholtz energy
+
+ type(hyperdual), dimension(size(n)) :: a
+ type(hyperdual) :: nij
+
+ ! Cubic Parameters
+ type(hyperdual) :: Ar_att
+ type(hyperdual) :: amix, bmix
+ type(hyperdual) :: b_v
+
+ ! HardMixing parameters
+ type(hyperdual) :: Ar_rep
+ type(hyperdual) :: lambda(0:3), eta
+ type(hyperdual) :: l1l2_l3l0
+ type(hyperdual) :: l23_l0l32
+ type(hyperdual) :: logContribution
+ real(pr), parameter :: xi = 4.0_pr
+
+ integer :: i, j
+ integer :: nc
+
+ nc = size(n)
+
+ ! Alpha function
+ associate(&
+ ac => self%ac, b => self%b, k => self%k, &
+ tc => self%components%tc, &
+ kij => self%kij, lij => self%lij)
+
+ ! Attractive parameter
+ a = self%ac*(1.0_pr + self%k*(1.0_pr - sqrt(t/self%components%tc)))**2
+
+ ! Mixing rule
+ amix = 0.0_pr
+ bmix = 0.0_pr
+ lambda = 0.0_pr
+ do i = 1, nc
+ do j = 1, nc
+ nij = n(i)*n(j)
+ amix = amix + nij * sqrt(a(i)*a(j)) * (1 - kij(i, j))
+ bmix = bmix + nij * 0.5_pr * (b(i) + b(j)) *(1 - lij(i, j))
+ end do
+ lambda(1) = lambda(1) + n(i)*b(i)**(1.0_pr/3.0_pr)
+ lambda(2) = lambda(2) + n(i)*b(i)**(2.0_pr/3.0_pr)
+ end do
+ bmix = bmix/sum(n)
+
+ lambda(0) = sum(n)
+ lambda(3) = bmix
+ eta = bmix/v/xi
+ l1l2_l3l0 = lambda(1)*lambda(2)/lambda(3)/lambda(0)
+ l23_l0l32 = lambda(2)**3/lambda(0)/lambda(3)**2
+ logContribution = log(1._pr - xi*eta)/xi
+
+ Ar_rep = -sum(n)*((1._pr + 3._pr*l1l2_l3l0)*logContribution &
+ + 3._pr/xi*(l23_l0l32 - 1._pr/2._pr - l1l2_l3l0/2._pr) &
+ *(eta + logContribution))
+ b_v = bmix/v
+ Ar_att = (- sum(n) * log(1.0_pr - b_v) &
+ - amix / (R*t*bmix)*1.0_pr / (del1 - del2) &
+ * log((1.0_pr + del1 * b_v) / (1.0_pr + del2 * b_v)) &
+ ) * (R * t)
+
+ ar = Ar_rep + Ar_att
+ end associate
+ end function arfun
+
+ function v0(self, n, P, T)
+ class(HardSpheresCubicEoS), intent(in) :: self !! Model
+ real(pr), intent(in) :: n(:) !! Moles vector
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr) :: v0
+
+ v0 = sum(n * self%b)
+ end function v0
+
+
+ subroutine main
+ use yaeos
+ use forsus, only: Substance, forsus_dir, forsus_default_dir
+ use hyperdual_pr76, only: hPr76 => PR76, set_hpr => setup
+
+ integer, parameter :: nc=2
+
+ real(pr) :: n(nc), V, P, Phs, T
+ real(pr) :: tc(nc), pc(nc), w(nc), kij(nc,nc), lij(nc,nc)
+ type(Substance) :: sus(nc)
+
+ type(CubicEoS) :: pr76
+ type(hPR76) :: hdpr76
+ type(HardSpheresCubicEoS) :: hspr76
+
+ type(EquilibriaState) :: eq
+ type(PTEnvel2) :: env
+
+ real(pr) :: Ar, ArT, ArV, ArTV, ArT2, ArV2, Arn(nc), Artn(nc), ArVn(nc), arn2(nc,nc)
+
+ integer :: i
+
+ forsus_dir = "build/dependencies/forsus/" // forsus_default_dir
+
+ sus(1) = Substance("methane")
+ sus(2) = Substance("n-decane")
+
+ tc = sus%critical%critical_temperature%value
+ pc = sus%critical%critical_pressure%value/1e5
+ w = sus%critical%acentric_factor%value
+
+ tc(2) = 874.0
+ pc(2) = 6.8
+ w(2) = 1.52596
+
+ kij = 0
+ lij = 0
+
+ pr76 = PengRobinson76(tc, pc, w, kij, lij)
+ hdpr76 = set_hpr(tc, pc, w, kij, lij)
+
+ ! Copy PR76 into HSPR76
+ hspr76%components%tc = tc
+ hspr76%components%pc = pc
+ hspr76%components%w = w
+ hspr76%ac = pr76%ac
+ hspr76%b = pr76%b
+
+ associate(alpha => pr76%alpha)
+ select type(alpha)
+ type is (AlphaSoave)
+ hspr76%k = alpha%k
+ end select
+ end associate
+
+ hspr76%kij = kij
+ hspr76%lij = lij
+
+ n = [0.3, 0.7]
+ V = 1
+ T = 400
+
+ block
+ real(pr) :: dPdV, k, khs
+ do i=1,100
+ P = real(i, pr)
+ call volume(pr76, n, P, T, V, root_type="stable")
+ call pressure(pr76, n, V, T, P, dPdV)
+ k = -1/V * 1/dPdV
+
+ call volume(hspr76, n, P, T, V, root_type="stable")
+ call pressure(hspr76, n, V, T, P, dPdV)
+ khs = -1/V * 1/dPdV
+
+ print *, P, k, khs
+ end do
+ end block
+
+ P = 50
+ do i=1,99
+ n(1) = real(i)/100
+ n(2) = 1 - n(1)
+
+ eq = saturation_pressure(pr76, n, T=T, kind="bubble", P0=P)
+ P = eq%p
+ if (eq%iters < 1000) write(1, *) eq%x(1), eq%y(1), eq%p
+
+ eq = saturation_pressure(hspr76, n, T=T, kind="bubble", p0=eq%P)
+ if (eq%iters < 1000) write(2, *) eq%x(1), eq%y(1), eq%p
+ end do
+ call exit
+
+ T = 150
+ eq = saturation_pressure(pr76, n, T=T, kind="bubble")
+ print *, eq%iters, eq
+ env = pt_envelope_2ph(pr76, n, eq)
+
+ print *, size(env%points)
+ write(1, *) env
+
+ eq = saturation_pressure(hspr76, n, T=T, kind="bubble", p0=eq%P)
+ print *, eq%iters, eq
+
+ env = pt_envelope_2ph(hspr76, n, eq)
+ print *, size(env%points)
+ write(2, *) env
+ end subroutine main
+end module yaeos__HardSpheresCubicEoS
diff --git a/example/extra/pure_psat.f90 b/example/extra/pure_psat.f90
new file mode 100644
index 000000000..90ed05307
--- /dev/null
+++ b/example/extra/pure_psat.f90
@@ -0,0 +1,70 @@
+!! Program to calculate the vapor pressure of pure components
+!!
+
+module pure_psat
+ !! Module used to calculate the saturation pressure of pure components at
+ !! a given temperature.
+ use yaeos
+contains
+ real(pr) function Psat(eos, ncomp, T)
+ use yaeos__math, only: solve_system
+ class(ArModel), intent(in) :: eos
+ integer, intent(in) :: ncomp
+ real(pr), intent(in) :: T
+
+ real(pr) :: P1, P2
+ real(pr) :: f1, f2
+
+ real(pr) :: n(size(eos))
+
+ n = 0
+ n(ncomp) = 1
+
+ P1 = 0.5
+ P2 = 1
+
+ do while(abs(diff(P2)) > 1e-10)
+ f1 = diff(P1)
+ f2 = diff(P2)
+ Psat = (P1 * f2 - P2 * f1)/(f2 - f1)
+ P1 = P2
+ P2 = Psat
+ end do
+
+ contains
+ real(pr) function diff(P)
+ real(pr), intent(in) :: P
+ real(pr) :: V_l, V_v
+ real(pr) :: phi_v(size(eos)), phi_l(size(eos))
+ call eos%lnphi_pt(n, P, T, V=V_v, lnPhi=phi_v, root_type="vapor")
+ call eos%lnphi_pt(n, P, T, V=V_l, lnPhi=phi_l, root_type="liquid")
+ diff = phi_v(1) - phi_l(1)
+ end function
+ end function Psat
+end module
+
+program main
+ use yaeos
+ use forsus, only: Substance, forsus_default_dir, forsus_dir
+ use pure_psat, only: Psat
+ implicit none
+ integer, parameter :: nc=2
+ type(CubicEoS) :: eos
+ type(Substance) :: sus(nc)
+ real(pr) :: n(nc), T, f
+ integer :: i, j
+
+ forsus_dir = "build/dependencies/forsus/" // forsus_default_dir
+ sus(1) = Substance("water")
+ sus(2) = Substance("ethanol")
+ eos = SoaveRedlichKwong(&
+ sus%critical%critical_temperature%value, &
+ sus%critical%critical_pressure%value/1e5,&
+ sus%critical%acentric_factor%value &
+ )
+ T = 273.15_pr + 50
+ do i=273+90, nint(maxval(sus%critical%critical_temperature%value))
+ T = real(i,pr)
+ print *, T, (Psat(eos, j, T), j=1,nc)
+ end do
+end program main
diff --git a/example/extra/taperobinson.f90 b/example/extra/taperobinson.f90
index ed417849c..72dba51ad 100644
--- a/example/extra/taperobinson.f90
+++ b/example/extra/taperobinson.f90
@@ -16,6 +16,7 @@
MODULE TAPENADE_PR
USE YAEOS__CONSTANTS, ONLY : pr, r
USE YAEOS__TAPENADE_AR_API, ONLY : armodeltapenade
+ use yaeos__tapenade_interfaces
IMPLICIT NONE
type, extends(ArModelTapenade) :: TPR76
REAL(pr), ALLOCATABLE :: kij(:, :), lij(:, :)
@@ -794,12 +795,6 @@ SUBROUTINE AR_D_B(model, n, nb, nd, ndb, v, vb, vd, vdb, t, tb, td, &
INTEGER :: ad_from
INTEGER :: ad_to
INTEGER :: ad_to0
- EXTERNAL PUSHREAL8ARRAY
- EXTERNAL PUSHINTEGER4
- EXTERNAL PUSHREAL8
- EXTERNAL POPREAL8
- EXTERNAL POPINTEGER4
- EXTERNAL POPREAL8ARRAY
INTEGER :: arg12
LOGICAL, DIMENSION(SIZE(n)) :: mask1
LOGICAL, DIMENSION(SIZE(n)) :: mask2
diff --git a/example/tutorials/basics.f90 b/example/tutorials/basics.f90
index b83caa51d..0b6e2b653 100644
--- a/example/tutorials/basics.f90
+++ b/example/tutorials/basics.f90
@@ -32,10 +32,10 @@ program basics
n = [0.3, 0.7]
! Pressure calculation
- call pressure(model, n, v=2.5_pr, T=150._pr, P=P)
+ call model%pressure(n, v=2.5_pr, T=150._pr, P=P)
print *, "P: ", P
! Derivatives can also be calculated when included as optional arguments!
- call pressure(model, n, v=2.5_pr, T=150._pr, P=P, dPdV=dPdV)
+ call model%pressure(n, v=2.5_pr, T=150._pr, P=P, dPdV=dPdV)
print *, "dPdV: ", dPdV
end program basics
diff --git a/example/tutorials/cubic_eos.f90 b/example/tutorials/cubic_eos.f90
new file mode 100644
index 000000000..7b86c88c4
--- /dev/null
+++ b/example/tutorials/cubic_eos.f90
@@ -0,0 +1,66 @@
+!> We have seen that some cubic models are available in yaeos. But will show
+!> here how it is possible to make your own CubicEoS by choosing which piece
+!> of the model you want to use.
+!>
+!> This is just an example model and it is not intended to be used in real
+!> applications. It is just to show how to create a CubicEoS model.
+program main
+ use yaeos
+ integer, parameter :: nc = 2 !! Number of components
+ type(CubicEoS) :: eos !! The CubicEoS model
+
+ real(pr) :: tc(nc), pc(nc), w(nc) !! Critical constants
+ real(pr) :: kij(nc, nc), lij(nc, nc) !! Binary interaction parameters
+ character(len=50) :: name(nc) !! Name of the components
+
+ type(Substances) :: composition
+ !! All models should have their own composition
+ type(AlphaRKPR) :: alpha_function
+ !! The RKPR Alpha Function
+ type(QMR) :: mixrule
+ !! A Quadratic mixing rule (ClassicVdW)
+
+ integer :: i
+ real(pr) :: n(nc), V, P, T
+
+ ! First we define the components critical constants
+ Tc = [190._pr, 310._pr]
+ Pc = [14._pr, 30._pr ]
+ w = [0.001_pr, 0.03_pr]
+ name = ["Component 1", "Component 2"]
+ composition = Substances(name, Tc, Pc, w)
+
+
+ ! RKPR Alpha function uses a set of k parameters
+ alpha_function%k = [0.48_pr, 0.58_pr]
+
+ ! The mixrule
+ kij = 0
+ lij = 0
+ kij(1,2) = 0.1_pr
+ kij(2,1) = kij(1, 2)
+ mixrule = QMR(k=kij, l=lij)
+
+ ! We need to set up the model parameters
+ eos%ac = [0.042748_pr, 0.052748_pr]
+ eos%b = [0.005, 0.001]
+ eos%del1 = [0.1, 0.2]
+ eos%del2 = [0.4, 0.5]
+
+ ! We now add the before defined components and mixrule
+ eos%alpha = alpha_function
+ eos%components = composition
+ eos%mixrule = mixrule
+
+
+ T = 50
+ n = [0.5, 0.5]
+ do i=1,100
+ V = real(i, pr)/100
+ call eos%pressure(n, V, T, P)
+ print *, V, P
+
+ end do
+
+
+end program
\ No newline at end of file
diff --git a/example/tutorials/huron_vidal.f90 b/example/tutorials/huron_vidal.f90
index 34639455a..a3acc00b1 100644
--- a/example/tutorials/huron_vidal.f90
+++ b/example/tutorials/huron_vidal.f90
@@ -10,7 +10,6 @@ program main
implicit none
integer, parameter :: nc = 2
-
real(pr) :: n(nc)
real(pr) :: a(nc, nc), b(nc, nc), c(nc, nc) ! NRTL parameters
@@ -26,16 +25,14 @@ program main
type(Substance) :: sus(nc)
- integer :: i, j
-
molecules(1)%groups_ids = [16]
molecules(1)%number_of_groups = [1]
molecules(2)%groups_ids = [1, 2, 14]
molecules(2)%number_of_groups = [1, 1, 1]
-
forsus_dir = "./build/dependencies/forsus/data/json"
+
sus(1) = Substance("water")
sus(2) = Substance("ethanol")
@@ -46,50 +43,34 @@ program main
a = 0; b = 0; c = 0
! NRTL model parameters
- a(1, 2) = 3.458
- a(2, 1) = -0.801
-
- b(1, 2) = -586.1
- b(2, 1) = 246.2
-
- c(1, 2) = 0.3
- c(2, 1) = 0.3
-
+ a(1, 2) = 3.458; a(2, 1) = -0.801
+ b(1, 2) = -586.1; b(2, 1) = 246.2
+ c(1, 2) = 0.3; c(2, 1) = 0.3
+
ge_model = NRTL(a, b, c)
- n = [0.2, 0.8]
+
+ ! Moles vector
n = [0.9, 0.1]
- ! n = [0.8, 0.2]
+
! Define the model to be SRK
model = SoaveRedlichKwong(tc, pc, w)
call phase_envel(1)
- ! mixrule = MHV(ge_model, model%b)
- ! mixrule%q = -0.593_pr
- ! deallocate (model%mixrule)
- ! model%mixrule = mixrule
- ! call phase_envel(2)
-
- ! mixrule = MHV(ge_model, model%b)
- ! mixrule%q = -0.593_pr
- ! deallocate (model%mixrule)
- ! model%mixrule = mixrule
- ! call phase_envel(2)
-
- ! ge_model_unifac = setup_unifac(molecules)
+ mixrule = MHV(ge=ge_model, q=-0.593_pr, b=model%b)
+
+ ! SoaveRedlichKwong uses by default QMR mixing rules.
+ ! We will change it to Huron-Vidal
+ deallocate(model%mixrule)
+ model%mixrule = mixrule
+ call phase_envel(2)
+
+ ge_model_unifac = setup_unifac(molecules)
- ! mixrule = MHV(ge_model_unifac, model%b)
- ! mixrule%q = -0.593_pr
- ! deallocate (model%mixrule)
- ! model%mixrule = mixrule
- ! call phase_envel(3)
-
- do i=1,99
- n(2) = real(i,pr)/100
- n(1) = 1 - n(2)
- sat = saturation_pressure(model, n, T=473._pr, kind="bubble")
- write (*, *) sat
- end do
+ mixrule = MHV(ge=ge_model_unifac, q=-0.593_pr, b=model%b)
+ deallocate (model%mixrule)
+ model%mixrule = mixrule
+ call phase_envel(3)
contains
@@ -99,7 +80,7 @@ subroutine phase_envel(fu)
type(EquilibriaState) :: sat
type(PTEnvel2) :: env
- sat = saturation_pressure(model, n, T=250._pr, kind="bubble", y0=[0.1_pr, 0.9_pr])
+ sat = saturation_pressure(model, n, T=300._pr, kind="bubble")
write (*, *) sat, sat%iters
env = pt_envelope_2ph(model, n, sat, specified_variable_0=nc + 1, delta_0=0.001_pr)
diff --git a/example/tutorials/new_alpha_function.f90 b/example/tutorials/new_alpha_function.f90
index 8ef43e024..c222936c9 100644
--- a/example/tutorials/new_alpha_function.f90
+++ b/example/tutorials/new_alpha_function.f90
@@ -45,7 +45,6 @@ end module alpha_mathias_copeman
program new_alpha_example
use yaeos__example_tools, only: methane_butane_pr76
- use yaeos, only: fugacity_vt, pressure
use yaeos, only: pr, PengRobinson76, CubicEoS, QMR
use alpha_mathias_copeman, only: MathiasCopeman
type(CubicEoS) :: eos
@@ -67,14 +66,14 @@ program new_alpha_example
v = 2
t = 150
- call pressure(eos, n, V, T, P=P)
+ call eos%pressure(n, V, T, P=P)
print *, "Peng-Robinson76:", P
! Replace the original alpha
deallocate(eos%alpha) ! Remove the already defined alpha
eos%alpha = alpha ! assign the new defined alpha
- call pressure(eos, n, V, T, P=P)
+ call eos%pressure(n, V, T, P=P)
print *, "Peng-Robinson76-MC:", P
diff --git a/fpm.toml b/fpm.toml
index 1a361a51b..d1906b24b 100644
--- a/fpm.toml
+++ b/fpm.toml
@@ -1,5 +1,5 @@
name = "yaeos"
-version = "0.3.0"
+version = "1.0.0"
license = "MPL"
author = "Federico E. Benelli"
maintainer = "federico.benelli@mi.unc.edu.ar"
@@ -17,22 +17,22 @@ library = true
[fortran]
implicit-typing = false
-implicit-external = true
+implicit-external = false
source-form = "free"
[dependencies]
stdlib = "*"
forbear = {git="https://github.com/szaghi/forbear"}
json-fortran = {git="https://github.com/jacobwilliams/json-fortran"}
+nlopt-f = {git="https://github.com/grimme-lab/nlopt-f"}
forsus = {git="https://github.com/ipqa-research/forsus"}
-nlopt-f.git = "https://github.com/grimme-lab/nlopt-f"
+fortime = { git = "https://github.com/gha3mi/fortime.git" }
[dev-dependencies]
test-drive = {git = "https://github.com/fortran-lang/test-drive"}
-
[[example]]
-name = "benchmarks"
+name = "demo"
source-dir = "example/extra"
main = "demo.f90"
@@ -61,4 +61,13 @@ name = "huron_vidal"
source-dir = "example/tutorials"
main = "huron_vidal.f90"
+[[example]]
+name = "pure_psat"
+source-dir = "example/extra"
+main = "pure_psat.f90"
+
+[[example]]
+name = "cubic_eos"
+source-dir = "example/tutorials"
+main = "cubic_eos.f90"
diff --git a/media/PTEnvel2.png b/media/PTEnvel2.png
new file mode 100644
index 000000000..6c67366cb
Binary files /dev/null and b/media/PTEnvel2.png differ
diff --git a/python/MANIFEST.in b/python/MANIFEST.in
new file mode 100644
index 000000000..ac5aca89d
--- /dev/null
+++ b/python/MANIFEST.in
@@ -0,0 +1,19 @@
+include LICENCE
+include README.md
+include CONTRIBUTING.md
+include requirements.txt
+include pyproject.toml
+
+recursive-include yaeos *.py
+include yaeos/compiled_module/*.so
+
+exclude tox.ini
+exclude requirements-dev.txt
+exclude _build
+exclude __pycache__
+exclude compiled_flag
+
+recursive-exclude tmp_dir *
+recursive-exclude dist *
+recursive-exclude tests *
+recursive-exclude docs *
diff --git a/python/README.md b/python/README.md
new file mode 100644
index 000000000..fb9682a6a
--- /dev/null
+++ b/python/README.md
@@ -0,0 +1,36 @@
+# yaeos Python bindings
+THIS IS A WIP SO THE API WILL DRASTRICALLY CHANGE WITH TIME
+
+Set of Python bindings to call `yaeos` functions and models.
+
+Editable instalation
+
+```
+cd python
+pip install -e .
+python setup.py build_fortran_editable
+```
+
+If you want to install on your environment instead
+
+```
+pip install .
+```
+
+To check if the instalation worked correctly:
+
+```python
+from yaeos import PengRobinson76, QMR
+
+import numpy as np
+
+mr = QMR(np.zeros((2,2)), np.zeros((2,2)))
+
+model = PengRobinson76(np.array([320, 375]), np.array([30, 45]), np.array([0.0123, 0.045]), mr)
+
+model.fugacity(np.array([5.0, 4.0]), 2.0, 303.15)
+```
+
+```
+{'ln_phi': array([2.61640775, 2.49331419]), 'dt': None, 'dp': None, 'dn': None}
+```
\ No newline at end of file
diff --git a/python/docs/tutorials/tutorial.ipynb b/python/docs/tutorials/tutorial.ipynb
new file mode 100644
index 000000000..f9945f998
--- /dev/null
+++ b/python/docs/tutorials/tutorial.ipynb
@@ -0,0 +1,466 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "3a2bdbde-7f69-4b8f-ad42-4eb89c90167f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import yaeos\n",
+ "from yaeos import PengRobinson76, QMR\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "85ff95ba-7a1a-4ca3-bec1-3c5bb50325ea",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'ln_phi': array([-0.18662712, -0.16554916]),\n",
+ " 'dt': None,\n",
+ " 'dp': None,\n",
+ " 'dn': array([[-0.00186921, 0.00934604],\n",
+ " [ 0.00934604, -0.04673019]])}"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Number of components, for easier definition\n",
+ "nc = 2\n",
+ "\n",
+ "# kij and lij matrices\n",
+ "k12 = 0.1\n",
+ "lij = kij = np.zeros((nc,nc))\n",
+ "kij[0,1] = kij[1,0] = k12\n",
+ "\n",
+ "mixrule = QMR(kij, lij)\n",
+ "\n",
+ "# Critical constants\n",
+ "Tc = [320, 375]\n",
+ "Pc = [30, 45]\n",
+ "w = [0.0123, 0.045]\n",
+ "\n",
+ "model = PengRobinson76(Tc, Pc, w, mixrule)\n",
+ "\n",
+ "\n",
+ "n = [1.0, 0.2]\n",
+ "model.fugacity(n, v=2.0, t=303.15, dn=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "cf0a8e95",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n = [0.4, 0.6]\n",
+ "Tc = [190.564, 425.12]\n",
+ "Pc = [45.99, 37.96]\n",
+ "w = [0.0115478, 0.200164]\n",
+ "\n",
+ "lij = kij = np.zeros((nc,nc))\n",
+ "mixrule = QMR(kij, lij)\n",
+ "model = PengRobinson76(Tc, Pc, w, mixrule)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "5e06f2a9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 530 ms, sys: 0 ns, total: 530 ms\n",
+ "Wall time: 539 ms\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%time\n",
+ "P, T = 60.0, 294.0\n",
+ "\n",
+ "ts = np.linspace(200, 400, 50)\n",
+ "ps = np.linspace(30, 100, 50)\n",
+ "betas = []\n",
+ "\n",
+ "t = []\n",
+ "p = []\n",
+ "\n",
+ "for T in ts:\n",
+ " for P in ps:\n",
+ " flash = model.flash_pt(n, P, T)\n",
+ " x = flash[\"x\"]\n",
+ " y = flash[\"y\"]\n",
+ " P = flash[\"P\"]\n",
+ " T = flash[\"T\"]\n",
+ " beta = flash[\"beta\"]\n",
+ " t.append(T)\n",
+ " p.append(P)\n",
+ " betas.append(beta)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "7c42b4fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9d6AkSXXl/YvIzPJVr5637X33dE+PZ2A8wzgEg5G0rKRduRXSOu1qpdXCSsgjhKTlkxeLJBa0QqwsEkgCGawAMcB4zNie7mnfz9tymRnfH1kmqyozogYeTc9MHXjT71XdijgZFRlxM+LEvUIppeijjz766KOPPvq4hCC/2QT66KOPPvroo48+OtF3UProo48++uijj0sOfQeljz766KOPPvq45NB3UProo48++uijj0sOfQeljz766KOPPvq45NB3UProo48++uijj0sOfQeljz766KOPPvq45NB3UProo48++uijj0sO9jebwNcC3/c5c+YM+XweIcQ3m04fffTRRx999NEDlFKsrq4yNTWFlPo1kuelg3LmzBm2bNnyzabRRx999NFHH318DTh58iQzMzNam+elg5LP54HgAguFwjeZTR999NFHH3300QtWVlbYsmVLcx7X4XnpoDS2dQqFQt9B6aOPPvroo4/nGXqRZ/RFsn300UcfffTRxyWHvoPSRx999NFHH31ccug7KH300UcfffTRxyWHvoPSRx999NFHH31ccug7KH300UcfffTRxyWHvoPSRx999NFHH31ccug7KH300UcfffTRxyWHvoPSRx999NFHH31ccnheBmrr45uH9ZUNHvjHRyivV9h6cIa9V+3sCrhT8z0+N3uM+co6E+kC14xsxxLtvrBSiocWTnFibZ68k+KlY7tI205XfU+vzPLo0lkS0uIlo9sZSma7bM6XVvnC3Ak85XN0aIZtuaEum7Vahc9eOMaGW2VnfoTDg1ORvP/lwjPMV9YZT+e5bjSa94MLpzixtkDeSfKyHnhfN7Kd4VQ37wulVT5f53350DTbc8NfM+/PzT7DXHmdsVSO60Z3YMvo9j5e5/3SsZ1k7ERXfcdW5/jS4hksIbludDsjqVyXzWx5jc/PHsdTPocHp9mR7+a97lb57IWnWXer7MgNc2Rwuou36/vcN/sMs+VVRlP5WN6PLJ7i+No8WTvJ9WM7ydrJrvqe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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "plt.scatter(t, p, c=betas)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "73924e0d",
+ "metadata": {},
+ "source": [
+ "## Modified Huron-Vidal MixingRule"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "a0a29755",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 3.62 s, sys: 0 ns, total: 3.62 s\n",
+ "Wall time: 3.63 s\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%%time\n",
+ "from yaeos import NRTL, MHV, PengRobinson76, yaeos_c, QMR\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "nc = 2\n",
+ "tc = [647.14, 513.92]\n",
+ "pc = [220.64, 61.48]\n",
+ "w = [0.344, 0.649]\n",
+ "\n",
+ "a = [[0, 3.458], [-0.801, 0]]\n",
+ "b = [[0, -586.1], [246.2, 0]]\n",
+ "c = [[0, 0.3], [0.3, 0]]\n",
+ "\n",
+ "b = np.array(b)\n",
+ "\n",
+ "ge_model = NRTL(a, b, c)\n",
+ "mixrule = MHV(ge_model, q=-0.53)\n",
+ "\n",
+ "null_mixing = QMR(np.zeros((nc,nc)), np.zeros((nc,nc)))\n",
+ "\n",
+ "model_stock = PengRobinson76(tc, pc, w, null_mixing)\n",
+ "model_mhv = PengRobinson76(tc, pc, w, mixrule)\n",
+ "\n",
+ "colors = [\"red\", \"green\", \"blue\", \"orange\", \"black\"]\n",
+ "ts = np.linspace(50+273, 200+273, 9)\n",
+ "import time\n",
+ "for i, T in enumerate(ts):\n",
+ " i=4\n",
+ " xs = np.linspace(0.001, 0.999, 100)\n",
+ " ys = []\n",
+ " ps = []\n",
+ "\n",
+ " st = time.time()\n",
+ " \n",
+ " for x1 in xs:\n",
+ " x = [x1, 1-x1]\n",
+ " sat = model_mhv.saturation_pressure(x, T, \"bubble\")\n",
+ " p, y = sat[\"P\"], sat[\"y\"]\n",
+ " ps.append(p)\n",
+ " ys.append(y[0])\n",
+ "\n",
+ " plt.plot(xs, ps, color=colors[i])\n",
+ " plt.plot(ys, ps, color=colors[i])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9ba9be74",
+ "metadata": {},
+ "source": [
+ "# Phase envelope tracing"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "bac65808",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import yaeos\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "import chemicals\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "9de1de8b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "names = [\"methane\", \"n-decane\", \"water\", \"hexatriacontane\"]\n",
+ "chems = []\n",
+ "\n",
+ "Tc = []\n",
+ "Pc = []\n",
+ "w = []\n",
+ "for c in names:\n",
+ " chem = chemicals.CAS_from_any(c)\n",
+ " Tc.append(chemicals.Tc(chem))\n",
+ " Pc.append(chemicals.Pc(chem)/1e5)\n",
+ " w.append(chemicals.acentric.omega(chem))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "21c0ea1a",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "49e6c6e5908c42529dfdd26ca2572480",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "image/png": "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",
+ "text/html": [
+ "\n",
+ " \n",
+ "
\n",
+ " Figure 11\n",
+ "
\n",
+ "

\n",
+ "
\n",
+ " "
+ ],
+ "text/plain": [
+ "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "z = np.ones(len(names))\n",
+ "z = z/z.sum()\n",
+ "\n",
+ "models = [\n",
+ " yaeos.PengRobinson76,\n",
+ " yaeos.PengRobinson78,\n",
+ " yaeos.SoaveRedlichKwong,\n",
+ "]\n",
+ "\n",
+ "for m in models:\n",
+ " model = m(Tc, Pc, w)\n",
+ " T, P, Tcs, Pcs = yaeos.yaeos_c.pt2_phase_envelope(model.id, z, kind=\"dew\", t0=150, p0=0.01)\n",
+ " plt.plot(T, P, label=model.name)\n",
+ " plt.scatter(Tcs, Pcs, label=model.name + \"-CP\")\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "id": "da909167",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from ipywidgets import interact, fixed\n",
+ "import ipywidgets as widgets"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "61e58514",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "3544535a0a484cc29759fd8a07a81145",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "interactive(children=(Dropdown(description='i', options=(0, 1, 2, 3), value=0), FloatSlider(value=0.4901, desc…"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "f2291cda697b49cf8c127fff2371992d",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "image/png": "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iXfcnDlzSElJYfjw4cTHx9OqVSuee+45vXHmPKdLwCIiJlTmcJH8+HyfrHvruHRCAv746ccwDBYvXsz8+fMZNGgQU6ZMITMzk1q1agGey5VfffUVU6ZM4bnnngPA4XDw1ltv0ahRIwBGjBjBuHHjvMt87bXXGDt2LNdddx0Ar7/++knvXZs7dy5hYWE4nU7sdjtWq5XXX38dgJKSEt58802mTp1K3759AXj77bdZuHAh7777LqNHj/Yu54knnqBXr14ATJs2jTp16jBr1ixuuOGGk26z2+1m6tSphIeHA3DLLbewePFinn32WbKysnA6nfTv35969eoB0Lp1a+93X3jhBcaMGcNNN90EeMLukiVLeOWVV5g8ebJ3vlGjRtGvXz8AnnrqKVq2bMnu3btp3rx5pVrKy8uZPn06Dz/8cKXxe/bs4euvv2bw4MHMmzeP3bt3c/fdd+NwOHjiiSdOul3iewqAIiJyXjsevhwOB263m5tvvpmBAwcydepUmjZtWmleu91ObGys93NISIg3/AEkJiaSm5sLQEFBATk5OXTu3Nk73Waz0aFDB9xud6XlXnbZZbz55puUlJTw8ssv4+fnx4ABAwBPK53D4SA1NdU7v7+/P507d2bbtm2VlpOSkuL9e0xMDM2aNTthnl+qX7++N/z9uv62bdvSs2dPWrduTXp6Or1792bgwIFER0dTWFjIoUOHKtUEkJqayoYNGyqNa9OmTaXlA+Tm5p4QAGfNmkVRURFDhgypNN7tdhMXF8e//vUv7+938OBBnn/+eQXA85gCoIiICQX729g6Lt1n6/4jjoevgIAAatWqhZ+fHx999BE2m421a9dis1VeXlhYmPfv/v7+laZZLJY/dQk6NDSUxo0bA5573tq2bcu7775b6V64c+Fk9R8PpzabjYULF7JixQoWLFjAa6+9xiOPPMKqVasqheA/so7jrwj8dQAGz+XfK6+8kvj4+ErjExMT8ff3r7QfWrRoQXZ2NhUVFXoX73lK9wCKiJiQxWIhJMDPJ8MffQ/x8fBVt25d/Pw87Rbt27fH5XKRm5tL48aNKw0JCQmntdzIyEji4+MrPazhcrlYt27db37ParXy97//nUcffZSysjIaNWpEQEAAy5cv987jcDhYs2YNycnJlb77/fffe/+el5fHzp07adGixWnVezIWi4XU1FSeeuopfvzxRwICApg1axYRERHUqlWrUk3geQjl1zWdjoyMDJYsWXLSwJuamsru3bsrhcadO3eSmJio8HceUwAUEZFqp2nTpgwePJhbb72Vzz77jIyMDFavXs348eP573//e9rLueeeexg/fjyff/45O3bsYOTIkeTl5f1uSL3++uux2WxMnjyZ0NBQhg0bxujRo/nqq6/YunUrd9xxB6WlpScEpnHjxrF48WI2b97M0KFDqVGjxglPHJ+uVatW8dxzz/HDDz+QmZnJZ599xuHDh72BcvTo0UycOJGPPvqIHTt28PDDD7N+/XpGjhz5h9f13nvvkZiY6L3H8ZeGDRvG0aNHGTlyJDt37uS///0vzz33HMOHD/9T2yVVQ5eARUSkWpoyZQrPPPMMDz74IAcPHqRGjRp07dqVK6+88rSXMWbMGLKzs7n11lux2WzceeedpKenn3BZ+df8/PwYMWIEkyZNYtiwYUyYMAG3280tt9xCUVERHTt2ZP78+URHR1f63oQJExg5ciS7du2iXbt2fPHFF3+6lSwiIoJvvvmGV155hcLCQurVq8eLL77oDWn33nsvBQUFPPjgg+Tm5pKcnMycOXNo0qTJH1rP8QdRhg4detLfJSkpifnz53P//ffTpk0bateuzciRIxkzZsyf2i6pGhbjTJ/HN7HCwkIiIyMpKCggIiLC1+WIiJxUeXk5GRkZNGjQgKCgIF+Xc15zu920aNGCG264gaefftrX5cgZ+K3jXudvtQCKiIiJ7du3jwULFtC9e3fsdjuvv/46GRkZ3Hzzzb4uTeSc0j2AIiJiWlarlalTp9KpUydSU1PZtGkTixYtOqMHM0SqA7UAioiIaSUlJZ3wpKyIGagFUERERMRkFABFRERETKZaBsAnn3wSi8VSafjlK2vKy8sZPnw4sbGxhIWFMWDAAHJyciotIzMzk379+hESEkJcXByjR48+5cuvRURERC4k1fYewJYtW7Jo0SLv5+O9wwPcf//9/Pe//+Xjjz8mMjKSESNG0L9/f+99Hi6Xi379+pGQkMCKFSvIysri1ltvxd/f3/sCcREREZELVbUNgH5+fid93U9BQQHvvvsuM2bM4PLLLwc8nYW2aNGC77//nq5du7JgwQK2bt3KokWLiI+Pp127djz99NOMGTOGJ598Uq+uERERkQtatbwEDLBr1y5q1apFw4YNGTx4MJmZmQCsXbsWh8NBWlqad97mzZtTt25dVq5cCcDKlStp3bp1pRdap6enU1hYyJYtW065TrvdTmFhYaVBREREpLqplgGwS5cuTJ06la+++oo333yTjIwMLrnkEoqKisjOziYgIICoqKhK34mPjyc7OxuA7OzsSuHv+PTj005l/PjxREZGeoekpKSzu2EiInJBWrp0KRaLhfz8/FPOM3Xq1BPOXSLnSrUMgH379uX666+nTZs2pKenM2/ePPLz8/nPf/5zTtc7duxYCgoKvMP+/fvP6fpERMxu6NCh3of9AgICaNy4MePGjavSh/Z+WYO/vz8NGjTgoYceory8/Kyu58Ybb2Tnzp1ndZln6mQPXVosFkJDQyvN98orr9CsWTOCg4NJSkri/vvvP+u/j5xd1fYewF+KioqiadOm7N69m169elFRUUF+fn6lf0nl5OR47xlMSEhg9erVlZZx/Cnhk91XeFxgYCCBgYFnfwNEROSU+vTpw5QpU7Db7cybN4/hw4fj7+/P2LFjq7wGh8PB2rVrGTJkCBaLhYkTJ561dQQHBxMcHHzWlnc2jBo1irvuuqvSuJ49e9KpUyfv5xkzZvDwww/z3nvvcfHFF7Nz505vaH7ppZequmQ5TdWyBfDXiouL+emnn0hMTKRDhw74+/uzePFi7/QdO3aQmZlJSkoKACkpKWzatInc3FzvPAsXLiQiIoLk5OQqr19ERE4tMDCQhIQE6tWrx7Bhw0hLS2POnDnY7XZGjRpF7dq1CQ0NpUuXLixdutT7veOXVOfPn0+LFi0ICwujT58+ZGVleedxOp3ce++9REVFERsby5gxYxgyZAjXXnvtSWtISkri2muvJS0tjYULF3qn2+127r33XuLi4ggKCqJbt26sWbPmhG1Zvnw5bdq0ISgoiK5du7J58+YT6j3uySefpF27drz//vvUr1+fyMhIbrrpJoqKirzzfPLJJ7Ru3Zrg4GBiY2NJS0ujpKQEALfbzbhx46hTpw6BgYG0a9eOr776yvvdvXv3YrFY+Oyzz7jssssICQmhbdu23vvlAcLCwkhISPAOOTk5bN26ldtvv907z4oVK0hNTeXmm2+mfv369O7dm0GDBp3Q0CLnl2oZAEeNGsWyZcvYu3cvK1as4LrrrsNmszFo0CAiIyO5/fbbeeCBB1iyZAlr167ltttuIyUlha5duwLQu3dvkpOTueWWW9iwYQPz58/n0UcfZfjw4WrhExFzMAyoKPHNYBhnVHpwcDAVFRWMGDGClStXMnPmTDZu3Mj1119Pnz592LVrl3fe0tJSXnjhBd5//32++eYbMjMzGTVqlHf6xIkTmT59OlOmTGH58uUUFhYye/bs31z/5s2bWbFiRaUeIx566CE+/fRTpk2bxrp162jcuDHp6ekcPXq00ndHjx7Niy++yJo1a6hZsyZXXXUVDofjlOv66aefmD17NnPnzmXu3LksW7aMCRMmAJCVlcWgQYP4y1/+wrZt21i6dCn9+/fHOPb7vvrqq7z44ou88MILbNy4kfT0dK6++upKvw/AI488wqhRo1i/fj1NmzZl0KBBp7zE/s4779C0aVMuueQS77iLL76YtWvXegPfnj17mDdvHldcccVv/o7iY0Y1dOONNxqJiYlGQECAUbt2bePGG280du/e7Z1eVlZm3H333UZ0dLQREhJiXHfddUZWVlalZezdu9fo27evERwcbNSoUcN48MEHDYfD8YfqKCgoMACjoKDgrGyXiMi5UFZWZmzdutUoKyv730h7sWE8EeGbwV582rUPGTLEuOaaawzDMAy3220sXLjQCAwMNIYOHWrYbDbj4MGDlebv2bOnMXbsWMMwDGPKlCkGUOn8MHnyZCM+Pt77OT4+3nj++ee9n51Op1G3bl3vOo/XYLPZjNDQUCMwMNAADKvVanzyySeGYRhGcXGx4e/vb0yfPt37nYqKCqNWrVrGpEmTDMMwjCVLlhiAMXPmTO88R44cMYKDg42PPvrIW29kZKR3+hNPPGGEhIQYhYWF3nGjR482unTpYhiGYaxdu9YAjL179570t6tVq5bx7LPPVhrXqVMn4+677zYMwzAyMjIMwHjnnXe807ds2WIAxrZt205YXllZmREdHW1MnDjxhGmvvvqq4e/vb/j5+RmAcdddd520pqp00uP+GJ2/DaNa3gM4c+bM35weFBTE5MmTmTx58innqVevHvPmzTvbpYmIyFk2d+5cwsLCcDgcuN1ubr75ZgYOHMjUqVNp2rRppXntdjuxsbHezyEhITRq1Mj7OTEx0Xv7T0FBATk5OXTu3Nk73Waz0aFDB9xud6XlXnbZZbz55puUlJTw8ssv4+fnx4ABAwBPK53D4SA1NdU7v7+/P507d2bbtm2VlnP8ViSAmJgYmjVrdsI8v1S/fn3Cw8NPWn/btm3p2bMnrVu3Jj09nd69ezNw4ECio6MpLCzk0KFDlWoCSE1NZcOGDZXGtWnTptLyAXJzcyu9YQtg1qxZFBUVMWTIkErjly5dynPPPccbb7xBly5d2L17NyNHjuTpp5/mscceO+W2iW9VywAoIiJnyD8E/n7Id+v+A46Hr4CAAGrVqoWfnx8fffQRNpuNtWvXYrPZKs0fFhb2v1X5+1eaZrFYvJdI/4jQ0FAaN24MwHvvvUfbtm159913K90Ldy6crP7j4dRms7Fw4UJWrFjBggULeO2113jkkUdYtWpVpRD8R9ZhsVgATgjA4Ln8e+WVV57Qjdpjjz3GLbfcwl//+lcAWrduTUlJCXfeeSePPPIIVmu1vNvsgqe9IiJiRhYLBIT6ZjgWMk7X8fBVt25d72s/27dvj8vlIjc3l8aNG1cafqs3h1+KjIwkPj6+0sMaLpeLdevW/eb3rFYrf//733n00UcpKyujUaNGBAQEeF83CuBwOFizZs0JDxZ+//333r/n5eWxc+dOWrRocVr1nozFYiE1NZWnnnqKH3/8kYCAAGbNmkVERAS1atWqVBN4HkL5Mw87ZmRksGTJkpMG3tLS0hNC3vFQ/mfCtlQNtQCKiEi107RpUwYPHsytt97Kiy++SPv27Tl8+DCLFy+mTZs29OvX77SWc8899zB+/HgaN25M8+bNee2118jLy/O2hJ3K9ddfz+jRo5k8eTKjRo1i2LBhjB49mpiYGOrWrcukSZMoLS09ITCNGzeO2NhY4uPjeeSRR6hRo8YJTxyfrlWrVrF48WJ69+5NXFwcq1at4vDhw95AOXr0aJ544gkaNWpEu3btmDJlCuvXr2f69Ol/eF3vvfceiYmJ9O3b94RpV111FS+99BLt27f3XgJ+7LHHuOqqq05onZXzhwKgiIhUS1OmTOGZZ57hwQcf5ODBg9SoUYOuXbty5ZVXnvYyxowZQ3Z2Nrfeeis2m40777yT9PT03w0ufn5+jBgxgkmTJjFs2DAmTJiA2+3mlltuoaioiI4dOzJ//nyio6MrfW/ChAmMHDmSXbt20a5dO7744os//f75iIgIvvnmG1555RUKCwupV68eL774ojek3XvvvRQUFPDggw+Sm5tLcnIyc+bMoUmTJn9oPW63m6lTpzJ06NCT/i6PPvooFouFRx99lIMHD3qfbn722Wf/1HZJ1bAYap/90woLC4mMjKSgoICIiAhflyMiclLl5eVkZGTQoEEDgoKCfF3Oec3tdtOiRQtuuOEGnn76aV+XI2fgt457nb/VAigiIia2b98+FixYQPfu3bHb7bz++utkZGRw8803+7o0kXNKD4GIiIhpWa1Wpk6dSqdOnUhNTWXTpk0sWrTojB7MEKkO1AIoIiKmlZSUdMKTsiJmoBZAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAERGR88TQoUN/993APXr04L777vN+rl+/Pq+88sppLX/q1KlERUX96frkwqEAKCIi57XDhw8zbNgw6tatS2BgIAkJCaSnp593/fdZLBbvEBERQadOnfj888/P+XrXrFnDnXfeedaW9+STT9KuXbtK47799luioqK477770BtkLwwKgCIicl4bMGAAP/74I9OmTWPnzp3MmTOHHj16cOTIEV+XdoIpU6aQlZXFDz/8QGpqKgMHDmTTpk3ndJ01a9YkJCTknC3/v//9L+np6TzwwAO88sorWCyWc7YuqToKgCIict7Kz8/n22+/ZeLEiVx22WXUq1ePzp07M3bsWK6++moAMjMzueaaawgLCyMiIoIbbriBnJwc7zJ++uknrrnmGuLj4wkLC6NTp04sWrTIO/3vf/87Xbp0OWHdbdu2Zdy4cd7P77zzDi1atCAoKIjmzZvzxhtvnPCdqKgoEhISaNq0KU8//TROp5MlS5Z4p+/fv58bbriBqKgoYmJiuOaaa9i7d+8pt7+kpIRbb72VsLAwEhMTefHFF0+Y59eXgPPz8/nb3/5GfHw8QUFBtGrVirlz51b6zvz582nRogVhYWH06dOHrKysk65/xowZ9O/fn0mTJvH4448DsHnzZqxWK4cPHwbg6NGjWK1WbrrpJu/3nnnmGbp16+b9vGzZMjp37kxgYCCJiYk8/PDDOJ1O7/QePXpw77338tBDDxETE0NCQgJPPvlkpVq2b99Ot27dCAoKIjk5mUWLFmGxWJg9e/Ypfz85NQVAERETMgyDUkepT4Y/cgkxLCyMsLAwZs+ejd1uP2G62+3mmmuu4ejRoyxbtoyFCxeyZ88ebrzxRu88xcXFXHHFFSxevJgff/yRPn36cNVVV5GZmQnA4MGDWb16NT/99JP3O1u2bGHjxo3cfPPNAEyfPp3HH3+cZ599lm3btvHcc8/x2GOPMW3atJPW7XQ6effddwEICAgAwOFwkJ6eTnh4ON9++y3Lly/3BrCKioqTLmf06NEsW7aMzz//nAULFrB06VLWrVt3yt/L7XbTt29fli9fzgcffMDWrVuZMGECNpvNO09paSkvvPAC77//Pt988w2ZmZmMGjXqhGVNnjyZ2267jffee48RI0Z4x7ds2ZLY2FiWLVsGeC4P//IzeAJfjx49ADh48CBXXHEFnTp1YsOGDbz55pu8++67PPPMM5XWN23aNEJDQ1m1ahWTJk1i3LhxLFy4EACXy8W1115LSEgIq1at4l//+hePPPLIKX8H+X16F7CIiAmVOcvoMuPEVq+qsOrmVYT4n94lSz8/P6ZOncodd9zBW2+9xUUXXUT37t256aabaNOmDYsXL2bTpk1kZGSQlJQEwL///W9atmzJmjVr6NSpE23btqVt27beZT799NPMmjWLOXPmMGLECFq2bEnbtm2ZMWMGjz32GOAJfF26dKFx48YAPPHEE7z44ov0798fgAYNGrB161b++c9/MmTIEO+yBw0ahM1mo6ysDLfbTf369bnhhhsA+Oijj3C73bzzzjvey6hTpkwhKiqKpUuX0rt370rbXlxczLvvvssHH3xAz549AU9IqlOnzil/r0WLFrF69Wq2bdtG06ZNAWjYsGGleRwOB2+99RaNGjUCYMSIEZVaOgG2bdvGiBEjePfddxk8eHClaRaLhUsvvZSlS5cycOBAli5dym233cY777zD9u3badSoEStWrOChhx4C4I033iApKYnXX38di8VC8+bNOXToEGPGjOHxxx/HavW0RbVp04YnnngCgCZNmvD666+zePFievXqxcKFC/npp59YunQpCQkJADz77LP06tXrlL+F/Da1AIqIyHltwIABHDp0iDlz5tCnTx+WLl3KRRddxNSpU9m2bRtJSUne8AeQnJxMVFQU27ZtAzxBatSoUbRo0YKoqCjCwsLYtm2btwUQPK2AM2bMADytox9++KE3+JSUlPDTTz9x++23e1skw8LCeOaZZyq1GgK8/PLLrF+/ni+//JLk5GTeeecdYmJiANiwYQO7d+8mPDzcu4yYmBjKy8tPWA54Ll1XVFRUujwdExNDs2bNTvlbrV+/njp16njD38mEhIR4wx9AYmIiubm5leapU6cOF110Ec8///xJLw93796dpUuXAp7Wvssvv9wbCtesWYPD4SA1NRXwhMmUlJRK9w6mpqZSXFzMgQMHvOPatGlTaR2/rGvHjh0kJSV5wx9A586dT7mN8vvUAigiYkLBfsGsunmVz9b9RwUFBdGrVy969erFY489xl//+leeeOIJHnzwwd/97qhRo1i4cCEvvPACjRs3Jjg4mIEDB1a67Dpo0CDGjBnDunXrKCsrY//+/d7LyMXFxQC8/fbbJ9wr+MtLqwAJCQk0btyYxo0bM2XKFK644gq2bt1KXFwcxcXFdOjQgenTp59QY82aNf/wb3IywcG//9v6+/tX+myxWE64LB8eHs6iRYvo1asXl112GUuWLCExMdE7/XhXNLt27WLr1q1069aN7du3s3TpUvLy8ujYseMffjDlZHW53e4/tAw5fQqAIiImZLFYTvsy7PkoOTmZ2bNn06JFC/bv38/+/fu9rYBbt24lPz+f5ORkAJYvX87QoUO57rrrAE+g+/WDF3Xq1KF79+5Mnz6dsrIyevXqRVxcHADx8fHUqlWLPXv2nHA59Ld07tyZDh068Oyzz/Lqq69y0UUX8dFHHxEXF0dERMTvfr9Ro0b4+/uzatUq6tatC0BeXh47d+6ke/fuJ/1OmzZtOHDgADt37vzNVsDTER0dzaJFi+jduzc9evRgyZIl1KpVC4DWrVsTHR3NM888Q7t27QgLC6NHjx5MnDiRvLw87/1/AC1atODTTz/FMAxvK+Dy5csJDw//zcvZv9SsWTP2799PTk4O8fHxgKf7G/nzdAlYRETOW0eOHOHyyy/ngw8+YOPGjWRkZPDxxx8zadIkrrnmGtLS0mjdujWDBw9m3bp1rF69mltvvZXu3bvTsWNHwHM/2Weffcb69evZsGEDN99880lblgYPHszMmTP5+OOPTwh6Tz31FOPHj+cf//gHO3fuZNOmTUyZMoWXXnrpN+u/7777+Oc//8nBgwcZPHgwNWrU4JprruHbb78lIyODpUuXcu+991a6FHpcWFgYt99+O6NHj+brr79m8+bNDB061HvP3Ml0796dSy+9lAEDBrBw4UIyMjL48ssv+eqrr07n5z5BVFQUCxcuJDo6mh49enDo0CHgf/cBTp8+3Rv22rRpg91uZ/HixZUC6t13383+/fu555572L59O59//jlPPPEEDzzwwG9uyy/16tWLRo0aMWTIEDZu3Mjy5ct59NFHvbXIH6cAKCIi562wsDC6dOnCyy+/zKWXXkqrVq147LHHuOOOO7wPFXz++edER0dz6aWXkpaWRsOGDfnoo4+8y3jppZeIjo7m4osv5qqrriI9PZ2LLrrohHUNHDiQI0eOUFpaesLbOP7617/yzjvvMGXKFFq3bk337t2ZOnUqDRo0+M36+/TpQ4MGDXj22WcJCQnhm2++oW7duvTv358WLVpw++23U15efsoWweeff55LLrmEq666irS0NLp160aHDh1+c52ffvopnTp1YtCgQSQnJ/PQQw/hcrl+8zu/JTIykgULFlCjRg26d+/OwYMHAU/YdLlc3gBotVq59NJLsVgs3vv/AGrXrs28efNYvXo1bdu25a677uL222/3BrjTYbPZmD17NsXFxXTq1Im//vWv3qeAg4KC/vS2mZnFUJfef1phYSGRkZEUFBScVnO+iIgvlJeXk5GRQYMGDXSylAvG8uXL6datG7t37670UMtxv3Xc6/ytewBFRESkGpg1axZhYWE0adKE3bt3M3LkSFJTU08a/uT3KQCKiIjIea+oqIgxY8aQmZlJjRo1SEtLO+mbUeT0KACKiIjIee/WW2/l1ltv9XUZFww9BCIiIiJiMgqAIiIiIiajACgiYhLq9EHMRMf7b1MAFBG5wB1/xVZpaamPKxGpOseP91+/Yk489BCIiMgFzmazERUVRW5uLgAhISF6e4JcsAzDoLS0lNzcXKKiok54X7N4KACKiJhAQkICgDcEilzooqKivMe9nEgBUETEBCwWC4mJicTFxeFwOHxdjsg55e/vr5a/36EAKCJiIjabTSdGEdFDICIiIiJmowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImowAoIiIiYjIKgCIiIiImc0EEwAkTJmCxWLjvvvu848rLyxk+fDixsbGEhYUxYMAAcnJyKn0vMzOTfv36ERISQlxcHKNHj8bpdFZx9SIiIiJVq9oHwDVr1vDPf/6TNm3aVBp///3388UXX/Dxxx+zbNkyDh06RP/+/b3TXS4X/fr1o6KighUrVjBt2jSmTp3K448/XtWbICIiIlKlqnUALC4uZvDgwbz99ttER0d7xxcUFPDuu+/y0ksvcfnll9OhQwemTJnCihUr+P777wFYsGABW7du5YMPPqBdu3b07duXp59+msmTJ1NRUeGrTRIRERE556p1ABw+fDj9+vUjLS2t0vi1a9ficDgqjW/evDl169Zl5cqVAKxcuZLWrVsTHx/vnSc9PZ3CwkK2bNly0vXZ7XYKCwsrDSIiIiLVjZ+vC/izZs6cybp161izZs0J07KzswkICCAqKqrS+Pj4eLKzs73z/DL8HZ9+fNrJjB8/nqeeeuosVC8iIiLiO9WyBXD//v2MHDmS6dOnExQUVGXrHTt2LAUFBd5h//79VbZuERERkbOlWgbAtWvXkpuby0UXXYSfnx9+fn4sW7aMf/zjH/j5+REfH09FRQX5+fmVvpeTk0NCQgIACQkJJzwVfPzz8Xl+LTAwkIiIiEqDiIiISHVTLQNgz5492bRpE+vXr/cOHTt2ZPDgwd6/+/v7s3jxYu93duzYQWZmJikpKQCkpKSwadMmcnNzvfMsXLiQiIgIkpOTq3ybRERERKpKtbwHMDw8nFatWlUaFxoaSmxsrHf87bffzgMPPEBMTAwRERHcc889pKSk0LVrVwB69+5NcnIyt9xyC5MmTSI7O5tHH32U4cOHExgYWOXbJCIiIlJVqmUAPB0vv/wyVquVAQMGYLfbSU9P54033vBOt9lszJ07l2HDhpGSkkJoaChDhgxh3LhxPqxaRERE5NyzGIZh+LqI6qqwsJDIyEgKCgp0P6CIiEg1ofN3Nb0HUERERET+PAVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZOplgHwzTffpE2bNkRERBAREUFKSgpffvmld3p5eTnDhw8nNjaWsLAwBgwYQE5OTqVlZGZm0q9fP0JCQoiLi2P06NE4nc6q3hQRERGRKlctA2CdOnWYMGECa9eu5YcffuDyyy/nmmuuYcuWLQDcf//9fPHFF3z88ccsW7aMQ4cO0b9/f+/3XS4X/fr1o6KighUrVjBt2jSmTp3K448/7qtNEhEREakyFsMwDF8XcTbExMTw/PPPM3DgQGrWrMmMGTMYOHAgANu3b6dFixasXLmSrl278uWXX3LllVdy6NAh4uPjAXjrrbcYM2YMhw8fJiAg4LTWWVhYSGRkJAUFBURERJyzbRMREZGzR+fvatoC+Esul4uZM2dSUlJCSkoKa9euxeFwkJaW5p2nefPm1K1bl5UrVwKwcuVKWrdu7Q1/AOnp6RQWFnpbEUVEREQuVH6+LuDP2rRpEykpKZSXlxMWFsasWbNITk5m/fr1BAQEEBUVVWn++Ph4srOzAcjOzq4U/o5PPz7tVOx2O3a73fu5sLDwLG2NiIiISNWpti2AzZo1Y/369axatYphw4YxZMgQtm7dek7XOX78eCIjI71DUlLSOV2fiIiIyLlQbQNgQEAAjRs3pkOHDowfP562bdvy6quvkpCQQEVFBfn5+ZXmz8nJISEhAYCEhIQTngo+/vn4PCczduxYCgoKvMP+/fvP7kaJiIiIVIFqGwB/ze12Y7fb6dChA/7+/ixevNg7bceOHWRmZpKSkgJASkoKmzZtIjc31zvPwoULiYiIIDk5+ZTrCAwM9HY9c3wQERERqW6q5T2AY8eOpW/fvtStW5eioiJmzJjB0qVLmT9/PpGRkdx+++088MADxMTEEBERwT333ENKSgpdu3YFoHfv3iQnJ3PLLbcwadIksrOzefTRRxk+fDiBgYE+3joRERGRc6taBsDc3FxuvfVWsrKyiIyMpE2bNsyfP59evXoB8PLLL2O1WhkwYAB2u5309HTeeOMN7/dtNhtz585l2LBhpKSkEBoaypAhQxg3bpyvNklERESkylww/QD6gvoREhERqX50/r6A7gEUERERkdOjACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMgqAIiIiIiajACgiIiJiMtUyAI4fP55OnToRHh5OXFwc1157LTt27Kg0T3l5OcOHDyc2NpawsDAGDBhATk5OpXkyMzPp168fISEhxMXFMXr0aJxOZ1VuioiIiEiVq5YBcNmyZQwfPpzvv/+ehQsX4nA46N27NyUlJd557r//fr744gs+/vhjli1bxqFDh+jfv793usvlol+/flRUVLBixQqmTZvG1KlTefzxx32xSSIiIiJVxmIYhuHrIs7U4cOHiYuLY9myZVx66aUUFBRQs2ZNZsyYwcCBAwHYvn07LVq0YOXKlXTt2pUvv/ySK6+8kkOHDhEfHw/AW2+9xZgxYzh8+DABAQG/u97CwkIiIyMpKCggIiLinG6jiIiInB06f1fTFsBfKygoACAmJgaAtWvX4nA4SEtL887TvHlz6taty8qVKwFYuXIlrVu39oY/gPT0dAoLC9myZUsVVi8iIiJStfx8XcCZcrvd3HfffaSmptKqVSsAsrOzCQgIICoqqtK88fHxZGdne+f5Zfg7Pv34tJOx2+3Y7Xbv58LCwrO1GSIiIiJVptq3AA4fPpzNmzczc+bMc76u8ePHExkZ6R2SkpLO+TpFREREzrZqHQBHjBjB3LlzWbJkCXXq1PGOT0hIoKKigvz8/Erz5+TkkJCQ4J3n108FH/98fJ5fGzt2LAUFBd5h//79Z3FrRERERKpGtQyAhmEwYsQIZs2axddff02DBg0qTe/QoQP+/v4sXrzYO27Hjh1kZmaSkpICQEpKCps2bSI3N9c7z8KFC4mIiCA5Ofmk6w0MDCQiIqLSICIiIlLdVMt7AIcPH86MGTP4/PPPCQ8P996zFxkZSXBwMJGRkdx+++088MADxMTEEBERwT333ENKSgpdu3YFoHfv3iQnJ3PLLbcwadIksrOzefTRRxk+fDiBgYG+3DwRERGRc6padgNjsVhOOn7KlCkMHToU8HQE/eCDD/Lhhx9it9tJT0/njTfeqHR5d9++fQwbNoylS5cSGhrKkCFDmDBhAn5+p5eL9Ri5iIhI9aPzdzUNgOcLHUAiIiLVj87f1fQeQBERERH58xQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARURERExGAVBERETEZBQARUREREzGz9cFiIhUK4YBFSVQchhKfgZ7AdiLoaIY7EXH/n7sT1cFuF3gdoDbeWxweQar7djgB1b/Y3/awD8YAsIgMAwCwiEw/NjfwyA4GkJrQmgN8Av09S8hItWYAqCIyHEuJxRlQcEBKNjvGfL3e8aVHPYMxYfBWebrSiEw0hMEQ2tCWE2IqANRdSEqCSKTPH8PjgaLxdeVish5SAFQRMzF7YbCg3BkF/y8+9ifu+DIT57xhuv0luMX7AlfQZGVW+kCwyAwAgJCPa10Vr+TDLZjLYHOyoPLAc5y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vB9AERERETMy7T2AIiIiImalACgiIiJiMgqAIiIiIiajACgiIiJiMgqAf9LkyZOpX78+QUFBdOnShdWrV/u6pAvO+PHj6dSpE+Hh4cTFxXHttdeyY8eOSvOUl5czfPhwYmNjCQsLY8CAASd07p2ZmUm/fv0ICQkhLi6O0aNH43Q6q3JTLjgTJkzAYrFw3333ecdpX1SdgwcP8n//93/ExsYSHBxM69at+eGHH7zTDcPg8ccfJzExkeDgYNLS0ti1a1elZRw9epTBgwcTERFBVFQUt99+O8XFxVW9KdWey+Xiscceo0GDBgQHB9OoUSOefvrpSu+Y1f44N7755huuuuoqatWqhcViYfbs2ZWmn63ffePGjVxyySUEBQWRlJTEpEmTzvWmVQ1D/rCZM2caAQEBxnvvvWds2bLFuOOOO4yoqCgjJyfH16VdUNLT040pU6YYmzdvNtavX29cccUVRt26dY3i4mLvPHfddZeRlJRkLF682Pjhhx+Mrl27GhdffLF3utPpNFq1amWkpaUZP/74ozFv3jyjRo0axtixY32xSReE1atXG/Xr1zfatGljjBw50jte+6JqHD161KhXr54xdOhQY9WqVcaePXuM+fPnG7t37/bOM2HCBCMyMtKYPXu2sWHDBuPqq682GjRoYJSVlXnn6dOnj9G2bVvj+++/N7799lujcePGxqBBg3yxSdXas88+a8TGxhpz5841MjIyjI8//tgICwszXn31Ve882h/nxrx584xHHnnE+OyzzwzAmDVrVqXpZ+N3LygoMOLj443BgwcbmzdvNj788EMjODjY+Oc//1lVm3nOKAD+CZ07dzaGDx/u/exyuYxatWoZ48eP92FVF77c3FwDMJYtW2YYhmHk5+cb/v7+xscff+ydZ9u2bQZgrFy50jAMz/8grFarkZ2d7Z3nzTffNCIiIgy73V61G3ABKCoqMpo0aWIsXLjQ6N69uzcAal9UnTFjxhjdunU75XS3220kJCQYzz//vHdcfn6+ERgYaHz44YeGYRjG1q1bDcBYs2aNd54vv/zSsFgsxsGDB89d8Regfv36GX/5y18qjevfv78xePBgwzC0P6rKrwPg2frd33jjDSM6OrrS/6PGjBljNGvW7Bxv0bmnS8B/UEVFBWvXriUtLc07zmq1kpaWxsqVK31Y2YWvoKAAwPvy7rVr1+JwOCrti+bNm1O3bl3vvli5ciWtW7eu1Ll3eno6hYWFbNmypQqrvzAMHz6cfv36VfrNQfuiKs2ZM4eOHTty/fXXExcXR/v27Xn77be90zMyMsjOzq60LyIjI+nSpUulfREVFUXHjh2986SlpWG1Wlm1alXVbcwF4OKLL2bx4sXs3LkTgA0bNvDdd9/Rt29fQPvDV87W775y5UouvfRSAgICvPOkp6ezY8cO8vLyqmhrzg1Tvwnkz/j5559xuVwnvC0kPj6e7du3+6iqC5/b7ea+++4jNTWVVq1aAZCdnU1AQABRUVGV5o2Pjyc7O9s7z8n21fFpcvpmzpzJunXrWLNmzQnTtC+qzp49e3jzzTd54IEH+Pvf/86aNWu49957CQgIYMiQId7f8mS/9S/3RVxcXKXpfn5+xMTEaF/8QQ8//DCFhYU0b94cm82Gy+Xi2WefZfDgwQDaHz5ytn737OxsGjRocMIyjk+Ljo4+J/VXBQVAqRaGDx/O5s2b+e6773xdiint37+fkSNHsnDhQoKCgnxdjqm53W46duzIc889B0D79u3ZvHkzb731FkOGDPFxdebzn//8h+nTpzNjxgxatmzJ+vXrue+++6hVq5b2h5zXdAn4D6pRowY2m+2EpxtzcnJISEjwUVUXthEjRjB37lyWLFlCnTp1vOMTEhKoqKggPz+/0vy/3BcJCQkn3VfHp8npWbt2Lbm5uVx00UX4+fnh5+fHsmXL+Mc//oGfnx/x8fHaF1UkMTGR5OTkSuNatGhBZmYm8L/f8rf+H5WQkEBubm6l6U6nk6NHj2pf/EGjR4/m4Ycf5qabbqJ169bccsst3H///YwfPx7Q/vCVs/W7X8j/31IA/IMCAgLo0KEDixcv9o5zu90sXryYlJQUH1Z24TEMgxEjRjBr1iy+/vrrE5rhO3TogL+/f6V9sWPHDjIzM737IiUlhU2bNlX6j3zhwoVERESccBKVU+vZsyebNm1i/fr13qFjx44MHjzY+3fti6qRmpp6QndIO3fupF69egA0aNCAhISESvuisLCQVatWVdoX+fn5rF271jvP119/jdvtpkuXLlWwFReO0tJSrNbKp1KbzYbb7Qa0P3zlbP3uKSkpfPPNNzgcDu88CxcupFmzZtX68i+gbmD+jJkzZxqBgYHG1KlTja1btxp33nmnERUVVenpRjlzw4YNMyIjI42lS5caWVlZ3qG0tNQ7z1133WXUrVvX+Prrr40ffvjBSElJMVJSUrzTj3c90rt3b2P9+vXGV199ZdSsWVNdj5wFv3wK2DC0L6rK6tWrDT8/P+PZZ581du3aZUyfPt0ICQkxPvjgA+88EyZMMKKioozPP//c2Lhxo3HNNdectPuL9u3bG6tWrTK+++47o0mTJup25E8YMmSIUbt2bW83MJ999plRo0YN46GHHvLOo/1xbhQVFRk//vij8eOPPxqA8dJLLxk//vijsW/fPsMwzs7vnp+fb8THxxu33HKLsXnzZmPmzJlGSEiIuoExs9dee82oW7euERAQYHTu3Nn4/vvvfV3SBQc46TBlyhTvPGVlZcbdd99tREdHGyEhIcZ1111nZGVlVVrO3r17jb59+xrBwcFGjRo1jAcffNBwOBxVvDUXnl8HQO2LqvPFF18YrVq1MgIDA43mzZsb//rXvypNd7vdxmOPPWbEx8cbgYGBRs+ePY0dO3ZUmufIkSPGoEGDjLCwMCMiIsK47bbbjKKioqrcjAtCYWGhMXLkSKNu3bpGUFCQ0bBhQ+ORRx6p1G2I9se5sWTJkpOeI4YMGWIYxtn73Tds2GB069bNCAwMNGrXrm1MmDChqjbxnLIYxi+6KxcRERGRC57uARQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExGQVAEREREZNRABQRERExmf8HezbYB5otwKgAAAAASUVORK5CYII=",
+ "text/html": [
+ "\n",
+ " \n",
+ "
\n",
+ " Figure\n",
+ "
\n",
+ "

\n",
+ "
\n",
+ " "
+ ],
+ "text/plain": [
+ "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%matplotlib widget\n",
+ "x = np.linspace(-10, 10,100)\n",
+ "\n",
+ "def f(x, A, B, C):\n",
+ " return A*x**2 + B*x + C\n",
+ "\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(1, 1, 1)\n",
+ "line, = ax.plot(x, f(x, A=1, B=1, C=1))\n",
+ "\n",
+ "\n",
+ "def run(i, x, n):\n",
+ " z = np.ones(n)\n",
+ " z[i] = x\n",
+ " exclude = [i]\n",
+ " mask = np.ones(z.shape, bool)\n",
+ " mask[exclude] = False\n",
+ " z[mask] = (1 - x)/2\n",
+ " \n",
+ " z = z/sum(z)\n",
+ " print(z)\n",
+ "\n",
+ " models = [\n",
+ " yaeos.PengRobinson76,\n",
+ " yaeos.PengRobinson78,\n",
+ " yaeos.SoaveRedlichKwong,\n",
+ " ]\n",
+ "\n",
+ " ax.clear()\n",
+ " for m in models:\n",
+ " model = m(Tc, Pc, w)\n",
+ " T, P, Tcs, Pcs = yaeos.yaeos_c.pt2_phase_envelope(model.id, z, kind=\"dew\", t0=150, p0=0.01)\n",
+ " ax.plot(T, P, label=model.name)\n",
+ " plt.legend()\n",
+ " \n",
+ " ax.set_xlim(0, 1000)\n",
+ " ax.set_ylim(0, 550)\n",
+ " return T, P\n",
+ "\n",
+ "def update(i, x, n):\n",
+ " T, P = run(i, x, n)\n",
+ " #line.set_xdata(T)\n",
+ " #line.set_ydata(P)\n",
+ " #fig.canvas.draw_idle()\n",
+ "\n",
+ "interact(update, i=[i for i in range(len(Tc))], x=(0.0001, 0.9999, 0.01), n=fixed(len(Tc)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a15f127d-d055-4c96-92bb-baf643afe24b",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/python/pyproject.toml b/python/pyproject.toml
new file mode 100644
index 000000000..185668349
--- /dev/null
+++ b/python/pyproject.toml
@@ -0,0 +1,14 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["fpm", "meson", "ninja", "numpy", "setuptools", "wheel"]
+
+
+[tool.black]
+line-length = 79
+target-version = ["py310"]
+
+
+[tool.pytest.ini_options]
+markers = [
+ "marker_name: marker_description",
+]
\ No newline at end of file
diff --git a/python/requirements-dev.txt b/python/requirements-dev.txt
new file mode 100644
index 000000000..dcd196456
--- /dev/null
+++ b/python/requirements-dev.txt
@@ -0,0 +1,29 @@
+# Style
+flake8-nb
+flake8-black
+flake8-builtins
+flake8-import-order
+pep8-naming
+pydocstyle
+
+# documentation (also pandoc must be installed)
+nbsphinx
+sphinx
+sphinx_copybutton
+sphinx_rtd_theme
+sphinxcontrib.bibtex
+
+# Testing
+check-manifest
+pytest
+pytest-cov
+tox
+
+# General purpose
+ipdb
+ipython
+jupyter
+matplotlib
+
+# Build
+build
diff --git a/python/setup.py b/python/setup.py
new file mode 100644
index 000000000..fe320a738
--- /dev/null
+++ b/python/setup.py
@@ -0,0 +1,241 @@
+import shutil
+import subprocess
+from pathlib import Path
+
+from setuptools import Command, setup
+from setuptools.command.editable_wheel import editable_wheel
+from setuptools.command.egg_info import egg_info
+
+
+# =============================================================================
+# Directories and constants
+# =============================================================================
+THIS_DIR = Path(__file__).parent
+BUILD_DIR = (THIS_DIR.parent / "build" / "python").absolute()
+LINK_DIR = BUILD_DIR / "lib"
+INCL_DIR = BUILD_DIR / "include"
+COMPILED_FLAG = THIS_DIR / "compiled_flag"
+
+FFLAGS = "-g -fPIC -funroll-loops -fstack-arrays -Ofast -frepack-arrays -faggressive-function-elimination -fopenmp" # noqa
+CFLAGS = "-fPIC"
+
+
+# =============================================================================
+# Usefull functions
+# =============================================================================
+def pre_build():
+ """Execute fpm and f2py compilations commands."""
+ print(THIS_DIR)
+
+ if COMPILED_FLAG.exists():
+ return
+
+ subprocess.check_call(
+ [
+ "fpm",
+ "install",
+ "--profile",
+ "release",
+ "--flag",
+ f"{FFLAGS}",
+ "--c-flag",
+ f"{CFLAGS}",
+ "--prefix",
+ BUILD_DIR,
+ ]
+ )
+
+ subprocess.check_call(
+ [
+ "f2py",
+ "-m",
+ "yaeos_compiled",
+ f"-L{LINK_DIR}",
+ f"-I{INCL_DIR}",
+ "-c",
+ "yaeos/fortran_wrap/yaeos_c.f90",
+ "-lyaeos", "-llapack",
+ "--backend",
+ "meson",
+ ]
+ )
+
+ COMPILED_FLAG.touch()
+
+
+def initial_compiled_clean():
+ """Erase all compiled files from development directory"""
+ # Clear fpm build
+ if BUILD_DIR.exists():
+ shutil.rmtree(BUILD_DIR)
+
+ # Clear compiled files on compiled_files
+ compiled_module_dir = THIS_DIR / "yaeos" / "compiled_module"
+
+ if compiled_module_dir.exists():
+ for so_file in compiled_module_dir.glob("*.so"):
+ so_file.unlink()
+
+ # Additionally, clear any .so files in the root directory if present
+ for so_file in THIS_DIR.glob("yaeos_compiled*.so"):
+ so_file.unlink()
+
+
+def final_build_clean():
+ """Clean the build of setuptools."""
+
+ if (THIS_DIR / "build").exists():
+ print((THIS_DIR / "build").absolute())
+ shutil.rmtree(THIS_DIR / "build")
+
+ # Clear compiled files on compiled_files
+ compiled_module_dir = THIS_DIR / "yaeos" / "compiled_module"
+
+ if compiled_module_dir.exists():
+ for so_file in compiled_module_dir.glob("*.so"):
+ so_file.unlink()
+
+ # Clean COMPILED_FLAG
+ if COMPILED_FLAG.exists():
+ COMPILED_FLAG.unlink()
+
+
+def move_compiled_to_editable_loc():
+ """Move compiled files to 'compiled_module' directory"""
+
+ for file in THIS_DIR.glob("yaeos_compiled.*"):
+ target_dir = THIS_DIR / "yaeos" / "compiled_module"
+ target_dir.mkdir(parents=True, exist_ok=True)
+
+ shutil.move(file.absolute(), (target_dir / file.name).absolute())
+
+
+def save_editable_compiled():
+ """Temporaly save the editable compiled from install and sdist commands"""
+ tmp_dir = THIS_DIR / "tmp_editable"
+
+ if not tmp_dir.exists():
+ tmp_dir.mkdir()
+
+ compiled_module_dir = THIS_DIR / "yaeos" / "compiled_module"
+
+ if compiled_module_dir.exists():
+ for so_file in compiled_module_dir.glob("*.so"):
+ if ((tmp_dir / so_file.name).absolute()).exists():
+ ((tmp_dir / so_file.name).absolute()).unlink()
+
+ shutil.move(
+ so_file.absolute(), (tmp_dir / so_file.name).absolute()
+ )
+
+
+def restore_save_editable_compiled():
+ tmp_dir = THIS_DIR / "tmp_editable"
+
+ compiled_module_dir = THIS_DIR / "yaeos" / "compiled_module"
+
+ if tmp_dir.exists():
+ for so_file in tmp_dir.glob("*.so"):
+ shutil.move(
+ so_file.absolute(),
+ (compiled_module_dir / so_file.name).absolute(),
+ )
+
+ tmp_dir.rmdir()
+
+
+# =============================================================================
+# Build command
+# =============================================================================
+class BuildFortran(Command):
+ description = "Compile Fortran library with fpm and f2py"
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ dir = str(THIS_DIR.absolute())
+
+ if ("build" in dir) or ("check-manifest" in dir):
+ # Do not compile, we are building, the compilation has been already
+ # done at this point.
+ ...
+ else:
+ pre_build()
+
+
+# =============================================================================
+# - Building for developers (editable installation)
+# pip install -e .
+# =============================================================================
+class CustomEditable(editable_wheel):
+ def run(self):
+ self.run_command("build_fortran")
+ move_compiled_to_editable_loc()
+ save_editable_compiled()
+
+ # Run base editable_wheel run method
+ super().run()
+
+
+# =============================================================================
+# - Custom egg_info command
+# =============================================================================
+class CustomEgg(egg_info):
+ def run(self):
+ self.run_command("build_fortran")
+ move_compiled_to_editable_loc()
+ super().run()
+
+
+# =============================================================================
+# Call setup
+# =============================================================================
+name = "yaeos"
+version = "0.3.0"
+author = "Federico E. Benelli"
+author_email = "federico.benelli@mi.unc.edu.ar"
+maintainer = "Federico E. Benelli"
+maintainer_email = "federico.benelli@mi.unc.edu.ar"
+lic = "MPL"
+
+
+save_editable_compiled()
+
+initial_compiled_clean()
+
+setup(
+ name=name,
+ version=version,
+ author=author,
+ author_email=author_email,
+ maintainer=maintainer,
+ maintainer_email=maintainer_email,
+ description="",
+ license=lic,
+ keywords="thermodynamics equation-of-state",
+ url="https://github.com/ipqa-research/yaeos",
+ classifiers=[
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Science/Research/Engineering",
+ "Topic :: Thermodynamics",
+ "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
+ ],
+ install_requires=["numpy"],
+ cmdclass={
+ "build_fortran": BuildFortran,
+ "editable_wheel": CustomEditable,
+ "egg_info": CustomEgg
+ },
+ packages=["yaeos"],
+ package_data={"yaeos": ["compiled_module/*.so"]},
+ include_package_data=True,
+)
+
+final_build_clean()
+
+restore_save_editable_compiled()
diff --git a/python/tests/__init__.py b/python/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/python/tests/test_dummy.py b/python/tests/test_dummy.py
new file mode 100644
index 000000000..1e297f87d
--- /dev/null
+++ b/python/tests/test_dummy.py
@@ -0,0 +1,48 @@
+import numpy as np
+import numpy.testing as npt
+
+from yaeos import SoaveRedlichKwong, PengRobinson76, QMR
+
+
+def test_dummy():
+ mr = QMR(np.zeros((2, 2)), np.zeros((2, 2)))
+
+ model = PengRobinson76(
+ np.array([300, 350]), np.array([30, 40]), np.array([0.152, 0.325]), mr
+ )
+
+ fug = model.fugacity(np.array([5, 6]), 2.0, 303.15)["ln_phi"]
+
+ assert np.allclose(fug, np.array([0.65960035, 0.30581106]))
+
+
+def test_flash():
+ nc = 2
+ n = [0.4, 0.6]
+ Tc = [190.564, 425.12]
+ Pc = [45.99, 37.96]
+ w = [0.0115478, 0.200164]
+
+ lij = kij = np.zeros((nc, nc))
+ mixrule = QMR(kij, lij)
+ model = PengRobinson76(Tc, Pc, w, mixrule)
+
+ P, T = 60.0, 294.0
+ flash = model.flash_pt(n, pressure=T, temperature=P)
+
+ npt.assert_allclose(flash["x"], [0.32424472, 0.67575528], rtol=1e-5)
+
+
+def test_saturation():
+ nc = 2
+ n = [0.4, 0.6]
+ tc = [190.564, 425.12]
+ pc = [45.99, 37.96]
+ w = [0.0115478, 0.200164]
+
+ lij = kij = np.zeros((nc, nc))
+ mixrule = QMR(kij, lij)
+ model = SoaveRedlichKwong(tc, pc, w, mixrule)
+
+ bub = model.saturation_pressure(n, temperature=303.15, kind="bubble")
+ npt.assert_allclose(bub["y"], [0.899642, 0.100358], rtol=1e-5)
diff --git a/python/tox.ini b/python/tox.ini
new file mode 100644
index 000000000..8b00d2e6a
--- /dev/null
+++ b/python/tox.ini
@@ -0,0 +1,79 @@
+[tox]
+isolated_build = True
+envlist =
+ style,
+ docstyle,
+ check-manifest,
+ py310,
+ py311,
+ py312,
+ coverage,
+
+
+# =============================================================================
+# ENVS
+# =============================================================================
+[gh-actions]
+python =
+ 3.10: py310, style, docstyle, coverage, check-manifest
+ 3.11: py311
+ 3.12: py312
+
+[testenv]
+deps =
+ ipdb
+ pytest
+skip_install = False
+usedevelop = True
+commands =
+ pytest tests/ {posargs}
+
+
+[testenv:style]
+skip_install = True
+usedevelop = False
+deps =
+ flake8
+ flake8-black
+ flake8-builtins
+ flake8-import-order
+ pep8-naming
+commands =
+ flake8 tests/ yaeos/ {posargs}
+
+
+[testenv:docstyle]
+deps =
+ pydocstyle
+ tomli
+commands = pydocstyle yaeos --convention=numpy
+
+
+[testenv:check-manifest]
+skip_install = True
+usedevelop = False
+allowlist_externals = touch, rm
+deps = check-manifest
+commands =
+ check-manifest
+
+
+; [testenv:docs]
+; description = "Invoke sphinx-build to build the HTML docs"
+; whitelist_externals = make
+; usedevelop = True
+; skip_install = False
+; changedir = docs
+; deps = -r {toxinidir}/docs/requirements.txt
+; commands = sphinx-build -W -b html -d {envtmpdir}/doctrees source {envtmpdir}/html
+
+
+[testenv:coverage]
+deps =
+ {[testenv]deps} # same dependencies of [testenv]
+ coverage
+ pytest-cov
+commands =
+ coverage erase
+ pytest tests/ --cov=yaeos/ --cov-append --cov-report=term-missing
+ coverage report --fail-under=70 -m
diff --git a/python/yaeos/__init__.py b/python/yaeos/__init__.py
new file mode 100644
index 000000000..9787061ac
--- /dev/null
+++ b/python/yaeos/__init__.py
@@ -0,0 +1,23 @@
+from yaeos.compiled_module.yaeos_compiled import yaeos_c
+
+from yaeos.core import (
+ SoaveRedlichKwong,
+ PengRobinson76,
+ PengRobinson78,
+ RKPR,
+ NRTL,
+ MHV,
+ QMR,
+)
+
+
+__all__ = [
+ "yaeos_c",
+ "SoaveRedlichKwong",
+ "PengRobinson76",
+ "PengRobinson78",
+ "RKPR",
+ "QMR",
+ "NRTL",
+ "MHV",
+]
diff --git a/python/yaeos/compiled_module/__init__.py b/python/yaeos/compiled_module/__init__.py
new file mode 100644
index 000000000..00fe9522e
--- /dev/null
+++ b/python/yaeos/compiled_module/__init__.py
@@ -0,0 +1,4 @@
+from .yaeos_compiled import yaeos_c
+
+
+__all__ = ["yaeos_c"]
diff --git a/python/yaeos/core.py b/python/yaeos/core.py
new file mode 100644
index 000000000..dd54940b1
--- /dev/null
+++ b/python/yaeos/core.py
@@ -0,0 +1,194 @@
+"""CubicEoS interface
+"""
+
+from abc import ABC, abstractmethod
+
+import numpy as np
+
+from yaeos import yaeos_c
+
+
+class GeModel(ABC):
+ """Excess Gibbs model."""
+
+ def __del__(self):
+ yaeos_c.make_available_ge_models_list(self.id)
+
+
+class ArModel(ABC):
+ """Residual Helmholtz (Ar) model"""
+
+ def fugacity(self, n, v, t, dt=None, dp=None, dn=None):
+
+ nc = len(n)
+
+ if dt:
+ dt = np.empty(nc, order="F")
+ if dp:
+ dp = np.empty(nc, order="F")
+ if dn:
+ dn = np.empty((nc, nc), order="F")
+
+ res = yaeos_c.fug_vt(
+ self.id, n, v, t, dlnphidt=dt, dlnphidp=dp, dlnphidn=dn
+ )
+ res = {"ln_phi": res, "dt": dt, "dp": dp, "dn": dn}
+ return res
+
+ def flash_pt(self, z, pressure, temperature):
+ """Two-phase split with specification of temperature and pressure.
+
+ Calculates the phase split at a given pressure and temperature
+ """
+
+ x, y, pressure, temperature, volume_x, volume_y, beta = yaeos_c.flash(
+ self.id, z, pressure, temperature
+ )
+
+ flash_result = {
+ "x": x,
+ "y": y,
+ "P": pressure,
+ "T": temperature,
+ "beta": beta,
+ }
+
+ return flash_result
+
+ def saturation_pressure(self, z, temperature, kind="bubble"):
+ """Saturation pressure at specified temperature
+
+ Arguments
+ ---------
+ z: array
+ Global molar fractions
+ temperature: float
+ Temperature [K]
+ kind: string
+ Kind of saturation point, defaults to "bubble". Options are
+ - "bubble"
+ - "dew"
+ - "liquid-liquid"
+ """
+ p, x, y, volume_x, volume_y, beta = yaeos_c.saturation_pressure(
+ self.id, z, temperature, kind
+ )
+
+ return {
+ "x": x,
+ "y": y,
+ "Vx": volume_x,
+ "Vy": volume_y,
+ "T": temperature,
+ "P": p,
+ "beta": beta,
+ }
+
+ def __del__(self):
+ yaeos_c.make_available_ar_models_list(self.id)
+
+
+class NRTL:
+
+ def __init__(self, a, b, c):
+ self.a = a
+ self.b = b
+ self.c = c
+ self.id = yaeos_c.nrtl(a, b, c)
+
+
+class CubicMixRule(ABC):
+ @abstractmethod
+ def set_mixrule(self, ar_model_id):
+ raise NotImplementedError
+
+
+class CubicEoS(ArModel):
+ def __init__(self, tc, pc, w):
+ nc = len(tc)
+ self.nc = nc
+ self.tc = tc
+ self.pc = pc
+ self.w = w
+
+ def set_mixrule(self, mixrule: CubicMixRule):
+ self.mixrule = mixrule
+ self.mixrule.set_mixrule(self.id)
+
+
+class QMR(ABC):
+
+ def __init__(self, kij, lij):
+ self.kij = kij
+ self.lij = lij
+
+ def set_mixrule(self, ar_model_id):
+ yaeos_c.set_qmr(ar_model_id, self.kij, self.lij)
+
+
+class MHV(ABC):
+
+ def __init__(self, ge, q, lij=None):
+ self.ge = ge
+ self.q = q
+ self.lij = lij
+
+ def set_mixrule(self, ar_model_id):
+ yaeos_c.set_mhv(ar_model_id, self.ge.id, self.q)
+
+
+class PengRobinson76(CubicEoS):
+ name = "PengRobinson76"
+
+ def __init__(self, tc, pc, w, mixrule: CubicMixRule = None):
+ super(PengRobinson76, self).__init__(tc, pc, w)
+ self.id = yaeos_c.pr76(self.tc, self.pc, self.w)
+ self.mixrule = mixrule
+ if mixrule:
+ mixrule.set_mixrule(self.id)
+
+
+class PengRobinson78(CubicEoS):
+ name = "PengRobinson78"
+
+ def __init__(self, tc, pc, w, mixrule: CubicMixRule = None):
+ super(PengRobinson78, self).__init__(tc, pc, w)
+ self.id = yaeos_c.pr78(self.tc, self.pc, self.w)
+ self.mixrule = mixrule
+ if mixrule:
+ mixrule.set_mixrule(self.id)
+
+
+class SoaveRedlichKwong(CubicEoS):
+ name = "SoaveReldichKwong"
+
+ def __init__(self, tc, pc, w, mixrule: CubicMixRule = None):
+ super(SoaveRedlichKwong, self).__init__(tc, pc, w)
+ self.id = yaeos_c.srk(self.tc, self.pc, self.w)
+ if mixrule:
+ mixrule.set_mixrule(self.id)
+
+
+class RKPR(CubicEoS):
+ name = "RKPR"
+
+ def __init__(
+ self, tc, pc, w, zc, k=None, delta_1=None, mixrule: CubicMixRule = None
+ ):
+ super(RKPR, self).__init__(tc, pc, w)
+ self.zc = zc
+ match (k is None, delta_1 is None):
+ case (True, True):
+ self.id = yaeos_c.rkpr(self.tc, self.pc, self.w, self.zc)
+ case (False, True):
+ self.id = yaeos_c.rkpr(self.tc, self.pc, self.w, self.zc, k=k)
+ case (True, False):
+ self.id = yaeos_c.rkpr(
+ self.tc, self.pc, self.w, self.zc, delta_1=delta_1
+ )
+ case (False, False):
+ self.id = yaeos_c.rkpr(
+ self.tc, self.pc, self.w, self.zc, k=k, delta_1=delta_1
+ )
+ if mixrule:
+ mixrule.set_mixrule(self.id)
diff --git a/python/yaeos/fortran_wrap/yaeos_c.f90 b/python/yaeos/fortran_wrap/yaeos_c.f90
new file mode 100644
index 000000000..837a95868
--- /dev/null
+++ b/python/yaeos/fortran_wrap/yaeos_c.f90
@@ -0,0 +1,381 @@
+module yaeos_c
+ !! # Yaeos C Interface
+ !! C interface intended to be used on external languanges. With an emphasis
+ !! on using it on Python.
+ !!
+ !! # Description
+ !! The interface holds two lists of models (one for `ArModels` and another
+ !! for`GeModels`), and two lists of logicals that represent wich models are
+ !! in those lists are allocated.
+ !!
+ !! When a model is instanciated/allocated, it is stored in the singleton
+ !! object `x_model` and right after that the `extend_x_models_list` procedure
+ !! is called. This procedure searches for the first `free_x_models` id and
+ !! allocates the singleton model there, returning the `id` of the procedure.
+ use iso_c_binding, only: c_double, c_int, c_int64_t
+ use yaeos, only: ArModel, GeModel
+ implicit none
+
+ private
+
+ ! CubicEoS
+ public :: srk, pr76, pr78, rkpr
+ ! Mixing rules
+ public :: set_mhv, set_qmr
+
+ ! __del__
+ public :: make_available_ar_models_list
+ public :: make_available_ge_models_list
+ ! GeMoels
+ public :: nrtl
+ public :: ln_gamma
+
+ ! Thermoprops
+ public :: fug_vt
+
+ ! Phase equilibria
+ public :: flash
+ public :: saturation_pressure
+ public :: pt2_phase_envelope
+
+ type :: ArModelContainer
+ !! Container type for ArModels
+ class(ArModel), allocatable :: model
+ end type ArModelContainer
+
+ type :: GeModelContainer
+ !! Container type for GeModels
+ class(GeModel), allocatable :: model
+ end type GeModelContainer
+
+ class(ArModel), allocatable :: ar_model !! Singleton to hold temporal ArModels
+ class(GeModel), allocatable :: ge_model !! Singleton to hold temporal GeModels
+
+ ! Containers of models
+ integer, parameter :: max_models = 1000000
+ logical :: free_ar_model(max_models) = .true.
+ logical :: free_ge_model(max_models) = .true.
+
+ class(ArModelContainer), allocatable :: ar_models(:)
+ class(GeModelContainer), allocatable :: ge_models(:)
+
+contains
+
+ ! ==========================================================================
+ ! Ge Models
+ ! --------------------------------------------------------------------------
+ subroutine nrtl(a, b, c, id)
+ use yaeos, only: fNRTL => NRTL
+ real(c_double), intent(in) :: a(:,:), b(:,:), c(:,:)
+ integer(c_int), intent(out) :: id
+ ge_model = fNRTL(a, b, c)
+ call extend_ge_models_list(id)
+ end subroutine nrtl
+
+ subroutine extend_ge_models_list(id)
+ !! Find the first available model container and allocate the model
+ !! there. Then return the found id.
+ integer(c_int), intent(out) :: id
+ integer :: i
+ if (.not. allocated(ge_models)) allocate(ge_models(max_models))
+
+ ! Find the first not allocated model
+ do i=1,max_models
+ if (free_ge_model(i)) then
+ free_ge_model(i) = .false.
+ id = i
+ call move_alloc(ge_model, ge_models(i)%model)
+ exit
+ end if
+ end do
+ if (id == max_models) error stop 1
+ end subroutine extend_ge_models_list
+
+ subroutine make_available_ge_models_list(id)
+ !! Make the geModel id available for allocation
+ integer(c_int), intent(in) :: id
+ free_ge_model(id) = .true.
+ end subroutine make_available_ge_models_list
+
+ subroutine ln_gamma(id, n, T, lngamma)
+ integer(c_int), intent(in) :: id
+ real(c_double), intent(in) :: n(:)
+ real(c_double), intent(in) :: T
+ real(c_double), intent(out) :: lngamma(size(n))
+ call ge_models(id)%model%ln_activity_coefficient(n, T, lngamma)
+ end subroutine ln_gamma
+
+ ! =============================================================================
+ ! Ar Models
+ ! -----------------------------------------------------------------------------
+ subroutine extend_ar_models_list(id)
+ !! Find the first available model container and allocate the model
+ !! there. Then return the found id.
+ integer(c_int), intent(out) :: id
+ integer :: i
+ if (.not. allocated(ar_models)) allocate(ar_models(max_models))
+
+ ! Find the first not allocated model
+ do i=1,max_models
+ if (free_ar_model(i)) then
+ free_ar_model(i) = .false.
+ id = i
+ call move_alloc(ar_model, ar_models(i)%model)
+ exit
+ end if
+ end do
+ if (id == max_models) error stop 1
+ end subroutine extend_ar_models_list
+
+ subroutine make_available_ar_models_list(id)
+ !! Make the ArModel id available for allocation
+ integer(c_int), intent(in) :: id
+ free_ar_model(id) = .true.
+ end subroutine make_available_ar_models_list
+
+ ! ==========================================================================
+ ! Cubic Mixing rules
+ ! --------------------------------------------------------------------------
+ subroutine set_mhv(ar_id, ge_id, q)
+ !! Michelsen's Modified Huron-Vidal 1 with constant `q_1` parameter
+ use yaeos, only: MHV, CubicEoS
+ integer(c_int), intent(in) :: ar_id
+ integer(c_int), intent(in) :: ge_id
+ real(c_double), intent(in) :: q
+
+ type(MHV) :: mixrule
+
+ ar_model = ar_models(ar_id)%model
+ ge_model = ge_models(ge_id)%model
+
+ select type(ar_model)
+ class is(CubicEoS)
+ mixrule = MHV(ge=ge_model, b=ar_model%b, q=q)
+ deallocate(ar_model%mixrule)
+ ar_model%mixrule = mixrule
+ end select
+
+ call move_alloc(ar_model, ar_models(ar_id)%model)
+ end subroutine set_mhv
+
+ subroutine set_qmr(ar_id, kij, lij)
+ use yaeos, only: QMR, CubicEoS
+ integer(c_int), intent(in) :: ar_id
+ real(c_double) :: kij(:, :)
+ real(c_double) :: lij(:, :)
+
+ type(QMR) :: mixrule
+
+ ar_model = ar_models(ar_id)%model
+
+ select type(ar_model)
+ class is(CubicEoS)
+ mixrule = QMR(k=kij, l=lij)
+ deallocate(ar_model%mixrule)
+ ar_model%mixrule = mixrule
+ end select
+
+ call move_alloc(ar_model, ar_models(ar_id)%model)
+ end subroutine set_qmr
+
+ ! ==========================================================================
+ ! Cubic EoS implementations
+ ! --------------------------------------------------------------------------
+ subroutine pr76(tc, pc, w, id)
+ use yaeos, only: PengRobinson76
+ real(c_double), intent(in) :: tc(:), pc(:), w(:)
+ integer(c_int), intent(out) :: id
+
+ ar_model = PengRobinson76(tc, pc, w)
+ call extend_ar_models_list(id)
+ end subroutine pr76
+
+ subroutine pr78(tc, pc, w, id)
+ use yaeos, only: PengRobinson78
+ real(c_double), intent(in) :: tc(:), pc(:), w(:)
+ integer(c_int), intent(out) :: id
+
+ ar_model = PengRobinson78(tc, pc, w)
+ call extend_ar_models_list(id)
+ end subroutine pr78
+
+ subroutine srk(tc, pc, w, id)
+ use yaeos, only: SoaveRedlichKwong
+ real(c_double), intent(in) :: tc(:), pc(:), w(:)
+ integer(c_int), intent(out) :: id
+ ar_model = SoaveRedlichKwong(tc, pc, w)
+ call extend_ar_models_list(id)
+ end subroutine srk
+
+ subroutine rkpr(tc, pc, w, zc, delta_1, k, id)
+ use yaeos, only: fRKPR => RKPR
+ real(c_double), intent(in) :: tc(:), pc(:), w(:), zc(:)
+ real(c_double), optional, intent(in) :: delta_1(:), k(:)
+ integer(c_int), intent(out) :: id
+
+ if (present(delta_1) .and. present(k)) then
+ ar_model = fRKPR(tc, pc, w, zc, delta_1=delta_1, k=k)
+ elseif (present(delta_1)) then
+ ar_model = fRKPR(tc, pc, w, zc, delta_1=delta_1)
+ elseif (present(k)) then
+ ar_model = fRKPR(tc, pc, w, zc, k=k)
+ else
+ ar_model = fRKPR(tc, pc, w, zc)
+ end if
+ call extend_ar_models_list(id)
+ end subroutine rkpr
+
+ ! ==========================================================================
+ ! Thermodynamic properties
+ ! --------------------------------------------------------------------------
+ subroutine fug_vt(id, n, v, t, lnfug, dlnphidp, dlnphidt, dlnphidn)
+ integer(c_int), intent(in) :: id
+ real(c_double), intent(in) :: n(:), v, t
+ real(c_double), intent(out) :: lnfug(size(n))
+ real(c_double) :: p
+
+ real(c_double), optional, intent(in out) :: &
+ dlnphidp(size(n)), dlnphidt(size(n)), dlnphidn(size(n), size(n))
+
+ call ar_models(id)%model%lnphi_vt(&
+ n, V, T, P, lnfug, dlnPhidP, dlnphidT, dlnPhidn &
+ )
+ end subroutine fug_vt
+
+ ! ==========================================================================
+ ! Phase equilibria
+ ! --------------------------------------------------------------------------
+ subroutine equilibria_state_to_arrays(eq_state, x, y, P, T, Vx, Vy, beta)
+ use yaeos, only: EquilibriaState
+ type(EquilibriaState) :: eq_state
+ real(c_double), intent(out) :: x(:)
+ real(c_double), intent(out) :: y(:)
+ real(c_double), intent(out) :: P
+ real(c_double), intent(out) :: T
+ real(c_double), intent(out) :: Vx
+ real(c_double), intent(out) :: Vy
+ real(c_double), intent(out) :: Beta
+
+ x = eq_state%x
+ y = eq_state%y
+ P = eq_state%p
+ T = eq_state%T
+ Vx = eq_state%Vx
+ Vy = eq_state%Vy
+ beta = eq_state%beta
+ end subroutine equilibria_state_to_arrays
+
+ subroutine flash(id, z, T, P, x, y, k0, Pout, Tout, Vx, Vy, beta)
+ use yaeos, only: EquilibriaState, fflash => flash
+ integer(c_int), intent(in) :: id
+ real(c_double), intent(in) :: z(:)
+ real(c_double), intent(in) :: T
+ real(c_double), intent(in) :: P
+ real(c_double), optional, intent(in out) :: k0(size(z))
+ real(c_double), intent(out) :: x(size(z))
+ real(c_double), intent(out) :: y(size(z))
+ real(c_double), intent(out) :: Pout
+ real(c_double), intent(out) :: Tout
+ real(c_double), intent(out) :: Vx
+ real(c_double), intent(out) :: Vy
+ real(c_double), intent(out) :: beta
+
+ type(EquilibriaState) :: result
+ integer :: iters
+
+ result = fflash(ar_models(id)%model, z, t, p_spec=p, iters=iters)
+ if (.not. allocated(result%x) .or. .not. allocated(result%y)) then
+ Pout = P
+ Tout = T
+ x = z
+ y = z
+ beta = -1
+ Vx = 1
+ Vy = 1
+ return
+ end if
+
+ call equilibria_state_to_arrays(result, x, y, Pout, Tout, Vx, Vy, beta)
+ end subroutine flash
+
+ subroutine saturation_pressure(id, z, T, kind, P, x, y, Vx, Vy, beta)
+ use yaeos, only: EquilibriaState, fsaturation_pressure => saturation_pressure
+ integer(c_int), intent(in) :: id
+ real(c_double), intent(in) :: z(:)
+ real(c_double), intent(in) :: T
+ character(len=15), intent(in) :: kind
+
+ real(c_double), intent(out) :: P
+ real(c_double), intent(out) :: x(size(z))
+ real(c_double), intent(out) :: y(size(z))
+ real(c_double), intent(out) :: Vx, Vy, beta
+
+ real(c_double) :: aux
+
+ type(EquilibriaState) :: sat
+
+ sat = fsaturation_pressure(ar_models(id)%model, z, T, kind)
+ call equilibria_state_to_arrays(sat, x, y, P, aux, Vx, Vy, beta)
+ end subroutine saturation_pressure
+
+ subroutine pt2_phase_envelope(id, z, kind, Ts, Ps, tcs, pcs, T0, P0)
+ use yaeos, only: &
+ saturation_pressure, saturation_temperature, pt_envelope_2ph, &
+ EquilibriaState, PTEnvel2
+ integer(c_int), intent(in) :: id
+ real(c_double), intent(in) :: z(:)
+ character(len=15), intent(in) :: kind
+ real(c_double), intent(out) :: Ts(1000)
+ real(c_double), intent(out) :: Ps(1000)
+ real(c_double), intent(out) :: Tcs(5), Pcs(5)
+ real(c_double), optional, intent(in) :: T0, P0
+
+ real(8) :: makenan, nan
+ type(EquilibriaState) :: sat
+ type(PTEnvel2) :: env
+
+ integer :: i, neval=0
+
+ real(c_double) :: T, P
+
+ makenan=0
+
+ neval = neval + 1
+ nan = makenan/makenan
+ Ts = nan
+ Ps = nan
+ Tcs = nan
+ Pcs = nan
+
+ if (present(T0)) then
+ T = T0
+ else
+ T = 150
+ end if
+
+ if (present(P0)) then
+ P = P0
+ else
+ P = 1
+ end if
+
+ select case(kind)
+ case("bubble")
+ sat = saturation_pressure(ar_models(id)%model, z, T=T, kind=kind)
+ case("dew")
+ sat = saturation_temperature(ar_models(id)%model, z, P=P, kind=kind)
+ case("liquid-liquid")
+ sat = saturation_temperature(ar_models(id)%model, z, P=P, kind=kind)
+ end select
+
+
+ env = pt_envelope_2ph(ar_models(id)%model, z, sat)
+ i = size(env%points)
+ Ts(:i) = env%points%T
+ Ps(:i) = env%points%P
+
+ i = size(env%cps)
+ Tcs(:i) = env%cps%T
+ Pcs(:i) = env%cps%P
+ end subroutine pt2_phase_envelope
+end module yaeos_c
diff --git a/src/adiff/autodiff_api/tapenade/interfaces.f90 b/src/adiff/autodiff_api/tapenade/interfaces.f90
index 57dbb1fc9..576911992 100644
--- a/src/adiff/autodiff_api/tapenade/interfaces.f90
+++ b/src/adiff/autodiff_api/tapenade/interfaces.f90
@@ -1,37 +1,36 @@
-module tapenade_interfaces
+module yaeos__tapenade_interfaces
+ use yaeos__constants, only: pr
implicit none
- interface pushreal8
- subroutine pushreal8(realnum)
- real(8) :: realnum
- end subroutine
-
- subroutine pushreal8array(realnum)
- real(8) :: realnum(:)
- end subroutine
- end interface
+ interface
+ subroutine pushinteger4(i)
+ integer :: i
+ end subroutine
+
+ subroutine popinteger4(i)
+ integer :: i
+ end subroutine
- interface popreal8
- subroutine popreal8(realnum)
- real(8) :: realnum
- end subroutine
- end interface
+ subroutine pushreal8array(a, n)
+ import pr
+ real(pr), dimension(n) :: a
+ integer :: n
+ end subroutine
- interface pushinteger4
- subroutine pushinteger4(intnum)
- integer :: intnum
- end subroutine
- end interface
+ subroutine pushreal8(a)
+ import pr
+ real(pr) :: a
+ end subroutine
- interface popinteger4
- subroutine popinteger4(intnum)
- integer :: intnum
- end subroutine
- end interface
+ subroutine POPREAL8(a)
+ import pr
+ real(pr) :: a
+ end subroutine
- interface pushcontrol1b
- subroutine pushcontrol1b(intnum)
- integer :: intnum
- end subroutine
- end interface
+ subroutine POPREAL8ARRAY(a, n)
+ import pr
+ real(pr), dimension(n) :: a
+ integer :: n
+ end subroutine
+ end interface
end module
\ No newline at end of file
diff --git a/src/consistency/consistency.f90 b/src/consistency/consistency.f90
index f3e2f98fe..d6543bed9 100644
--- a/src/consistency/consistency.f90
+++ b/src/consistency/consistency.f90
@@ -1,7 +1,25 @@
module yaeos__consistency
- !! Tools to evalaute the consistency of Ar and Ge models. This module also
- !! provides subroutines for numeric evaluations of Ar and Ge derivatives from
- !! central finite differences.
+ !! # yaeos__consistency
+ !! Subroutine to evaluate the consistency of thermodynamic models.
+ !!
+ !! # Description
+ !! Tools to evaluate the consistency of \(A^r\) and \(G^E\) models. This
+ !! module also provides subroutines for numerical evaluations of \(A^r\) and
+ !! \(G^E\) derivatives using central finite differences. The purpose of the
+ !! module is to assist in the development of new models and ensure the
+ !! accuracy of the derivatives implementation.
+ !!
+ !! # Examples
+ !! For detailed explanations and examples of each consistency test, please
+ !! refer to the API documentation of each submodule.
+ !!
+ !! - \(A^r\) consistency tests: [[yaeos__consistency_armodel]]
+ !! - \(G^E\) consistency tests: [[yaeos__consistency_gemodel]]
+ !!
+ !! # References
+ !! 1. Michelsen, M. L., & Mollerup, J. M. (2007). Thermodynamic models:
+ !! Fundamentals & computational aspects (2. ed). Tie-Line Publications.
+ !!
! Consistency test for ArModels
use yaeos__consistency_armodel
use yaeos__consistency_gemodel
diff --git a/src/consistency/consistency_tests/consistency_armodel.f90 b/src/consistency/consistency_tests/consistency_armodel.f90
index 39f38ffe1..9775cfc36 100644
--- a/src/consistency/consistency_tests/consistency_armodel.f90
+++ b/src/consistency/consistency_tests/consistency_armodel.f90
@@ -1,34 +1,39 @@
module yaeos__consistency_armodel
- !! Consistency checks of Helmholtz free energy models.
+ !! # yaeos__consistency_armodel
+ !! Consistency checks of Helmholtz free energy models ([[ArModel]]).
!!
+ !! # Description
!! This module contains tools to validate the analityc derivatives of
- !! implmented Helmholtz free energy models (ArModel). Also, allows to
+ !! implmented Helmholtz free energy models ([[ArModel]]). Also, allows to
!! evaluate the consistency tests described in Thermodynamic Models:
!! Fundamentals & Computational Aspects 2 ed. by Michelsen and Mollerup
!! Chapter 2 section 3.
!!
!! Available tools:
!!
- !! - numeric_ar_derivatives: From an instantiated ArModel evaluate all the
- !! Helmholtz free energy derivatives from the central finite difference
- !! method.
+ !! - [[numeric_ar_derivatives]]: From an instantiated [[ArModel]] evaluate
+ !! all the Helmholtz free energy derivatives from the central finite
+ !! difference method.
!!
- !! - ar_consistency: From an instantiated ArModel evaluate all the Michelsen
- !! and Mollerup consistency tests (refer to ar_consistency docs for more
- !! explanations)
+ !! - [[ar_consistency]]: From an instantiated [[ArModel]] evaluate all the
+ !! Michelsen and Mollerup consistency tests.
+ !!
+ !! # References
+ !! 1. Michelsen, M. L., & Mollerup, J. M. (2007). Thermodynamic models:
+ !! Fundamentals & computational aspects (2. ed). Tie-Line Publications.
!!
use yaeos__constants, only: pr, R
use yaeos__models_ar, only: ArModel
- use yaeos__thermoprops, only: enthalpy_residual_vt, gibbs_residual_vt
- use yaeos__thermoprops, only: fugacity_vt, pressure
implicit none
contains
subroutine ar_consistency(&
- eos, n, v, t, eq31, eq33, eq34, eq36, eq37 &
+ eos, n, V, T, eq31, eq33, eq34, eq36, eq37 &
)
- !! Evaluates the Michelsen and Mollerup (MM) consistency tests.
+ !! # ar_consistency
+ !! \(A^r\) models consistency tests.
!!
+ !! # Description
!! The evaluated equations are taken from Fundamentals & Computational
!! Aspects 2 ed. by Michelsen and Mollerup Chapter 2 section 3. The
!! "eq" are evaluations of the left hand side of the following
@@ -68,16 +73,19 @@ subroutine ar_consistency(&
!! \right)_{P,n} + \frac{H^r(T,P,n)}{RT^2} = 0
!! \]
!!
+ !! The consistency test could be applied to any instantiated [[ArModel]]
+ !! as shown in the following example.
+ !!
!! # Examples
!!
!! ```fortran
!! use yaeos, only: pr, SoaveRedlichKwong, ArModel
- !! use yaeos__consistency, only: ar_consistency
+ !! use yaeos__consistency_armodel, only: ar_consistency
!!
!! class(ArModel), allocatable :: model
!! real(pr) :: tc(4), pc(4), w(4)
!!
- !! real(pr) :: n(4), t, v
+ !! real(pr) :: n(4), T, V
!!
!! real(pr) :: eq31, eq33(size(n), size(n)), eq34(size(n)), eq36, eq37
!!
@@ -86,20 +94,25 @@ subroutine ar_consistency(&
!! pc = [45.99, 37.96, 39.23, 40.21]
!! w = [0.0115478, 0.200164, 0.3624, 0.298]
!!
- !! t = 600_pr
- !! v = 0.5_pr
+ !! T = 600_pr
+ !! V = 0.5_pr
!!
!! model = SoaveRedlichKwong(tc, pc, w)
!!
!! call ar_consistency(&
- !! model, n, v, t, eq31=eq31, eq33=eq33, eq34=eq34, eq36=eq36, eq37=eq37 &
+ !! model, n, V, T, eq31=eq31, eq33=eq33, eq34=eq34, eq36=eq36, eq37=eq37 &
!! )
!! ```
+ !! All `eqXX` variables should be close to zero.
+ !!
+ !! # References
+ !! 1. Michelsen, M. L., & Mollerup, J. M. (2007). Thermodynamic models:
+ !! Fundamentals & computational aspects (2. ed). Tie-Line Publications.
!!
- class(ArModel), intent(in) :: eos !! Model
+ class(ArModel), intent(in) :: eos !! Equation of state
real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(in) :: V !! Volume [L]
real(pr), optional, intent(out) :: eq31 !! MM Eq. 31
! TODO real(pr), optional, intent(out) :: eq32
real(pr), optional, intent(out) :: eq33(size(n), size(n)) !! MM Eq. 33
@@ -112,33 +125,31 @@ subroutine ar_consistency(&
! ========================================================================
! Previous calculations
! ------------------------------------------------------------------------
- real(pr) :: Grp, Grv, Hrv, p, dpdn(size(n)), ntot, z
- real(pr) :: lnphi(size(n)), lnphip(size(n)), dlnPhidP(size(n))
+ real(pr) :: Grp, Grv, Hrv, P, dPdn(size(n)), ntot, z
+ real(pr) :: lnphi(size(n)), dlnPhidP(size(n))
real(pr) :: dlnPhidT(size(n)), dlnPhidn(size(n), size(n))
- call pressure(eos, n, v, t, p, dpdn=dpdn)
+ call eos%pressure(n, V, T, P, dPdn=dPdn)
- call gibbs_residual_vt(eos, n, v, t, Grv)
+ call eos%gibbs_residual_vt(n, V, T, Grv)
- call enthalpy_residual_vt(eos, n, v, t, Hr=Hrv)
+ call eos%enthalpy_residual_vt(n, V, T, Hr=Hrv)
- call fugacity_vt(&
- eos, n, v, t, lnphip=lnphip, &
+ call eos%lnphi_vt(&
+ n, V, T, lnPhi=lnPhi, &
dlnPhidP=dlnPhidP, dlnPhidT=dlnPhidT, dlnPhidn=dlnPhidn &
)
ntot = sum(n)
- lnphi(:) = lnphip(:) - log(p)
+ z = P * V / ntot / R / T
- z = p * v / ntot / R / t
-
- Grp = Grv - ntot * R * t * log(z)
+ Grp = Grv - ntot * R * T * log(Z)
! ========================================================================
! Equation 31
! ------------------------------------------------------------------------
- if (present(eq31)) eq31 = sum(n(:) * lnphi(:)) - Grp / (R * t)
+ if (present(eq31)) eq31 = sum(n(:) * lnPhi(:)) - Grp / (R * T)
! ========================================================================
! Equation 32
@@ -172,32 +183,37 @@ subroutine ar_consistency(&
! ========================================================================
! Equation 36
! ------------------------------------------------------------------------
- if (present(eq36)) eq36 = sum(n(:) * dlnPhidP(:)) - (z - 1) * ntot / p
+ if (present(eq36)) eq36 = sum(n(:) * dlnPhidP(:)) - (z - 1) * ntot / P
! ========================================================================
! Equation 37
! ------------------------------------------------------------------------
if (present(eq37)) then
- eq37 = sum(n(:) * dlnPhidT(:)) + Hrv / (R * t**2)
+ eq37 = sum(n(:) * dlnPhidT(:)) + Hrv / (R * T**2)
end if
end subroutine ar_consistency
subroutine numeric_ar_derivatives(&
- eos, n, v, t, d_n, d_v, d_t, &
+ eos, n, V, T, d_n, d_v, d_t, &
Ar, ArV, ArT, Arn, ArV2, ArT2, ArTV, ArVn, ArTn, Arn2 &
)
+ !! # numeric_ar_derivatives
!! Evaluate the Helmholtz derivatives with central finite difference.
!!
+ !! # Description
+ !! Tool to facilitate the development of new [[ArModel]] by testing
+ !! the implementation of analytic derivatives.
+ !!
!! # Examples
!!
!! ```fortran
!! use yaeos, only: pr, SoaveRedlichKwong, ArModel
- !! use yaeos__consistency, only: numeric_ar_derivatives
+ !! use yaeos__consistency_armodel, only: numeric_ar_derivatives
!!
!! class(ArModel), allocatable :: model
!! real(pr) :: tc(4), pc(4), w(4)
!!
- !! real(pr) :: n(4), t, v
+ !! real(pr) :: n(4), T, V
!!
!! real(pr) :: Ar_num, ArV_num, ArT_num, Arn_num(size(n)), ArV2_num, ArT2_num
!! real(pr) :: ArTV_num, ArVn_num(size(n)), ArTn_num(size(n))
@@ -208,23 +224,23 @@ subroutine numeric_ar_derivatives(&
!! pc = [45.99, 37.96, 39.23, 40.21]
!! w = [0.0115478, 0.200164, 0.3624, 0.298]
!!
- !! t = 600_pr
- !! v = 0.5_pr
+ !! T = 600_pr
+ !! V = 0.5_pr
!!
!! model = SoaveRedlichKwong(tc, pc, w)
!!
!! call numeric_ar_derivatives(&
- !! model, n, v, t, d_n = 0.0001_pr, d_v = 0.0001_pr, d_t = 0.01_pr, &
+ !! model, n, V, T, d_n = 0.0001_pr, d_v = 0.0001_pr, d_t = 0.01_pr, &
!! Ar=Ar_num, ArV=ArV_num, ArT=ArT_num, ArTV=ArTV_num, ArV2=ArV2_num, &
!! ArT2=ArT2_num, Arn=Arn_num, ArVn=ArVn_num, ArTn=ArTn_num, &
!! Arn2=Arn2_num &
!! )
!! ```
!!
- class(ArModel), intent(in) :: eos !! Model
+ class(ArModel), intent(in) :: eos !! Equation of state
real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(in) :: V !! Volume [L]
real(pr), intent(in) :: d_n !! Moles finite difference step
real(pr), intent(in) :: d_t !! Temperature finite difference step
real(pr), intent(in) :: d_v !! Volume finite difference step
@@ -248,15 +264,15 @@ subroutine numeric_ar_derivatives(&
! Ar valuations
! ------------------------------------------------------------------------
! on point valuation
- call eos%residual_helmholtz(n, v, t, Ar=Ar)
+ call eos%residual_helmholtz(n, V, T, Ar=Ar)
! ========================================================================
! Central numeric derivatives
! ------------------------------------------------------------------------
! Volume
if (present(ArV) .or. present(ArV2)) then
- call eos%residual_helmholtz(n, v + d_v, t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n, v - d_v, t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n, V + d_v, T, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n, V - d_v, T, Ar=Ar_aux2)
if (present(ArV)) ArV = (Ar_aux1 - Ar_aux2) / (2 * d_v)
if (present(ArV2)) ArV2 = (Ar_aux1 - 2 * Ar + Ar_aux2) / d_v**2
@@ -264,8 +280,8 @@ subroutine numeric_ar_derivatives(&
! Temperature
if (present(ArT) .or. present(ArT2)) then
- call eos%residual_helmholtz(n, v, t + d_t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n, v, t - d_t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n, V, T + d_t, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n, V, T - d_t, Ar=Ar_aux2)
if (present(ArT)) ArT = (Ar_aux1 - Ar_aux2) / (2 * d_t)
if (present(ArT2)) ArT2 = (Ar_aux1 - 2 * Ar + Ar_aux2) / d_t**2
@@ -279,8 +295,8 @@ subroutine numeric_ar_derivatives(&
dn_aux1 = 0.0_pr
dn_aux1(i) = d_n
- call eos%residual_helmholtz(n + dn_aux1, v, t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n - dn_aux1, v, t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n + dn_aux1, V, T, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n - dn_aux1, V, T, Ar=Ar_aux2)
Arn(i) = (Ar_aux1 - Ar_aux2) / (2 * d_n)
end do
@@ -291,10 +307,10 @@ subroutine numeric_ar_derivatives(&
! ------------------------------------------------------------------------
! Temperature - Volume
if (present(ArTV)) then
- call eos%residual_helmholtz(n, v + d_v, t + d_t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n, v + d_v, t - d_t, Ar=Ar_aux2)
- call eos%residual_helmholtz(n, v - d_v, t + d_t, Ar=Ar_aux3)
- call eos%residual_helmholtz(n, v - d_v, t - d_t, Ar=Ar_aux4)
+ call eos%residual_helmholtz(n, V + d_v, T + d_t, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n, V + d_v, T - d_t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n, V - d_v, T + d_t, Ar=Ar_aux3)
+ call eos%residual_helmholtz(n, V - d_v, T - d_t, Ar=Ar_aux4)
ArTV = (Ar_aux1 - Ar_aux2 - Ar_aux3 + Ar_aux4) / (4 * d_t * d_v)
end if
@@ -307,10 +323,10 @@ subroutine numeric_ar_derivatives(&
dn_aux1 = 0.0_pr
dn_aux1(i) = d_n
- call eos%residual_helmholtz(n + dn_aux1, v, t + d_t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n + dn_aux1, v, t - d_t, Ar=Ar_aux2)
- call eos%residual_helmholtz(n - dn_aux1, v, t + d_t, Ar=Ar_aux3)
- call eos%residual_helmholtz(n - dn_aux1, v, t - d_t, Ar=Ar_aux4)
+ call eos%residual_helmholtz(n + dn_aux1, V, T + d_t, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n + dn_aux1, V, T - d_t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n - dn_aux1, V, T + d_t, Ar=Ar_aux3)
+ call eos%residual_helmholtz(n - dn_aux1, V, T - d_t, Ar=Ar_aux4)
ArTn(i) = &
(Ar_aux1 - Ar_aux2 - Ar_aux3 + Ar_aux4) / (4 * d_t * d_n)
@@ -325,10 +341,10 @@ subroutine numeric_ar_derivatives(&
dn_aux1 = 0.0_pr
dn_aux1(i) = d_n
- call eos%residual_helmholtz(n + dn_aux1, v + d_v, t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n + dn_aux1, v - d_v, t, Ar=Ar_aux2)
- call eos%residual_helmholtz(n - dn_aux1, v + d_v, t, Ar=Ar_aux3)
- call eos%residual_helmholtz(n - dn_aux1, v - d_v, t, Ar=Ar_aux4)
+ call eos%residual_helmholtz(n + dn_aux1, V + d_v, T, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n + dn_aux1, V - d_v, T, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n - dn_aux1, V + d_v, T, Ar=Ar_aux3)
+ call eos%residual_helmholtz(n - dn_aux1, V - d_v, T, Ar=Ar_aux4)
ArVn(i) = &
(Ar_aux1 - Ar_aux2 - Ar_aux3 + Ar_aux4) / (4 * d_v * d_n)
@@ -345,8 +361,8 @@ subroutine numeric_ar_derivatives(&
dn_aux1 = 0.0_pr
dn_aux1(i) = d_n
- call eos%residual_helmholtz(n + dn_aux1, v, t, Ar=Ar_aux1)
- call eos%residual_helmholtz(n - dn_aux1, v, t, Ar=Ar_aux2)
+ call eos%residual_helmholtz(n + dn_aux1, V, T, Ar=Ar_aux1)
+ call eos%residual_helmholtz(n - dn_aux1, V, T, Ar=Ar_aux2)
Arn2(i, j) = (Ar_aux1 - 2 * Ar + Ar_aux2) / d_n**2
else
@@ -357,16 +373,16 @@ subroutine numeric_ar_derivatives(&
dn_aux2(j) = d_n
call eos%residual_helmholtz(&
- n + dn_aux1 + dn_aux2, v, t, Ar=Ar_aux1 &
+ n + dn_aux1 + dn_aux2, V, T, Ar=Ar_aux1 &
)
call eos%residual_helmholtz(&
- n + dn_aux1 - dn_aux2, v, t, Ar=Ar_aux2 &
+ n + dn_aux1 - dn_aux2, V, T, Ar=Ar_aux2 &
)
call eos%residual_helmholtz(&
- n - dn_aux1 + dn_aux2, v, t, Ar=Ar_aux3 &
+ n - dn_aux1 + dn_aux2, V, T, Ar=Ar_aux3 &
)
call eos%residual_helmholtz(&
- n - dn_aux1 - dn_aux2, v, t, Ar=Ar_aux4 &
+ n - dn_aux1 - dn_aux2, V, T, Ar=Ar_aux4 &
)
Arn2(i, j) = &
diff --git a/src/consistency/consistency_tests/consistency_gemodel.f90 b/src/consistency/consistency_tests/consistency_gemodel.f90
index bc1df08b9..35be22413 100644
--- a/src/consistency/consistency_tests/consistency_gemodel.f90
+++ b/src/consistency/consistency_tests/consistency_gemodel.f90
@@ -1,21 +1,26 @@
module yaeos__consistency_gemodel
- !! Consistency checks of excess Gibbs free energy models.
+ !! # yaeos__consistency_gemodel
+ !! Consistency checks of Helmholtz free energy models ([[GeModel]]).
!!
+ !! # Description
!! This module contains tools to validate the analityc derivatives of
- !! implmented excess Gibbs free energy models (GeModel). Also, allows to
+ !! implmented excess Gibbs free energy models ([[GeModel]]). Also, allows to
!! evaluate the consistency tests described in Thermodynamic Models:
!! Fundamentals & Computational Aspects 2 ed. by Michelsen and Mollerup
!! Chapter 5 section 4.
!!
!! Available tools:
!!
- !! - numeric_ge_derivatives: From an instantiated GeModel evaluate all the
- !! excess Gibbs free energy derivatives from the central finite difference
- !! method.
+ !! - [[numeric_ge_derivatives]]: From an instantiated [[GeModel]] evaluate
+ !! all the excess Gibbs free energy derivatives from the central finite
+ !! difference method.
!!
- !! - ge_consistency: From an instantiated GeModel evaluate all the Michelsen
- !! and Mollerup consistency tests (refer to ge_consistency docs for more
- !! explanations)
+ !! - [[ge_consistency]]: From an instantiated GeModel evaluate all the
+ !! Michelsen and Mollerup consistency tests
+ !!
+ !! # References
+ !! 1. Michelsen, M. L., & Mollerup, J. M. (2007). Thermodynamic models:
+ !! Fundamentals & computational aspects (2. ed). Tie-Line Publications.
!!
use yaeos__constants, only: pr, R
use yaeos__models_ge, only: GeModel
@@ -23,29 +28,39 @@ module yaeos__consistency_gemodel
implicit none
contains
subroutine ge_consistency(model, n, t, eq58, eq59, eq60, eq61)
+ !! # ge_consistency
!! \(G^E\) models consistency tests
!!
!! # Description
!! Evaluate the \(G^E\) models consistency tests described in
!! Thermodynamic Models: Fundamentals & Computational Aspects 2 ed. by
- !! Michelsen and Mollerup (MM) Chapter 5 section 4.
+ !! Michelsen and Mollerup (MM) Chapter 5 section 4. The "eq" are
+ !! evaluations of the left hand side of the following expressions:
+ !!
+ !! Equation 58
!!
!! \[
- !! eq58 = \sum_i^{NC} n_i \text{ln} \gamma_i - \frac{G^E}{RT} = 0
+ !! \sum_i^{NC} n_i \text{ln} \gamma_i - \frac{G^E}{RT} = 0
!! \]
!!
+ !! Equation 59
+ !!
!! \[
- !! eq59 = \text{ln} \gamma_i - \frac{1}{RT}
+ !! \text{ln} \gamma_i - \frac{1}{RT}
!! \frac{\partial G^E}{\partial n_i} = 0
!! \]
!!
+ !! Equation 60
+ !!
!! \[
- !! eq60 = \frac{\partial \text{ln} \gamma_i}{\partial n_j} -
+ !! \frac{\partial \text{ln} \gamma_i}{\partial n_j} -
!! \frac{\partial \text{ln} \gamma_j}{\partial n_i} = 0
!! \]
!!
+ !! Equation 61
+ !!
!! \[
- !! eq61 = \sum_i^{NC} n_i
+ !! \sum_i^{NC} n_i
!! \frac{\partial \text{ln} \gamma_i}{\partial n_j} = 0
!! \]
!!
@@ -95,7 +110,8 @@ subroutine ge_consistency(model, n, t, eq58, eq59, eq60, eq61)
!! ```
!!
!! # References
- !! Thermodynamic Models: Fundamentals & Computational Aspects 2 ed. Michelsen and Mollerup
+ !! 1. Michelsen, M. L., & Mollerup, J. M. (2007). Thermodynamic models:
+ !! Fundamentals & computational aspects (2. ed). Tie-Line Publications.
!!
class(GeModel), intent(in) :: model
!! \(G^E\) model
@@ -160,8 +176,12 @@ end subroutine ge_consistency
subroutine numeric_ge_derivatives(&
model, n, t, d_n, d_t, Ge, GeT, Gen, GeT2, GeTn, Gen2 &
)
- !! # Numeric \(G^E\) model derivatives
- !! Evaluate the excess Gibbs derivatives with central finite difference.
+ !! # numeric_ge_derivatives
+ !! Numeric \(G^E\) model derivatives
+ !!
+ !! # Description
+ !! Tool to facilitate the development of new [[GeModel]] by testing
+ !! the implementation of analytic derivatives.
!!
!! # Examples
!!
@@ -222,7 +242,7 @@ subroutine numeric_ge_derivatives(&
!! ```
!!
class(GeModel), intent(in) :: model
- !!Ge Model
+ !! \(G^E\) model
real(pr), intent(in) :: n(:)
!! Moles number vector
real(pr), intent(in) :: t
diff --git a/src/fitting/kij_lij.f90 b/src/fitting/fit_kij_lij.f90
similarity index 91%
rename from src/fitting/kij_lij.f90
rename to src/fitting/fit_kij_lij.f90
index d58cc300a..5ba755727 100644
--- a/src/fitting/kij_lij.f90
+++ b/src/fitting/fit_kij_lij.f90
@@ -46,11 +46,10 @@ module yaeos__fitting_fit_kij_lij
contains
- function model_from_X(problem, X) result(model)
+ subroutine model_from_X(problem, X)
use yaeos, only: R, RKPR, PengRobinson78, ArModel, QMR, CubicEoS
real(pr), intent(in) :: X(:)
- class(FitKijLij), intent(in) :: problem
- class(ArModel), allocatable :: model
+ class(FitKijLij), intent(in out) :: problem
real(pr) :: kij(nc, nc), lij(nc, nc)
@@ -62,8 +61,7 @@ function model_from_X(problem, X) result(model)
lij(1, 2) = X(2)
lij(2, 1) = X(2)
- model = problem%model
-
+ associate(model => problem%model)
select type (model)
class is (CubicEoS)
associate (mr => model%mixrule)
@@ -74,6 +72,7 @@ function model_from_X(problem, X) result(model)
end select
end associate
end select
- end function model_from_X
+ end associate
+ end subroutine
end module yaeos__fitting_fit_kij_lij
diff --git a/src/fitting/fit_nrtl_mhv.f90 b/src/fitting/fit_nrtl_mhv.f90
new file mode 100644
index 000000000..a3e2ee77e
--- /dev/null
+++ b/src/fitting/fit_nrtl_mhv.f90
@@ -0,0 +1,55 @@
+module yaeos__fitting_fit_nrtl_mhv
+ use yaeos__constants, only: pr
+ use yaeos__fitting, only: FittingProblem
+ use yaeos__models, only: ArModel, NRTL, CubicEoS, MHV
+ use forsus, only: Substance
+ implicit none
+
+ integer, parameter :: nc = 2
+
+ type, extends(FittingProblem) :: FitMHVNRTL
+ logical :: fit_nrtl = .false.
+ logical :: fit_lij = .false.
+ contains
+ procedure :: get_model_from_X => model_from_X
+ end type FitMHVNRTL
+
+contains
+
+ subroutine model_from_X(problem, X)
+ use yaeos, only: R, RKPR, PengRobinson78, ArModel, QMR, CubicEoS
+ use yaeos__models_ar_cubic_quadratic_mixing, only: RKPR_D1mix
+ class(FitMHVNRTL), intent(in out) :: problem
+ real(pr), intent(in) :: X(:)
+ type(NRTL) :: ge
+
+ real(pr) :: a(nc, nc), b(nc, nc), c(nc, nc)
+
+ a=0; b=0; c=0
+
+ a(1, 2) = x(1)
+ a(2, 1) = x(2)
+
+ b(1, 2) = x(3)
+ b(2, 1) = x(4)
+
+ c(1, 2) = x(5)
+ c(2, 1) = x(6)
+
+ ge = NRTL(a, b, c)
+
+ associate (model => problem%model)
+ select type(model)
+ class is (CubicEoS)
+ associate(mr => model%mixrule)
+ select type (mr)
+ class is (MHV)
+ if (problem%fit_lij) mr%l(1, 2) = x(7)
+ if (problem%fit_lij) mr%l(2, 1) = x(7)
+ if (problem%fit_nrtl) mr%ge = ge
+ end select
+ end associate
+ end select
+ end associate
+ end subroutine model_from_X
+end module yaeos__fitting_fit_nrtl_mhv
diff --git a/src/fitting/fitting.f90 b/src/fitting/fitting.f90
index 8ba3b9611..761081e97 100644
--- a/src/fitting/fitting.f90
+++ b/src/fitting/fitting.f90
@@ -26,21 +26,17 @@ module yaeos__fitting
end type FittingProblem
abstract interface
- function model_from_X(problem, X)
+ subroutine model_from_X(problem, X)
!! Function that returns a setted model from the parameters vector
import ArModel, FittingProblem, pr
- class(FittingProblem), intent(in) :: problem
+ class(FittingProblem), intent(in out) :: problem
real(pr), intent(in) :: X(:)
-
- class(ArModel), allocatable :: model_from_X
- end function model_from_X
+ end subroutine model_from_X
end interface
type(bar_object), private :: bar
integer, private :: count
- class(ArModel), private, allocatable :: model
-
contains
real(pr) function optimize(X, func_data) result(y)
@@ -55,13 +51,14 @@ real(pr) function optimize(X, func_data) result(y)
type(nlopt_opt) :: opt !! Optimizer
type(nlopt_func) :: f !! Function to optimize
integer :: stat
-
+ integer :: i
+
count = 0
call bar%initialize(&
prefix_string='Fitting... ',&
width=1, spinner_string='⠋', spinner_color_fg='blue', &
min_value=0._pr, max_value=100._pr &
- )
+ )
call bar%start
! opt = nlopt_opt(nlopt_algorithm_enum%LN_NELDERMEAD, size(X))
@@ -71,7 +68,12 @@ real(pr) function optimize(X, func_data) result(y)
f = create_nlopt_func(fobj, f_data=func_data)
- dx = func_data%parameter_step
+ if (.not. allocated(func_data%parameter_step)) then
+ dx = [(0.05_pr, i=1, size(X))]
+ else
+ dx = func_data%parameter_step
+ end if
+
call opt%set_ftol_rel(func_data%solver_tolerance)
call opt%set_initial_step(dx)
@@ -106,60 +108,76 @@ real(pr) function fobj(x, gradient, func_data)
class is(FittingProblem)
fobj = error_function(X, func_data)
if (func_data%verbose) then
- call bar%update(current=real(count,pr)/(count + 100))
- write(*, "(E15.4, 2x)", advance="no") fobj
+ call bar%update(current=real(count,pr)/(count + 100))
+ write(*, "(E15.4, 2x)", advance="no") fobj
end if
end select
- write(2, *) X, fobj
+ write(2, "(*(E15.4,2x))") X, fobj
write(1, "(/)")
-
+
count = count + 1
end function fobj
real(pr) function error_function(X, func_data) result(fobj)
+ !! # `error_function`
+ !! Error function for phase-equilibria optimization. Using two-phase
+ !! points and an error function of:
+ !!
+ !! \[
+ !! FO = \sum_i (\frac{P_i^{exp} - P_i^{calc}}{P_i^{exp}})^2
+ !! + \sum_i (y_i^{exp} - y_i^{calc})**2
+ !! + \sum_i (x_i^{exp} - x_i^{calc})**2
+ !! \]
use yaeos__math, only: sq_error
real(pr), intent(in) :: X(:)
- class(FittingProblem), intent(in) :: func_data
+ class(FittingProblem) :: func_data
type(EquilibriaState) :: model_point !! Each solved point
type(EquilibriaState) :: exp_point
integer :: i
- model = func_data%get_model_from_X(X)
+ ! Update the problem model to the new vector of parameters
+ call func_data%get_model_from_X(X)
+
fobj = 0
- do i=1, size(func_data%experimental_points)
- exp_point = func_data%experimental_points(i)
-
- select case(exp_point%kind)
- case("bubble")
- model_point = saturation_pressure(&
- model, exp_point%x, exp_point%t, kind="bubble", &
- p0=exp_point%p, y0=exp_point%y &
- )
- case("dew")
- model_point = saturation_pressure(&
- model, exp_point%y, exp_point%t, kind="dew", &
- p0=exp_point%p, y0=exp_point%x &
- )
- case("liquid-liquid")
- model_point = saturation_pressure(&
- model, exp_point%x, exp_point%t, kind="liquid-liquid", &
- p0=exp_point%p, y0=exp_point%y &
- )
-
- end select
-
- fobj = fobj + sq_error(exp_point%p, model_point%p)
- fobj = fobj + maxval(sq_error(exp_point%y, model_point%y))
- fobj = fobj + maxval(sq_error(exp_point%x, model_point%x))
- write(1, *) exp_point, model_point
-
- if(isnan(fobj)) then
- fobj = 1e6
- exit
- end if
- end do
+ associate( model => func_data%model )
+
+ ! Calculate each point and calculate its error.
+ ! if at some point there is a NaN value, assign a big number and
+ ! exit
+ do i=1, size(func_data%experimental_points)
+ exp_point = func_data%experimental_points(i)
+
+ select case(exp_point%kind)
+ case("bubble")
+ model_point = saturation_pressure(&
+ model, exp_point%x, exp_point%t, kind="bubble", &
+ p0=exp_point%p, y0=exp_point%y &
+ )
+ case("dew")
+ model_point = saturation_pressure(&
+ model, exp_point%y, exp_point%t, kind="dew", &
+ p0=exp_point%p, y0=exp_point%x &
+ )
+ case("liquid-liquid")
+ model_point = saturation_pressure(&
+ model, exp_point%x, exp_point%t, kind="liquid-liquid", &
+ p0=exp_point%p, y0=exp_point%y &
+ )
+ end select
+
+ fobj = fobj + sq_error(exp_point%p, model_point%p)
+ fobj = fobj + maxval(sq_error(exp_point%y, model_point%y))
+ fobj = fobj + maxval(sq_error(exp_point%x, model_point%x))
+ write(1, *) exp_point, model_point
+
+ if(isnan(fobj)) then
+ ! fobj = 1e6
+ exit
+ end if
+ end do
+ end associate
end function error_function
end module yaeos__fitting
diff --git a/src/math/linalg.f90 b/src/math/linalg.f90
index d293fefde..82523eb85 100644
--- a/src/math/linalg.f90
+++ b/src/math/linalg.f90
@@ -26,7 +26,7 @@ subroutine dgesv(n, nrhs, a, lda, ipiv, b, ldb, info)
real(dp) :: b(n)
integer :: ldb
integer :: info
- end subroutine
+ end subroutine dgesv
end interface
n = size(a, dim=1)
@@ -42,4 +42,110 @@ subroutine dgesv(n, nrhs, a, lda, ipiv, b, ldb, info)
x = b_lapack
end function solve_system
-end module
\ No newline at end of file
+
+ subroutine cubic_roots(parameters, real_roots, complex_roots, flag)
+ use stdlib_sorting, only: sort
+ real(pr), parameter :: pi=atan(1.0_pr) * 4.0_pr
+ real(pr), intent(in) :: parameters(4)
+ real(pr), intent(out) :: real_roots(3)
+ complex(pr), intent(out) :: complex_roots(3)
+ integer, intent(out) :: flag
+ !! flag that identifies which case the solution is
+ !! - `0`: 3 real rotos, one of them repeated (use real_roots(1) and real_roots(2))
+ !! - `1`: 1 real root, 2 complex roots.
+ !! Use real_roots(1) and complex_roots(1) and complex_roots(2)
+ !! - `-1`: 3 real roots, all different
+
+ real(pr) :: p, q, u, v, nan
+ real(pr) :: disc, theta
+
+ nan = 0
+ nan = nan/nan
+
+ associate(&
+ a => parameters(1), b => parameters(2), &
+ c => parameters(3), d => parameters(4)&
+ )
+
+ p = c/a - b**2/(3*a**2)
+ q = d/a - b*c/(3*a**2) + 2*b**3/(27*a**3)
+
+ disc = q**2 + 4 * p**3 / 27
+ real_roots = nan
+ complex_roots = nan
+
+ if (abs(disc) < 1e-15) then
+ flag = 0
+ real_roots(1) = 3*q/p
+ real_roots(2) = -3*q/(2*p)
+ real_roots(3) = real_roots(2)
+ elseif (disc < 0) then
+ flag = -1
+ theta = acos(0.5_pr * 3 * q / p * sqrt(-3/p))
+ real_roots(1) = 2 * sqrt(-p/3) * cos(theta/3)
+ real_roots(2) = 2 * sqrt(-p/3) * cos((theta + 2*pi)/3)
+ real_roots(3) = 2 * sqrt(-p/3) * cos((theta + 4*pi)/3)
+ call sort(real_roots)
+ elseif (disc > 0) then
+ flag = 1
+ u = ((-q + sqrt(disc))/2)
+ v = ((-q - sqrt(disc))/2)
+
+ u = sign(abs(u)**(1.0_pr/3.0_pr), u)
+ v = sign(abs(v)**(1.0_pr/3.0_pr), v)
+ real_roots(1) = u + v
+ endif
+ real_roots = real_roots - b/(3*a)
+ end associate
+ end subroutine cubic_roots
+
+ subroutine cubic_roots_rosendo(parameters, real_roots, complex_roots, flag)
+ use stdlib_sorting, only: sort
+ real(pr), parameter :: pi=atan(1.0_pr) * 4.0_pr
+ real(pr), intent(in) :: parameters(4)
+ real(pr), intent(out) :: real_roots(3)
+ complex(pr), intent(out) :: complex_roots(3)
+ integer, intent(out) :: flag
+
+ real(pr) :: d1, d2, d3, Q, R, A, B, theta, alp, bet, gam
+ integer :: i
+
+ d1 = parameters(2) / parameters(1)
+ d2 = parameters(3) / parameters(1)
+ d3 = parameters(4) / parameters(1)
+
+ Q = (d1**2 - 3*d2) / 9.0_pr
+ R = (2*d1**3 - 9*d1*d2 + 27*d3) / 54.0_pr
+
+ if (R**2 <= Q**3) then
+ theta = acos(R / sqrt(Q**3))
+
+ real_roots(1) = -2 * sqrt(Q) * cos(theta / 3.0_pr) - d1 / 3.0_pr
+ real_roots(2) = -2 * sqrt(Q) * cos((theta + 2 * pi) / 3.0_pr) - d1 / 3.0_pr
+ real_roots(3) = -2 * sqrt(Q) * cos((theta - 2 * pi) / 3.0_pr) - d1 / 3.0_pr
+
+ ! Correction??
+ ! do i=1,100
+ ! real_roots(1) = -d1 - (real_roots(2) + real_roots(3))
+ ! real_roots(2) = (d2 - real_roots(1) * real_roots(3)) / (real_roots(1) + real_roots(3))
+ ! real_roots(3) = -d3 / (real_roots(1) * real_roots(2))
+ ! end do
+
+ call sort(real_roots)
+ flag = -1
+ else
+ A = - sign((abs(R) + sqrt(R**2 - Q**3))**(1.0_pr/3.0_pr), R)
+
+ if (abs(A) < 1e-6) then
+ A = 0.0_pr
+ B = 0.0_pr
+ else
+ B = Q / A
+ end if
+
+ real_roots = (A + B) - d1 / 3.0_pr
+ flag = 1
+ end if
+ end subroutine
+
+end module yaeos__math_linalg
diff --git a/src/math/math.f90 b/src/math/math.f90
index 292b1ac0b..6e42d8610 100644
--- a/src/math/math.f90
+++ b/src/math/math.f90
@@ -27,7 +27,23 @@ module yaeos__math
!! ```
use yaeos__math_continuation, only: continuation
- use yaeos__math_linalg, only: solve_system
+ use yaeos__math_linalg, only: solve_system, cubic_roots
+ use yaeos__constants, only: pr
+
+ implicit none
+
+ abstract interface
+ subroutine f_1d(x, f, df)
+ import pr
+ real(pr), intent(in) :: x
+ real(pr), intent(out) :: f
+ real(pr), intent(out) :: df
+ end subroutine f_1d
+ end interface
+
+ interface newton
+ module procedure :: newton_1d
+ end interface newton
contains
elemental real(pr) function sq_error(exp, pred)
@@ -62,11 +78,38 @@ function dx_to_dn(x, dx) result(dn)
real(pr) :: dn(size(x))
real(pr) :: sum_xdx
-
+
dn = 0
sum_xdx = sum(x * dx)
dn = dx - sum_xdx
end function dx_to_dn
+
+ subroutine newton_1d(f, x, tol, max_iters)
+ procedure(f_1d) :: f
+ real(pr), intent(in out) :: x
+ real(pr), intent(in) :: tol
+ integer, intent(in) :: max_iters
+
+ integer :: i
+ real(pr) :: fval, df, step
+
+
+ fval = 10
+ step = 10
+
+ do i=1, max_iters
+ if (abs(fval) < tol .or. abs(step) < tol) exit
+ call f(x, fval, df)
+
+ step = fval/df
+
+ do while (abs(step) > 0.5 * abs(x))
+ step = step/2
+ end do
+
+ x = x - step
+ end do
+ end subroutine newton_1d
end module yaeos__math
diff --git a/src/models/excess_gibbs/group_contribution/model_parameters.f90 b/src/models/excess_gibbs/group_contribution/model_parameters.f90
index 16ec0fa74..0b029f4d8 100644
--- a/src/models/excess_gibbs/group_contribution/model_parameters.f90
+++ b/src/models/excess_gibbs/group_contribution/model_parameters.f90
@@ -23,10 +23,14 @@ module yaeos__models_ge_group_contribution_model_parameters
!! \(c_{ij}\) for the maingroups interaction parameters. In the case of
!! the classic UNIFAC model that only requires \(a_{ij}\) parameters, the
!! \(b_{ij}\) and \(c_{ij}\) must be set as null matrixes.
- !! The documentation and source code of `yaeos` `UNIFACParameters`
+ !! The documentation and source code of `yaeos` [[UNIFACParameters]]
!! function could be consulted to understand how to instantiate a
- !! `GeGCModelParameters` object with the classic liquid-vapor UNIFAC
- !! parameters defined in: https://www.ddbst.com/published-parameters-unifac.html
+ !! [[GeGCModelParameters]] object with the classic liquid-vapor UNIFAC
+ !! parameters defined in DDBST.
+ !!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
!!
integer, allocatable :: subgroups_ids(:)
!! ID of each model's subgroup
@@ -82,6 +86,10 @@ function get_subgroup_index(self, subgroup_id) result(subgroup_idx)
!! print *, parameters%get_subgroup_index(178) ! Will print: 112
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_id
@@ -114,6 +122,10 @@ function get_maingroup_index(self, maingroup_id) result(maingroup_idx)
!! print *, parameters%get_maingroup_index(55) ! Will print: 52
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: maingroup_id
@@ -146,6 +158,10 @@ function get_subgroup_maingroup(self, subgroup_id) result(subgroup_maingroup)
!! print *, parameters%get_subgroup_maingroup(16) ! Will print: 7
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_id
@@ -182,6 +198,10 @@ function get_subgroup_R(self, subgroup_id) result(subgroup_R)
!! print *, parameters%get_subgroup_R(1) ! Will print: 0.9011
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_id
@@ -218,6 +238,10 @@ function get_subgroup_Q(self, subgroup_id) result(subgroup_Q)
!! print *, parameters%get_subgroup_Q(1) ! Will print: 0.8480
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_id
@@ -234,10 +258,10 @@ end function get_subgroup_Q
function get_maingroups_aij(self, maingroup_i_id, maingroup_j_id) result(aij)
!! # get_maingroups_aij
- !! Get the interaction parameter \(a_{ij} \)
+ !! Get the interaction parameter \(a_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(a_{ij} \) of the maingroups `i` and `j`
+ !! Get the interaction parameter \(a_{ij}\) of the maingroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -254,6 +278,10 @@ function get_maingroups_aij(self, maingroup_i_id, maingroup_j_id) result(aij)
!! print *, parameters%get_maingroups_aij(1, 7) ! prints: 1318.0000
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: maingroup_i_id
@@ -261,7 +289,7 @@ function get_maingroups_aij(self, maingroup_i_id, maingroup_j_id) result(aij)
integer, intent(in) :: maingroup_j_id
!! ID of the maingroup `j`
real(pr) :: aij
- !! Interaction parameter \(a_{ij} \)
+ !! Interaction parameter \(a_{ij}\)
integer :: i, j
@@ -273,10 +301,10 @@ end function get_maingroups_aij
function get_maingroups_bij(self, maingroup_i_id, maingroup_j_id) result(bij)
!! # get_maingroups_bij
- !! Get the interaction parameter \(b_{ij} \)
+ !! Get the interaction parameter \(b_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(b_{ij} \) of the maingroups `i` and `j`
+ !! Get the interaction parameter \(b_{ij}\) of the maingroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -293,9 +321,13 @@ function get_maingroups_bij(self, maingroup_i_id, maingroup_j_id) result(bij)
!! print *, parameters%get_maingroups_bij(1, 7) ! prints: 0.0
!! ```
!!
- !! In the example we obtain 0.0 because UNIFAC only have \(a_{ij} \)
+ !! In the example we obtain 0.0 because UNIFAC only have \(a_{ij}\)
!! parameters
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: maingroup_i_id
@@ -303,7 +335,7 @@ function get_maingroups_bij(self, maingroup_i_id, maingroup_j_id) result(bij)
integer, intent(in) :: maingroup_j_id
!! ID of the maingroup `j`
real(pr) :: bij
- !! Interaction parameter \(b_{ij} \)
+ !! Interaction parameter \(b_{ij}\)
integer :: i, j
@@ -315,10 +347,10 @@ end function get_maingroups_bij
function get_maingroups_cij(self, maingroup_i_id, maingroup_j_id) result(cij)
!! # get_maingroups_cij
- !! Get the interaction parameter \(c_{ij} \)
+ !! Get the interaction parameter \(c_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(c_{ij} \) of the maingroups `i` and `j`
+ !! Get the interaction parameter \(c_{ij}\) of the maingroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -338,6 +370,10 @@ function get_maingroups_cij(self, maingroup_i_id, maingroup_j_id) result(cij)
!! In the example we obtain 0.0 because UNIFAC only have \(a_{ij} \)
!! parameters
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: maingroup_i_id
@@ -345,7 +381,7 @@ function get_maingroups_cij(self, maingroup_i_id, maingroup_j_id) result(cij)
integer, intent(in) :: maingroup_j_id
!! ID of the maingroup `j`
real(pr) :: cij
- !! Interaction parameter \(c_{ij} \)
+ !! Interaction parameter \(c_{ij}\)
integer :: i, j
@@ -357,10 +393,10 @@ end function get_maingroups_cij
function get_subgroups_aij(self, subgroup_i_id, subgroup_j_id) result(aij)
!! # get_subgroups_aij
- !! Get the interaction parameter \(a_{ij} \)
+ !! Get the interaction parameter \(a_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(a_{ij} \) of the subgroups `i` and `j`
+ !! Get the interaction parameter \(a_{ij}\) of the subgroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -378,6 +414,10 @@ function get_subgroups_aij(self, subgroup_i_id, subgroup_j_id) result(aij)
!! print *, parameters%get_subgroups_aij(1, 16) ! prints: 1318.0000
!! ```
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_i_id
@@ -385,7 +425,7 @@ function get_subgroups_aij(self, subgroup_i_id, subgroup_j_id) result(aij)
integer, intent(in) :: subgroup_j_id
!! ID of the subgroup `j`
real(pr) :: aij
- !! Interaction parameter \(a_{ij} \)
+ !! Interaction parameter \(a_{ij}\)
integer :: mi_id, mj_id, i, j
@@ -400,10 +440,10 @@ end function get_subgroups_aij
function get_subgroups_bij(self, subgroup_i_id, subgroup_j_id) result(bij)
!! # get_subgroups_bij
- !! Get the interaction parameter \(b_{ij} \)
+ !! Get the interaction parameter \(b_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(b_{ij} \) of the subgroups `i` and `j`
+ !! Get the interaction parameter \(b_{ij}\) of the subgroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -424,6 +464,10 @@ function get_subgroups_bij(self, subgroup_i_id, subgroup_j_id) result(bij)
!! In the example we obtain 0.0 because UNIFAC only have \(a_{ij} \)
!! parameters
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_i_id
@@ -431,7 +475,7 @@ function get_subgroups_bij(self, subgroup_i_id, subgroup_j_id) result(bij)
integer, intent(in) :: subgroup_j_id
!! ID of the subgroup `j`
real(pr) :: bij
- !! Interaction parameter \(b_{ij} \)
+ !! Interaction parameter \(b_{ij}\)
integer :: mi_id, mj_id, i, j
@@ -446,10 +490,10 @@ end function get_subgroups_bij
function get_subgroups_cij(self, subgroup_i_id, subgroup_j_id) result(cij)
!! # get_subgroups_cij
- !! Get the interaction parameter \(c_{ij} \)
+ !! Get the interaction parameter \(c_{ij}\)
!!
!! # Description
- !! Get the interaction parameter \(c_{ij} \) of the subgroups `i` and `j`
+ !! Get the interaction parameter \(c_{ij}\) of the subgroups `i` and `j`
!! ids.
!!
!! # Examples
@@ -470,6 +514,10 @@ function get_subgroups_cij(self, subgroup_i_id, subgroup_j_id) result(cij)
!! In the example we obtain 0.0 because UNIFAC only have \(a_{ij} \)
!! parameters
!!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.dd
+ !! bst.com/published-parameters-unifac.html)
+ !!
class(GeGCModelParameters) :: self
integer, intent(in) :: subgroup_i_id
@@ -477,7 +525,7 @@ function get_subgroups_cij(self, subgroup_i_id, subgroup_j_id) result(cij)
integer, intent(in) :: subgroup_j_id
!! ID of the subgroup `j`
real(pr) :: cij
- !! Interaction parameter \(c_{ij} \)
+ !! Interaction parameter \(c_{ij}\)
integer :: mi_id, mj_id, i, j
diff --git a/src/models/excess_gibbs/group_contribution/unifac.f90 b/src/models/excess_gibbs/group_contribution/unifac.f90
index ca852312b..f89c96174 100644
--- a/src/models/excess_gibbs/group_contribution/unifac.f90
+++ b/src/models/excess_gibbs/group_contribution/unifac.f90
@@ -34,6 +34,41 @@ module yaeos__models_ge_group_contribution_unifac
!! ```
!!
!! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !! 9. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
!!
use yaeos__constants, only: pr, R
use yaeos__models_ge, only: GeModel
@@ -64,7 +99,8 @@ module yaeos__models_ge_group_contribution_unifac
!! ```
!!
!! # References
- !! https://www.ddbst.com/published-parameters-unifac.html
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
integer, allocatable :: groups_ids(:)
!! Indexes (ids) of each subgroup in the main group matrix
integer, allocatable :: number_of_groups(:)
@@ -114,6 +150,44 @@ module yaeos__models_ge_group_contribution_unifac
!!
!! print *, ln_gammas ! result: 0.10505475697637946 0.28073129552766890
!! ```
+ !!
+ !! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !! 9. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
+ !!
integer :: ngroups
!! Total number of individual groups in the mixture
integer :: nmolecules
@@ -193,6 +267,41 @@ end subroutine temperature_dependence
!! \]
!!
!! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !! 9. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
!!
real(pr), allocatable :: Aij(:, :)
contains
@@ -263,8 +372,6 @@ subroutine excess_gibbs(self, n, T, Ge, GeT, GeT2, Gen, GeTn, Gen2)
!! print *, "ln_gammas: ", ln_gammas
!! ```
!!
- !! # References
- !!
class(UNIFAC), intent(in) :: self
!! UNIFAC model
real(pr), intent(in) :: n(:)
@@ -384,7 +491,7 @@ subroutine Ge_combinatorial(self, n, T, Ge, dGe_dn, dGe_dn2)
!! \]
!!
!! # References
- !! SINTEF (https://github.com/thermotools/thermopack)
+ !! 1. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
class(UNIFAC) :: self
real(pr), intent(in) :: n(self%nmolecules)
@@ -598,7 +705,7 @@ subroutine Ge_residual(self, n, T, Ge, dGe_dn, dGe_dn2, dGe_dT, dGe_dT2, dGe_dTn
!! \]
!!
!! # References
- !! SINTEF (https://github.com/thermotools/thermopack)
+ !! 1. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
class(UNIFAC) :: self
real(pr), intent(in) :: n(self%nmolecules)
@@ -896,6 +1003,41 @@ subroutine UNIFAC_temperature_dependence(&
!! \]
!!
!! # References
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !! 9. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
!!
class(UNIFACPsi) :: self
!! \(\psi\) function
@@ -906,9 +1048,9 @@ subroutine UNIFAC_temperature_dependence(&
real(pr), optional, intent(out) :: psi(:, :)
!! \(\psi\)
real(pr), optional, intent(out) :: dpsi_dt(:, :)
- !! \(\frac{d \psi\}{dT} \)
+ !! \(\frac{d \psi}{dT}\)
real(pr), optional, intent(out) :: dpsi_dt2(:, :)
- !! \(\frac{d^2 \psi\}{dT^2} \)
+ !! \(\frac{d^2 \psi}{dT^2}\)
integer :: i, j
integer :: ngroups
@@ -942,7 +1084,7 @@ function thetas_i(nm, ng, parameters, stew, molecules) result(thetas_ij)
!! dependence)
!!
!! # References
- !!
+ !! 1. [SINTEF - Thermopack](https://github.com/thermotools/thermopack)
integer, intent(in) :: nm !! Number of molecules
integer, intent(in) :: ng !! Number of groups
type(GeGCModelParameters), intent(in) :: parameters !! UNIFAC parameters
@@ -1027,7 +1169,8 @@ type(UNIFAC) function setup_unifac(molecules, parameters)
!! ```
!!
!! # References
- !! https://www.ddbst.com/published-parameters-unifac.html
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
!!
type(Groups), intent(in) :: molecules(:)
!! Molecules (Group type) objects
diff --git a/src/models/excess_gibbs/group_contribution/unifac_parameters.f90 b/src/models/excess_gibbs/group_contribution/unifac_parameters.f90
index e87be941d..1c9faf958 100644
--- a/src/models/excess_gibbs/group_contribution/unifac_parameters.f90
+++ b/src/models/excess_gibbs/group_contribution/unifac_parameters.f90
@@ -21,7 +21,41 @@ module yaeos__models_ge_group_contribution_unifac_parameters
!! ```
!!
!! # References
- !! https://www.ddbst.com/published-parameters-unifac.html
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !!
use yaeos__constants, only: pr
use yaeos__models_ge_group_contribution_model_parameters, only: GeGCModelParameters
implicit none
@@ -61,7 +95,7 @@ type(GeGCModelParameters) function UNIFACParameters()
!!
!! ! Model setup
!! ! Disclaimer: the default parameters object can be ommited in the
- !! ! setup_unifac call, because if the parameters argument is not
+ !! ! setup_unifac call, because if the parameters argument is not
!! ! provided, the return of the constructor UNIFACParameters() will be
!! ! used either way. This is just a demostration.
!! model = setup_unifac(molecules, parameters)
@@ -73,7 +107,41 @@ type(GeGCModelParameters) function UNIFACParameters()
!! ```
!!
!! # References
- !! https://www.ddbst.com/published-parameters-unifac.html
+ !! 1. [Dortmund Data Bank Software & Separation Technology](https://www.ddbst
+ !! .com/published-parameters-unifac.html)
+ !! 2. Fredenslund, A., Jones, R. L., & Prausnitz, J. M. (1975).
+ !! Group‐contribution estimation of activity coefficients in nonideal liquid
+ !! mixtures. AIChE Journal, 21(6), 1086–1099.
+ !! [https://doi.org/10.1002/aic.690210607](https://doi.org/10.1002/aic.690210607)
+ !! 3. Skjold-Jorgensen, S., Kolbe, B., Gmehling, J., & Rasmussen, P. (1979).
+ !! Vapor-Liquid Equilibria by UNIFAC Group Contribution. Revision and
+ !! Extension. Industrial & Engineering Chemistry Process Design and
+ !! Development, 18(4), 714–722.
+ !! [https://doi.org/10.1021/i260072a024](https://doi.org/10.1021/i260072a024)
+ !! 4. Gmehling, J., Rasmussen, P., & Fredenslund, A. (1982). Vapor-liquid
+ !! equilibriums by UNIFAC group contribution. Revision and extension. 2.
+ !! Industrial & Engineering Chemistry Process Design and Development, 21(1),
+ !! 118–127.
+ !! [https://doi.org/10.1021/i200016a021](https://doi.org/10.1021/i200016a021)
+ !! 5. Macedo, E. A., Weidlich, U., Gmehling, J., & Rasmussen, P. (1983).
+ !! Vapor-liquid equilibriums by UNIFAC group contribution. Revision and
+ !! extension. 3. Industrial & Engineering Chemistry Process Design and
+ !! Development, 22(4), 676–678.
+ !! [https://doi.org/10.1021/i200023a023](https://doi.org/10.1021/i200023a023)
+ !! 6. Tiegs, D., Rasmussen, P., Gmehling, J., & Fredenslund, A. (1987).
+ !! Vapor-liquid equilibria by UNIFAC group contribution. 4. Revision and
+ !! extension. Industrial & Engineering Chemistry Research, 26(1), 159–161.
+ !! [https://doi.org/10.1021/ie00061a030](https://doi.org/10.1021/ie00061a030)
+ !! 7. Hansen, H. K., Rasmussen, P., Fredenslund, A., Schiller, M., &
+ !! Gmehling, J. (1991). Vapor-liquid equilibria by UNIFAC group
+ !! contribution. 5. Revision and extension. Industrial & Engineering
+ !! Chemistry Research, 30 (10), 2352–2355.
+ !! [https://doi.org/10.1021/ie00058a017](https://doi.org/10.1021/ie00058a017)
+ !! 8. Wittig, R., Lohmann, J., & Gmehling, J. (2003). Vapor−Liquid Equilibria
+ !! by UNIFAC Group Contribution. 6. Revision and Extension. Industrial &
+ !! Engineering Chemistry Research, 42(1), 183–188.
+ !! [https://doi.org/10.1021/ie020506l](https://doi.org/10.1021/ie020506l)
+ !!
! ========================================================================
! UNIFAC subgroups ids definition
! ------------------------------------------------------------------------
diff --git a/src/models/excess_gibbs/nrtl.f90 b/src/models/excess_gibbs/nrtl.f90
index c55fcf297..7d6224854 100644
--- a/src/models/excess_gibbs/nrtl.f90
+++ b/src/models/excess_gibbs/nrtl.f90
@@ -1,5 +1,6 @@
module yaeos__models_ge_NRTL
use yaeos__tapenade_ge_api, only: gemodeltapenade
+ use yaeos__tapenade_interfaces
use yaeos__constants, only: pr, R
implicit none
@@ -29,6 +30,8 @@ module yaeos__models_ge_NRTL
interface NRTL
module procedure :: init
end interface
+
+
contains
type(NRTL) function init(a, b, c)
@@ -376,12 +379,6 @@ subroutine EXCESS_GIBBS_D_B(model, n, nb, nd, ndb, t, tb, td, tdb, ge&
real(pr) :: tempb4
real(pr) :: tempb5
integer :: ad_to
- external PUSHREAL8ARRAY
- external PUSHREAL8
- external PUSHINTEGER4
- external POPINTEGER4
- external POPREAL8
- external POPREAL8ARRAY
integer :: arg10
real(pr) :: result1
temp = sum(n)
diff --git a/src/models/models.f90 b/src/models/models.f90
index 74ad6e164..336a8f3a6 100644
--- a/src/models/models.f90
+++ b/src/models/models.f90
@@ -24,7 +24,7 @@ module yaeos__models
use yaeos__models_base, only: BaseModel
! Residual Helmholtz Models
- use yaeos__models_ar, only: ArModel
+ use yaeos__models_ar, only: ArModel, size
! Cubic EoS models
use yaeos__models_ar_genericcubic, only: &
diff --git a/src/models/residual_helmholtz/ar_models.f90 b/src/models/residual_helmholtz/ar_models.f90
index 306b3979d..583ad108f 100644
--- a/src/models/residual_helmholtz/ar_models.f90
+++ b/src/models/residual_helmholtz/ar_models.f90
@@ -1,5 +1,6 @@
module yaeos__models_ar
- !! Module that defines the basics of a residual Helmholtz energy.
+
+ !! # Module that defines the basics of a residual Helmholtz energy.
!!
!! All the residual properties that are calculated in this library are
!! based on residual Helmholtz Equations of State. Following the book by
@@ -9,9 +10,29 @@ module yaeos__models_ar
!! are used. Because they're the fundamentals for phase equilibria
!! calculation.
!!
- !! @note Later on, third derivative with respect to volume will be included
+ !! @note
+ !! Later on, third derivative with respect to volume will be included
!! since it's importance on calculation of critical points.
- use yaeos__constants, only: pr
+ !! @endnote
+ !!
+ !! # Properties
+ !!
+ !! ## Available properties:
+ !!
+ !! - pressure(n, V, T)
+ !! - fugacity(n, V, T)
+ !! - fugacity(n, P, T, root=[vapor, liquid, stable])
+ !! - volume
+ !!
+ !! Calculate thermodynamic properties using Helmholtz energy as a basis.
+ !! All the routines in this module work with the logic:
+ !!
+ !! ```fortran
+ !! call foo(x, V, T, [dfoodv, dfoodT, ...])
+ !! ```
+ !! Where the user can call the routine of the desired property. And include
+ !! as optional values the desired derivatives of said properties.
+ use yaeos__constants, only: pr, R
use yaeos__models_base, only: BaseModel
implicit none
@@ -27,10 +48,21 @@ module yaeos__models_ar
character(len=:), allocatable :: name !! Name of the model
contains
procedure(abs_residual_helmholtz), deferred :: residual_helmholtz
- !! Method to calculate residual helmholtz energy and derivatives.
procedure(abs_volume_initializer), deferred :: get_v0
- !! Volume initializer
- end type
+ procedure :: lnphi_vt => fugacity_vt
+ procedure :: lnphi_pt => fugacity_pt
+ procedure :: pressure
+ procedure :: volume
+ procedure :: enthalpy_residual_vt
+ procedure :: gibbs_residual_vt
+ procedure :: entropy_residual_vt
+ procedure :: Cv_residual_vt
+ procedure :: Cp_residual_vt
+ end type ArModel
+
+ interface size
+ module procedure :: size_ar_model
+ end interface size
abstract interface
subroutine abs_residual_helmholtz(&
@@ -67,16 +99,396 @@ subroutine abs_residual_helmholtz(&
real(pr), optional, intent(out) :: ArVn(size(n)) !! \(\frac{d^2Ar}{dVn_i}\)
real(pr), optional, intent(out) :: ArTn(size(n)) !! \(\frac{d^2Ar}{dTn_i}\)
real(pr), optional, intent(out) :: Arn2(size(n), size(n))!! \(\frac{d^2Ar}{dn_{ij}}\)
- end subroutine
+ end subroutine abs_residual_helmholtz
function abs_volume_initializer(self, n, p, t)
- !! Initialization of volume.
+ !! Function that provides an initializer value for the liquid-root
+ !! of newton solver of volume. In the case the model will use the
+ !! `volume_michelsen` routine this value should provide the co-volume
+ !! of the model.
import ArModel, pr
class(ArModel), intent(in) :: self !! Ar Model
real(pr), intent(in) :: n(:) !! Moles vector
real(pr), intent(in) :: p !! Pressure [bar]
real(pr), intent(in) :: t !! Temperature [K]
real(pr) :: abs_volume_initializer !! Initial volume [L]
- end function
+ end function abs_volume_initializer
end interface
-end module
+
+contains
+
+ integer pure function size_ar_model(eos)
+ !! Get the size of the model.
+ class(ArModel), intent(in) :: eos
+ size_ar_model = size(eos%components%pc)
+ end function size_ar_model
+
+ subroutine volume(eos, n, P, T, V, root_type)
+ !! # Volume solver routine for residual Helmholtz models.
+ !! Solves volume roots using newton method. Given pressure and temperature.
+ !!
+ !! # Description
+ !! This subroutine solves the volume using a newton method. The variable
+ !! `root_type`
+ !!
+ !! # Examples
+ !!
+ !! ```fortran
+ !! class(ArModel) :: eos
+ !! call eos%volume(n, P, T, V, root_type="liquid")
+ !! call eos%volume(n, P, T, V, root_type="vapor")
+ !! call eos%volume(n, P, T, V, root_type="stable")
+ !! ```
+ use yaeos__constants, only: pr, R
+ use yaeos__math, only: newton
+ class(ArModel), intent(in) :: eos
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(out) :: V !! Volume [L]
+ character(len=*), intent(in) :: root_type
+ !! Desired root-type to solve. Options are:
+ !! `["liquid", "vapor", "stable"]`
+
+ integer :: max_iters=30
+ real(pr) :: tol=1e-7
+
+ real(pr) :: totnRT, GrL, GrV, Gr
+ real(pr) :: Vliq, Vvap
+
+ GrL = HUGE(GrL)
+ GrV = HUGE(GrV)
+
+ totnRT = sum(n) * R * T
+ select case(root_type)
+ case("liquid")
+ Vliq = eos%get_v0(n, P, T) * 1.001_pr
+ call newton(foo, Vliq, tol=tol, max_iters=max_iters)
+ GrL = Gr
+ case("vapor")
+ Vvap = R * T / P
+ call newton(foo, Vvap, tol=tol, max_iters=max_iters)
+ GrV = Gr
+ case("stable")
+ Vliq = eos%get_v0(n, P, T)*1.00001_pr
+ call newton(foo, Vliq, tol=tol, max_iters=max_iters)
+ GrL = Gr
+
+ Vvap = R * T / P
+ call newton(foo, Vvap, tol=tol, max_iters=max_iters)
+ GrV = Gr
+ end select
+
+ if (GrL < GrV) then
+ V = Vliq
+ else
+ V = Vvap
+ end if
+
+ contains
+ subroutine foo(x, f, df)
+ real(pr), intent(in) :: x
+ real(pr), intent(out) :: f, df
+ real(pr) :: Ar, ArV, ArV2, Pcalc, dPcalcdV, Vin
+ Vin = x
+ call eos%residual_helmholtz(n, Vin, T, Ar=Ar, ArV=ArV, ArV2=ArV2)
+ Pcalc = totnRT / Vin - ArV
+ dPcalcdV = -totnRT / Vin**2 - ArV2
+ f = Pcalc - p
+ df = dPcalcdV
+ Gr = Ar + P * Vin - totnRT - totnRT * log(P*Vin/(R*T))
+ end subroutine foo
+ end subroutine volume
+
+ subroutine pressure(eos, n, V, T, P, dPdV, dPdT, dPdn)
+ !! Pressure calculation.
+ !!
+ !! Calculate pressure using residual helmholtz models.
+ !!
+ !! # Examples
+ !! ```fortran
+ !! class(ArModel), allocatable :: eos
+ !! real(pr) :: n(2), t, v, p, dPdV, dPdT, dPdn(2)
+ !! eos = PengRobinson(Tc, Pc, w)
+ !! n = [1.0_pr, 1.0_pr]
+ !! t = 300.0_pr
+ !! v = 1.0_pr
+ !! call eos%pressure(n, V, T, P, dPdV=dPdV, dPdT=dPdT, dPdn=dPdn)
+ !! ```
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: t !! Temperature [K]
+ real(pr), intent(in) :: v !! Volume [L]
+ real(pr), intent(out) :: p !! Pressure [bar]
+ real(pr), optional, intent(out) :: dPdV !! \(\frac{dP}}{dV}\)
+ real(pr), optional, intent(out) :: dPdT !! \(\frac{dP}}{dT}\)
+ real(pr), optional, intent(out) :: dPdn(:) !! \(\frac{dP}}{dn_i}\)
+
+ real(pr) :: totn
+
+ real(pr) :: Ar, ArV, ArV2, ArTV, ArVn(size(eos))
+ integer :: nc
+ logical :: dn
+
+ totn = sum(n)
+ nc = size(n)
+
+ if (present(dPdn)) then
+ call eos%residual_helmholtz(&
+ n, v, t, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, ArVn=ArVn &
+ )
+ else
+ call eos%residual_helmholtz(&
+ n, v, t, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV &
+ )
+ end if
+
+ P = totn * R * T/V - ArV
+ if (present(dPdV)) dPdV = -ArV2 - R*t*totn/V**2
+ if (present(dPdT)) dPdT = -ArTV + totn*R/V
+ if (present(dPdn)) dPdn(:) = R*T/V - ArVn(:)
+ end subroutine pressure
+
+ subroutine fugacity_pt(eos, &
+ n, P, T, V, root_type, lnPhi, dlnPhidP, dlnPhidT, dlnPhidn &
+ )
+ !! Calculate logarithm of fugacity, given pressure and temperature.
+ !!
+ !! This routine will obtain the desired volume root at the specified
+ !! pressure and calculate fugacity at that point.
+ use iso_fortran_env, only: error_unit
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Mixture mole numbers
+ character(len=*), intent(in) :: root_type !! Type of root desired ["liquid", "vapor", "stable"]
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(in) :: T !! Temperature [K]
+
+ real(pr), optional, intent(out) :: lnPhi(size(n)) !! \(\ln(phi)\) vector
+ real(pr), optional, intent(out) :: V !! Volume [L]
+ real(pr), optional, intent(out) :: dlnPhidT(size(n)) !! ln(phi) Temp derivative
+ real(pr), optional, intent(out) :: dlnPhidP(size(n)) !! ln(phi) Presssure derivative
+ real(pr), optional, intent(out) :: dlnPhidn(size(n), size(n)) !! ln(phi) compositional derivative
+
+ real(pr) :: V_in, P_in
+
+ call eos%volume(n, P=P, T=T, V=V_in, root_type=root_type)
+ call eos%lnphi_vt(n, V_in, T, P_in, lnPhi, dlnPhidP, dlnPhidT, dlnPhidn)
+
+ if(present(V)) V = V_in
+
+ ! Check if the calculated pressure is the same as the input pressure.
+ if(abs(P_in - P) > 1e-2) then
+ write(error_unit, *) "WARN: possible bad root solving: ", P_in, P
+ end if
+ end subroutine fugacity_pt
+
+ subroutine fugacity_vt(eos, &
+ n, V, T, P, lnPhi, dlnPhidP, dlnPhidT, dlnPhidn, dPdV, dPdT, dPdn &
+ )
+ !! Calculate fugacity coefficent given volume and temperature.
+ !!
+ !!@note
+ !!While the natural output variable is \(ln \phi_i P\). The calculated
+ !!derivatives will be the derivatives of the fugacity coefficient
+ !!\(ln \phi_i\)
+ !!@endnote
+ !!
+ class(ArModel) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Mixture mole numbers
+ real(pr), intent(in) :: V !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+
+ real(pr), optional, intent(out) :: P !! Pressure [bar]
+ real(pr), optional, intent(out) :: lnPhi(size(n)) !! \(\ln(\phi_i*P)\) vector
+ real(pr), optional, intent(out) :: dlnPhidT(size(n)) !! \(ln(phi_i)\) Temp derivative
+ real(pr), optional, intent(out) :: dlnPhidP(size(n)) !! \(ln(phi_i)\) Presssure derivative
+ real(pr), optional, intent(out) :: dlnPhidn(size(n), size(n)) !! \(ln(phi_i)\) compositional derivative
+ real(pr), optional, intent(out) :: dPdV !! \(\frac{dP}{dV}\)
+ real(pr), optional, intent(out) :: dPdT !! \(\frac{dP}{dT}\)
+ real(pr), optional, intent(out) :: dPdn(:) !! \(\frac{dP}{dn_i}\)
+
+ real(pr) :: Ar, ArTV, ArV, ArV2
+ real(pr), dimension(size(n)) :: Arn, ArVn, ArTn
+ real(pr) :: Arn2(size(n), size(n))
+
+ real(pr) :: dPdV_in, dPdT_in, dPdn_in(size(n))
+ real(pr) :: P_in
+
+ real(pr) :: RT, Z
+
+ real(pr) :: totn
+ integer :: nc, i, j
+
+ totn = sum(n)
+ nc = size(n)
+
+ RT = R*T
+
+ if (present(lnPhi) .and. .not. (&
+ present(dlnPhidn) &
+ .or. present(dlnPhidP) &
+ .or. present(dlnPhidT) &
+ .or. present(P) &
+ )) then
+ call eos%residual_helmholtz(n, v, t, Arn=Arn, ArV=ArV)
+ P_in = totn*RT/V - ArV
+ Z = P_in*V/(totn*RT)
+ lnPhi(:) = Arn(:)/RT - log(Z)
+ return
+ else if (present(dlnPhidn)) then
+ call eos%residual_helmholtz(&
+ n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, &
+ Arn=Arn, ArVn=ArVn, ArTn=ArTn, Arn2=Arn2 &
+ )
+ else
+ call eos%residual_helmholtz(&
+ n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, &
+ Arn=Arn, ArVn=ArVn, ArTn=ArTn &
+ )
+ end if
+
+ P_in = totn*RT/V - ArV
+
+ Z = P_in*V/(totn*RT)
+ if (present(P)) P = P_in
+
+ dPdV_in = -ArV2 - RT*totn/V**2
+ dPdT_in = -ArTV + totn*R/V
+ dPdn_in = RT/V - ArVn
+
+ if (present(lnPhi)) lnPhi = Arn(:)/RT - log(Z)
+ if (present(dlnPhidP)) then
+ dlnPhidP(:) = -dPdn_in(:)/dPdV_in/RT - 1._pr/P_in
+ end if
+ if (present(dlnPhidT)) then
+ dlnPhidT(:) = (ArTn(:) - Arn(:)/T)/RT + dPdn_in(:)*dPdT_in/dPdV_in/RT + 1._pr/T
+ end if
+
+ if (present(dlnPhidn)) then
+ do i = 1, nc
+ do j = i, nc
+ dlnPhidn(i, j) = 1._pr/totn + (Arn2(i, j) + dPdn_in(i)*dPdn_in(j)/dPdV_in)/RT
+ dlnPhidn(j, i) = dlnPhidn(i, j)
+ end do
+ end do
+ end if
+
+ if (present(dPdV)) dPdV = dPdV_in
+ if (present(dPdT)) dPdT = dPdT_in
+ if (present(dPdn)) dPdn = dPdn_in
+ end subroutine fugacity_vt
+
+ subroutine enthalpy_residual_vt(eos, n, V, T, Hr, HrT, HrV, Hrn)
+ !! Calculate residual enthalpy given volume and temperature.
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: t !! Temperature [K]
+ real(pr), intent(in) :: v !! Volume [L]
+ real(pr), intent(out) :: Hr !! Residual enthalpy [bar L / mol]
+ real(pr), optional, intent(out) :: HrT !! \(\frac{dH^r}}{dT}\)
+ real(pr), optional, intent(out) :: HrV !! \(\frac{dH^r}}{dV}\)
+ real(pr), optional, intent(out) :: Hrn(size(n)) !! \(\frac{dH^r}}{dn}\)
+
+ real(pr) :: Ar, ArV, ArT, Arn(size(n))
+ real(pr) :: ArV2, ArT2, ArTV, ArVn(size(n)), ArTn(size(n))
+
+ call eos%residual_helmholtz(&
+ n, v, t, Ar=Ar, ArV=ArV, ArT=ArT, ArTV=ArTV, ArV2=ArV2, ArT2=ArT2, Arn=Arn, ArVn=ArVn, ArTn=ArTn &
+ )
+
+ Hr = Ar - t*ArT - v*ArV
+
+ if (present(HrT)) HrT = - t*ArT2 - v*ArTV
+ if (present(HrV)) HrV = - t*ArTV - v*ArV2
+ if (present(HrN)) HrN(:) = Arn(:) - t*ArTn(:) - v*ArVn(:)
+ end subroutine enthalpy_residual_vt
+
+ subroutine gibbs_residual_VT(eos, n, V, T, Gr, GrT, GrV, Grn)
+ !! Calculate residual Gibbs energy given volume and temperature.
+ use yaeos__constants, only: R
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: V !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(out) :: Gr !! Gibbs energy [bar L / mol]
+ real(pr), optional, intent(out) :: GrT !! \(\frac{dG^r}}{dT}\)
+ real(pr), optional, intent(out) :: GrV !! \(\frac{dG^r}}{dV}\)
+ real(pr), optional, intent(out) :: Grn(size(n)) !! \(\frac{dG^r}}{dn}\)
+
+ real(pr) :: Ar, ArV, ArT, Arn(size(n))
+ real(pr) :: p, dPdV, dPdT, dPdn(size(n)), z, totn
+
+ totn = sum(n)
+ call pressure(eos, n, V, T, P, dPdV=dPdV, dPdT=dPdT, dPdn=dPdn)
+ z = P*V/(totn*R*T)
+
+ call eos%residual_helmholtz(n, v, t, Ar=Ar, ArV=ArV, ArT=ArT, Arn=Arn)
+
+ Gr = Ar + P*V - totn*R*T
+
+ if (present(GrT)) GrT = ArT + V*dPdT - totn*R
+ if (present(GrV)) GrV = ArV + V*dPdV + P
+ if (present(GrN)) GrN(:) = Arn(:) + V*dPdn(:) - R*T
+ end subroutine gibbs_residual_VT
+
+ subroutine entropy_residual_vt(eos, n, V, T, Sr, SrT, SrV, Srn)
+ !! Calculate residual entropy given volume and temperature.
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: V !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(out) :: Sr !! Entropy [bar L / K / mol]
+ real(pr), optional, intent(out) :: SrT !! \(\frac{dS^r}}{dT}\)
+ real(pr), optional, intent(out) :: SrV !! \(\frac{dS^r}}{dV}\)
+ real(pr), optional, intent(out) :: Srn(size(n)) !! \(\frac{dS^r}}{dn}\)
+
+ real(pr) :: Ar, ArT, ArT2, ArTV, ArTn(size(n))
+
+ call eos%residual_helmholtz(&
+ n, v, t, Ar=Ar, ArT=ArT, ArTV=ArTV, ArT2=ArT2, ArTn=ArTn &
+ )
+
+ Sr = - ArT
+
+ if (present(SrT)) SrT = - ArT2
+ if (present(SrV)) SrV = - ArTV
+ if (present(SrN)) SrN = - ArTn
+ end subroutine entropy_residual_vt
+
+ subroutine Cv_residual_vt(eos, n, V, T, Cv)
+ !! Calculate residual heat capacity volume constant given v and t.
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(in) :: V !! Volume [L]
+ real(pr), intent(out) :: Cv !! heat capacity v constant [bar L / K / mol]
+
+ real(pr) :: Ar, ArT2
+
+ call eos%residual_helmholtz(n, V, T, Ar=Ar, ArT2=ArT2)
+
+ Cv = -T*ArT2
+ end subroutine Cv_residual_vt
+
+ subroutine Cp_residual_vt(eos, n, V, T, Cp)
+ !! Calculate residual heat capacity pressure constant given v and t.
+ use yaeos__constants, only: R
+ class(ArModel), intent(in) :: eos !! Model
+ real(pr), intent(in) :: n(:) !! Moles number vector
+ real(pr), intent(in) :: V !! Volume [L]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(out) :: Cp !! heat capacity p constant [bar L / K / mol]
+
+ real(pr) :: Ar, ArT2, Cv, p, dPdT, dPdV, totn
+
+ totn = sum(n)
+
+ call eos%residual_helmholtz(n, V, T, Ar=Ar, ArT2=ArT2)
+
+ call Cv_residual_vt(eos, n, V, T, Cv)
+
+ call pressure(eos, n, V, T, P, dPdV=dPdV, dPdT=dPdT)
+
+ Cp = Cv - T*dPdT**2/dPdV - totn*R
+ end subroutine Cp_residual_vt
+end module yaeos__models_ar
diff --git a/src/models/residual_helmholtz/cubic/generic_cubic.f90 b/src/models/residual_helmholtz/cubic/generic_cubic.f90
index 9821c746d..ea80156b6 100644
--- a/src/models/residual_helmholtz/cubic/generic_cubic.f90
+++ b/src/models/residual_helmholtz/cubic/generic_cubic.f90
@@ -21,12 +21,72 @@ module yaeos__models_ar_genericcubic
end type
type, extends(ArModel) :: CubicEoS
- !! Cubic Equation of State.
+ !! # Cubic Equation of State.
!!
!! Generic Cubic Equation of State as defined by Michelsen and Mollerup
- !! with constant \(\delta_1\) and \(\delta_2\) parameters.
+ !! with a \(\delta_1\) parameter that is not constant,
+ !! and a \(\delta_2\) parameter that depends on it. In the case of a
+ !! two parameter EoS like PengRobinson the \(\delta_1\) is the same for
+ !! all components so it can be considered as a constant instead of a
+ !! variable. The expression of the Equation is:
+ !!
+ !! \[
+ !! P = \frac{RT}{V-B}
+ !! - \frac{D(T_r)}{(V+B\Delta_1)(V+B\Delta_2)}
+ !! \]
class(CubicMixRule), allocatable :: mixrule
- class(AlphaFunction), allocatable :: alpha
+ !! # CubicMixRule derived type.
+ !! Uses the abstract derived type `CubicMixRule` to define the
+ !! mixing rule that the CubicEoS will use. It includes internally
+ !! three methods to calculate the corresponding parameters for the
+ !! Cubic EoS: `Dmix`, `Bmix` and `D1mix`.
+ !!
+ !! # Examples
+ !! ## Calculation of the B parameter.
+ !! ```fortran
+ !! use yaeos, only: CubicEoS, PengRobinson76
+ !! type(CubicEoS) :: eos
+ !! eos = PengRobinson76(tc, pc, w)
+ !! call eos%mixrule%Bmix(n, eos%b, B, dBi, dBij)
+ !! ```
+ !! ## Calculation of the D parameter.
+ !! ```fortran
+ !! use yaeos, only: CubicEoS, PengRobinson76
+ !! type(CubicEoS) :: eos
+ !! eos = PengRobinson76(tc, pc, w)
+ !!
+ !! ! The mixing rule takes the `a` parameters of the components so
+ !! ! they should be calculated externally
+ !! call eos%alpha%alpha(Tr, a, dadt, dadt2)
+ !! a = a * eos%ac
+ !! dadt = dadt * eos%ac / eos%components%Tc
+ !! dadt = dadt * eos%ac / eos%components%Tc**2
+ !! ! Calculate parameter
+ !! call eos%mixrule%Dmix(n, T, a, dadt, dadt2, D, dDdT, dDdT2, dDi, dDidT, dDij)
+ !! ```
+ !! ## Calculation of the D1 parameter.
+ !! ```fortran
+ !! use yaeos, only: CubicEoS, PengRobinson76
+ !! type(CubicEoS) :: eos
+ !! eos = PengRobinson76(tc, pc, w)
+ !! call eos%mixrule%D1mix(n, eos%del1, D1, dD1i, dD1ij)
+ !! ```
+ class(AlphaFunction), allocatable :: alpha
+ !! # AlphaFunction derived type.
+ !! Uses the abstract derived type `AlphaFunction` to define the
+ !! Alpha function that the CubicEoS will use. The Alpha function
+ !! receives the reduced temperature and returns the values of alpha
+ !! and its derivatives, named `a`, `dadt` and `dadt2` respectively.
+ !!
+ !! # Examples
+ !! ## Callign the AlphaFunction of a setted up model.
+ !! ```fortran
+ !! use yaeos, only: CubicEoS, PengRobinson76
+ !!
+ !! type(CubicEoS) :: eos
+ !! eos = PengRobinson76(tc, pc, w)
+ !! call eos%alpha%alpha(Tr, a, dadt, dadt2)
+ !! ```
real(pr), allocatable :: ac(:) !! Attractive critical parameter
real(pr), allocatable :: b(:) !! Repulsive parameter
real(pr), allocatable :: del1(:) !! \(\delta_1\) paramter
@@ -34,6 +94,7 @@ module yaeos__models_ar_genericcubic
contains
procedure :: residual_helmholtz => GenericCubic_Ar
procedure :: get_v0 => v0
+ procedure :: volume => volume
end type
abstract interface
@@ -85,7 +146,7 @@ subroutine GenericCubic_Ar(&
!!
!! \[
!! P = \frac{RT}{V-b}
- ! - \frac{a_c\alpha(T_r)}{(V+b\delta_1)(V+b\delta_2)}
+ !! - \frac{a_c\alpha(T_r)}{(V+b\delta_1)(V+b\delta_2)}
!! \]
!!
!! This routine assumes that the \(\delta_1\) is not a constant parameter
@@ -222,4 +283,130 @@ function v0(self, n, p, t)
call self%mixrule%Bmix(n, self%b, v0, dbi, dbij)
end function
+ subroutine volume(eos, n, P, T, V, root_type)
+ !! # Cubic EoS volume solver
+ !! Volume solver optimized for Cubic Equations of State.
+ !!
+ !! @warn
+ !! This routine intends to use the analyitical solution of the cubic
+ !! equation, but due to errors in the solutions it is not used. And
+ !! the general volume solver by Michelsen is used instead.
+ !! @endwarn
+ !!
+ !! # Description
+ !! Cubic equations can be analytically solved. Using an anallytical
+ !! solution provides the best possible solution in terms of speed and
+ !! precision. This subroutine uses the modified cardano method proposed
+ !! by Rosendo.
+ !!
+ !! # Examples
+ !!
+ !! ```fortran
+ !! use yaeos, only: CubicEoS, PengRobinson
+ !! type(CubicEoS) :: eos
+ !!
+ !! eos = PengRobinson(tc, pc, w)
+ !! ! Possible roots to solve
+ !! call eos%volume(n, P, T, V, "liquid")
+ !! call eos%volume(n, P, T, V, "vapor")
+ !! call eos%volume(n, P, T, V, "stable")
+ !! ```
+ !!
+ !! # References
+ !!
+ !! - [1] "Thermodynamic Models: Fundamental and Computational Aspects",
+ !! Michael L. Michelsen, Jørgen M. Mollerup.
+ !! Tie-Line Publications, Denmark (2004)
+ !! [doi](http://dx.doi.org/10.1016/j.fluid.2005.11.032)
+ !!
+ !! - [2] "A Note on the Analytical Solution of Cubic Equations of State
+ !! in Process Simulation", Rosendo Monroy-Loperena
+ !! [doi](https://dx.doi.org/10.1021/ie2023004)
+ use yaeos__constants, only: R
+ use yaeos__math_linalg, only: cubic_roots, cubic_roots_rosendo
+ use yaeos__models_solvers, only: volume_michelsen
+ class(CubicEoS), intent(in) :: eos
+ real(pr), intent(in) :: n(:), P, T
+ real(pr), intent(out) :: V
+ character(len=*), intent(in) :: root_type
+
+ real(pr) :: z(size(n))
+ real(pr) :: cp(4), rr(3)
+ complex(pr) :: cr(3)
+ integer :: flag
+
+ real(pr) :: V_liq, V_vap
+ real(pr) :: Ar, AT_Liq, AT_Vap
+
+ real(pr) :: Bmix, dBi(size(n)), dBij(size(n), size(n))
+ real(pr) :: D, dDi(size(n)), dDij(size(n), size(n)), dDidT(size(n)), dDdT, dDdT2
+ real(pr) :: D1, D2, dD1i(size(n)), dD1ij(size(n), size(n))
+ real(pr) :: Tr(size(n))
+ real(pr) :: a(size(n)), dadt(size(n)), dadt2(size(n))
+ real(pr) :: totn
+
+ call volume_michelsen(eos, n, P, T, V, root_type)
+ return
+
+ totn = sum(n)
+ z = n/totn
+ Tr = T/eos%components%Tc
+ ! ========================================================================
+ ! Attractive parameter and derivatives
+ ! ------------------------------------------------------------------------
+ call eos%alpha%alpha(Tr, a, dadt, dadt2)
+ a = eos%ac * a
+ dadt = eos%ac * dadt / eos%components%Tc
+ dadt2 = eos%ac * dadt2 / eos%components%Tc**2
+
+ ! ========================================================================
+ ! Mixing rules
+ ! ------------------------------------------------------------------------
+ call eos%mixrule%D1mix(z, eos%del1, D1, dD1i, dD1ij)
+ call eos%mixrule%Bmix(z, eos%b, Bmix, dBi, dBij)
+ call eos%mixrule%Dmix(&
+ z, T, a, dadt, dadt2, D, dDdT, dDdT2, dDi, dDidT, dDij&
+ )
+ D2 = (1._pr - D1)/(1._pr + D1)
+
+ cp(1) = -P
+ cp(2) = -P*Bmix*(D1 + D2 - 1) + R*T
+ cp(3) = -P*(D1*D2*Bmix**2 - D1*Bmix**2 - D2*Bmix**2) + R*T*Bmix*(D1+D2) - D
+ cp(4) = P*D1*D2*Bmix**3 + R*T *D1*D2*Bmix**2 + D*Bmix
+
+ ! call cubic_roots(cp, rr, cr, flag)
+ ! call cubic_roots_rosendo(cp, rr, cr, flag)
+
+ select case(flag)
+ case(-1)
+ V_liq = rr(1)
+ V_vap = rr(3)
+ if (V_liq < 0) V_liq = V_vap
+ case(1)
+ V_liq = rr(1)
+ V_vap = rr(1)
+ end select
+
+ select case(root_type)
+ case("liquid")
+ V = V_liq
+ case("vapor")
+ V = V_vap
+ case("stable")
+ ! AT is something close to Gr(P,T)
+ call eos%residual_helmholtz(z, V_liq, T, Ar=Ar)
+ AT_Liq = (Ar + V_liq*P)/(T*R) - sum(z)*log(V_liq)
+
+ call eos%residual_helmholtz(z, V_vap, T, Ar=Ar)
+ AT_Vap = (Ar + V_vap*P)/(T*R) - sum(z)*log(V_vap)
+
+ if (AT_liq <= AT_vap) then
+ V = V_liq
+ else
+ V = V_vap
+ end if
+ end select
+
+ V = totn * V
+ end subroutine
end module
diff --git a/src/models/residual_helmholtz/cubic/mixing_rules/base.f90 b/src/models/residual_helmholtz/cubic/mixing_rules/base.f90
index 64b238953..bdae22d57 100644
--- a/src/models/residual_helmholtz/cubic/mixing_rules/base.f90
+++ b/src/models/residual_helmholtz/cubic/mixing_rules/base.f90
@@ -22,7 +22,7 @@ module yaeos__models_ar_cubic_mixing_base
implicit none
contains
- subroutine bmix_linear(n, bi, b, dbi, dbij)
+ pure subroutine bmix_linear(n, bi, b, dbi, dbij)
real(pr), intent(in) :: n(:)
real(pr), intent(in) :: bi(:)
real(pr), intent(out) :: b, dbi(:), dbij(:, :)
@@ -32,7 +32,7 @@ subroutine bmix_linear(n, bi, b, dbi, dbij)
dbij = 0
end subroutine
- subroutine bmix_qmr(n, bi, lij, b, dbi, dbij)
+ pure subroutine bmix_qmr(n, bi, lij, b, dbi, dbij)
real(pr), intent(in) :: n(:)
real(pr), intent(in) :: bi(:)
real(pr), intent(in) :: lij(:, :)
@@ -70,7 +70,7 @@ subroutine bmix_qmr(n, bi, lij, b, dbi, dbij)
end do
end subroutine
- subroutine d1mix_rkpr(n, d1i, d1, dd1i, dd1ij)
+ pure subroutine d1mix_rkpr(n, d1i, d1, dd1i, dd1ij)
!! RKPR \(\delta_1\) parameter mixing rule.
!!
!! The RKPR EoS doesn't have a constant \(\delta_1\) value for each
diff --git a/src/models/solvers/volume.f90 b/src/models/solvers/volume.f90
new file mode 100644
index 000000000..a3bfac8a8
--- /dev/null
+++ b/src/models/solvers/volume.f90
@@ -0,0 +1,142 @@
+module yaeos__models_solvers
+ !! # `models solvers`
+ !! Set of different specialized solvers for different models
+ !!
+ !! # Description
+ !! This module holds specialized solvers for different kind of applications
+ !! and models.
+ !!
+ !! ## Volume solving
+ !! This module holds the routine `volume_michelsen` which is a solver for
+ !! volume that takes advantage over a simple newton on the function of
+ !! pressure by solving the function of pressure over the covolume instead,
+ !! which solution is limited in the range [0, 1]. This solver requires that
+ !! the EoS uses the method `get_v0` to return the covolume.
+ !!
+ !! # Examples
+ !!
+ !! ```fortran
+ !! A basic code example
+ !! ```
+ !!
+ !! # References
+ !!
+ use yaeos__constants, only: pr, R
+ use yaeos__models_ar, only: ArModel
+ implicit none
+
+contains
+
+ subroutine volume_michelsen(eos, n, P, T, V, root_type, max_iters)
+ !! Volume solver at a given pressure.
+ !!
+ !! Obtain the volume using the method described by Michelsen and Møllerup.
+ !! While \(P(V, T)\) can be obtained with a simple Newton method, a better
+ !! approach is solving \(P(B/V, T)\) where \(B\) is the EoS covolume.
+ !! This method is easier to solve because:
+ !! \[
+ !! V(P, T) \in [0, \infty)
+ !! \]
+ !! and
+ !! \[
+ !! \frac{B}{V}(P, T) \in [0, 1]
+ !! \]
+ !!
+ !! At chapter 3 page 94 of Michelsen and Møllerup's book a more complete
+ !! explanation can be seen
+ use iso_fortran_env, only: error_unit
+ use stdlib_optval, only: optval
+ class(ArModel), intent(in) :: eos
+ real(pr), intent(in) :: n(:) !! Mixture moles
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(out) :: V !! Volume [L]
+ character(len=*), optional, intent(in) :: root_type !! Type of root ["vapor" | "liquid" | "stable"]
+ integer, optional, intent(in) :: max_iters !! Maxiumum number of iterations, defaults to 100
+
+ character(len=10) :: root
+
+ real(pr) :: Ar, ArV, ArV2
+
+ real(pr) :: totn
+ real(pr) :: B !! Covolume
+ real(pr) :: ZETMIN, ZETA, ZETMAX
+ real(pr) :: pcalc, AT, AVAP, VVAP
+
+ integer :: iter, maximum_iterations
+
+ maximum_iterations = optval(max_iters, 100)
+ root = optval(root_type, "stable")
+
+ TOTN = sum(n)
+ B = eos%get_v0(n, p, t)
+ ITER = 0
+
+ ! Limits
+ ZETMIN = 0._pr
+ ZETMAX = 1._pr
+
+ select case(root_type)
+ case("liquid")
+ ZETA = 0.5_pr
+ call solve_point(P, V, Pcalc, AT, iter)
+ case("vapor","stable")
+ ZETA = min(0.5_pr, B*P/(TOTN*R*T))
+ call solve_point(P, V, Pcalc, AT, iter)
+
+ if (root_type == "stable") then
+ ! Run first for vapor and then for liquid
+ VVAP = V
+ AVAP = AT
+ ZETA = 0.5_pr
+ ZETMAX = 1._pr
+ call solve_point(P, V, Pcalc, AT, iter)
+ if (AT .gt. AVAP) V = VVAP
+ end if
+ case default
+ write(error_unit, *) "ERROR [VCALC]: Wrong specification"
+ error stop 1
+ end select
+ contains
+ subroutine solve_point(P, V, Pcalc, AT, iter)
+ real(pr), intent(in) :: P !! Objective pressure [bar]
+ real(pr), intent(out) :: V !! Obtained volume [L]
+ real(pr), intent(out) :: Pcalc !! Calculated pressure at V [bar]
+ real(pr), intent(out) :: AT !!
+ integer, intent(out) :: iter
+
+ real(pr) :: del, der
+
+ iter = 0
+ DEL = 1
+ pcalc = 2*p
+ do while(abs(DEL) > 1.e-10_pr .and. iter < maximum_iterations)
+ V = B/ZETA
+ iter = iter + 1
+ call eos%residual_helmholtz(n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2)
+
+ Pcalc = TOTN*R*T/V - ArV
+
+ if (Pcalc .gt. P) then
+ ZETMAX = ZETA
+ else
+ ZETMIN = ZETA
+ end if
+
+ ! AT is something close to Gr(P,T)
+ AT = (Ar + V*P)/(T*R) - TOTN*log(V)
+
+ DER = (ArV2*V**2 + TOTN*R*T)/B ! this is dPdrho/B
+ DEL = -(Pcalc - P)/DER
+ ZETA = ZETA + max(min(DEL, 0.1_pr), -.1_pr)
+
+ if (ZETA .gt. ZETMAX .or. ZETA .lt. ZETMIN) then
+ ZETA = 0.5_pr*(ZETMAX + ZETMIN)
+ end if
+ end do
+
+ if (iter >= maximum_iterations) write(error_unit, *) &
+ "WARN: Volume solver exceeded maximum number of iterations"
+ end subroutine solve_point
+ end subroutine volume_michelsen
+end module
\ No newline at end of file
diff --git a/src/phase_equilibria/boundaries/phase_envelopes_pt.f90 b/src/phase_equilibria/boundaries/phase_envelopes_pt.f90
index 498baf623..c31423a02 100644
--- a/src/phase_equilibria/boundaries/phase_envelopes_pt.f90
+++ b/src/phase_equilibria/boundaries/phase_envelopes_pt.f90
@@ -3,7 +3,6 @@ module yaeos__phase_equilibria_boundaries_phase_envelopes_pt
use yaeos__constants, only: pr
use yaeos__models, only: ArModel
use yaeos__equilibria_equilibria_state, only: EquilibriaState
- use yaeos__thermoprops, only: fugacity_tp
use yaeos__math_continuation, only: &
continuation, continuation_solver, continuation_stopper
implicit none
@@ -70,7 +69,7 @@ function pt_envelope_2ph(&
real(pr) :: S0 !! Initial specification value
integer :: max_points !! Maximum number of points
- integer :: max_iterations
+ integer :: max_iterations !! Maximum number of iterations
real(pr) :: X(size(z) + 2)
real(pr), allocatable :: XS(:, :)
@@ -107,10 +106,12 @@ function pt_envelope_2ph(&
XS = continuation(&
foo, X, ns0=ns, S0=S0, &
dS0=dS0, max_points=max_points, solver_tol=1.e-9_pr, &
- update_specification=update_specification, &
+ update_specification=update_spec, &
solver=solver, stop=stop_conditions &
)
+
contains
+
subroutine foo(X, ns, S, F, dF, dFdS)
!! Function that needs to be solved at each envelope point
real(pr), intent(in) :: X(:)
@@ -124,7 +125,7 @@ subroutine foo(X, ns, S, F, dF, dFdS)
character(len=14) :: kind_z, kind_y
real(pr) :: y(nc)
- real(pr) :: Vz, Vy, lnphip_z(nc), lnphip_y(nc)
+ real(pr) :: Vz, Vy, lnPhi_z(nc), lnPhi_y(nc)
real(pr) :: dlnphi_dt_z(nc), dlnphi_dt_y(nc)
real(pr) :: dlnphi_dp_z(nc), dlnphi_dp_y(nc)
real(pr) :: dlnphi_dn_z(nc, nc), dlnphi_dn_y(nc, nc)
@@ -143,29 +144,29 @@ subroutine foo(X, ns, S, F, dF, dFdS)
y = K*z
select case(kind)
- case ("bubble")
+ case ("bubble")
kind_z = "liquid"
kind_y = "vapor"
- case ("dew")
+ case ("dew")
kind_z = "vapor"
kind_y = "liquid"
- case default
+ case default
kind_z = "stable"
kind_y = "stable"
end select
-
- call fugacity_tp(&
- model, z, T, P, V=Vz, root_type=kind_z, &
- lnphip=lnphip_z, dlnPhidt=dlnphi_dt_z, &
+
+ call model%lnphi_pt(&
+ z, P, T, V=Vz, root_type=kind_z, &
+ lnPhi=lnphi_z, dlnPhidt=dlnphi_dt_z, &
dlnPhidp=dlnphi_dp_z, dlnphidn=dlnphi_dn_z &
)
- call fugacity_tp(&
- model, y, T, P, V=Vy, root_type=kind_y, &
- lnphip=lnphip_y, dlnPhidt=dlnphi_dt_y, &
+ call model%lnphi_pt(&
+ y, P, T, V=Vy, root_type=kind_y, &
+ lnPhi=lnphi_y, dlnPhidt=dlnphi_dt_y, &
dlnPhidp=dlnphi_dp_y, dlnphidn=dlnphi_dn_y &
)
- F(:nc) = X(:nc) + lnphip_y - lnphip_z
+ F(:nc) = X(:nc) + lnPhi_y - lnPhi_z
F(nc + 1) = sum(y - z)
F(nc + 2) = X(ns) - S
@@ -187,7 +188,7 @@ subroutine foo(X, ns, S, F, dF, dFdS)
dFdS(nc+2) = -1
end subroutine foo
- subroutine update_specification(X, ns, S, dS, dXdS, iterations)
+ subroutine update_spec(X, ns, S, dS, dXdS, step_iters)
!! Update the specification during continuation.
real(pr), intent(in out) :: X(:)
!! Vector of variables \([lnK_i \dots , lnT, lnP]\)
@@ -199,20 +200,17 @@ subroutine update_specification(X, ns, S, dS, dXdS, iterations)
!! Step in specification
real(pr), intent(in out) :: dXdS(:)
!! Variation of variables with respect to specification
- integer, intent(in) :: iterations
+ integer, intent(in) :: step_iters
!! Iterations used in the solver
- real(pr) :: Xnew(nc+2), Xold(nc+2), maxdS
-
- Xold = X
+ real(pr) :: maxdS
- ! ==============================================================
+ ! =====================================================================
! Update specification
- ! - Dont select T or P near critical poitns
+ ! - Dont select T or P near critical points
! - Update dS wrt specification units
! - Set step
- ! --------------------------------------------------------------
-
+ ! ---------------------------------------------------------------------
if (maxval(abs(X(:nc))) < 0.1_pr) then
ns = maxloc(abs(dXdS(:nc)), dim=1)
maxdS=0.01_pr
@@ -226,64 +224,97 @@ subroutine update_specification(X, ns, S, dS, dXdS, iterations)
dS = sign(1.0_pr, dS) * minval([ &
max(sqrt(abs(X(ns))/10._pr), 0.1_pr), &
- abs(dS)*3/iterations &
+ abs(dS)*3/step_iters &
] &
)
dS = sign(1.0_pr, dS) * maxval([abs(dS), maxdS])
- ! ==============================================================
- ! Save the point
- ! --------------------------------------------------------------
- envelopes%points = [&
- envelopes%points, &
- EquilibriaState(&
- kind=kind, &
- x=z, Vx=0._pr, y=exp(X(:nc))*z, Vy=0, &
- T=exp(X(nc+1)), P=exp(X(nc+2)), beta=0._pr, iters=iterations) &
- ]
-
-
- ! ==============================================================
- ! Handle critical point
- ! --------------------------------------------------------------
- cp: block
- !! Critical point detection
- !! If the values of lnK (X[:nc]) change sign then a critical point
- !! Has passed
- real(pr) :: Xc(nc+2) !! Value at (near) critical point
- real(pr) :: a !! Parameter for interpolation
-
- do while (maxval(abs(X(:nc))) < 0.1)
- ! If near a critical point, jump over it
- S = S + dS
- X = X + dXdS*dS
- end do
-
- Xnew = X + dXdS*dS
-
- if (all(Xold(:nc) * (Xnew(:nc)) < 0)) then
- select case(kind)
- case("dew")
- kind = "bubble"
- case("bubble")
- kind = "dew"
- case default
- kind = "liquid-liquid"
- end select
-
- ! 0 = a*X(ns) + (1-a)*Xnew(ns) < Interpolation equation to get X(ns) = 0
- a = -Xnew(ns)/(X(ns) - Xnew(ns))
- Xc = a * X + (1-a)*Xnew
- envelopes%cps = [&
- envelopes%cps, CriticalPoint(T=exp(Xc(nc+1)), P=exp(X(nc+2))) &
- ]
- ! X = Xc + dXdS*dS
- end if
-
- end block cp
-
- end subroutine update_specification
+ call save_point(X, step_iters)
+ call detect_critical(X, dXdS, ns, S, dS)
+ end subroutine update_spec
+
+ subroutine save_point(X, iters)
+ !! Save the converged point
+ real(pr), intent(in) :: X(:)
+ integer, intent(in) :: iters
+ type(EquilibriaState) :: point
+
+ real(pr) :: y(nc), T, P
+
+ T = exp(X(nc+1))
+ P = exp(X(nc+2))
+ y = exp(X(:nc))*z
+ point = EquilibriaState(&
+ kind=kind, x=z, Vx=0._pr, y=y, Vy=0._pr, &
+ T=T, P=P, beta=0._pr, iters=iters &
+ )
+
+ envelopes%points = [envelopes%points, point]
+ end subroutine save_point
+
+ subroutine detect_critical(X, dXdS, ns, S, dS)
+ !! # `detect_critical`
+ !! Critical point detection
+ !!
+ !! # Description
+ !! If the values of lnK (X[:nc]) change sign then a critical point
+ !! Has passed, since for this to happen all variables should pass
+ !! through zero. Near critical points (lnK < 0.05) points are harder
+ !! to converge, so more steps in the extrapolation vector are made to
+ !! jump over the critical point.
+ !! If the critical point is detected then the kind of the point is
+ !! changed and the point is saved using an interpolation knowing that
+ !!
+ !! \[
+ !! X_c = a * X + (1-a)*X_{new}
+ !! \]
+ !!
+ !! With \(X_c\) is the variables at the critical point, \(X_{new}\)
+ !! is the new initialization point of the method and \(a\) is the
+ !! parameter to interpolate the values. This subroutine finds the
+ !! value of \(a\) to obtain \(X_c\).
+ real(pr), intent(in out) :: X(:) !! Vector of variables
+ real(pr), intent(in out) :: dXdS(:) !! Variation of variables wrt S
+ integer, intent(in out) :: ns !! Number of specified variable
+ real(pr), intent(in out) :: S !! Specification value
+ real(pr), intent(in out) :: dS !! Step in specification
+ real(pr) :: Xc(nc+2) !! Value at (near) critical point
+ real(pr) :: a !! Parameter for interpolation
+
+ real(pr) :: Xold(size(X)) !! Old value of X
+ real(pr) :: Xnew(size(X)) !! Value of the next initialization
+
+ Xold = X
+
+ do while (maxval(abs(X(:nc))) < 0.05)
+ ! If near a critical point, jump over it
+ S = S + dS
+ X = X + dXdS*dS
+ end do
+
+ Xnew = X + dXdS*dS
+
+ if (all(Xold(:nc) * (Xnew(:nc)) < 0)) then
+ select case(kind)
+ case("dew")
+ kind = "bubble"
+ case("bubble")
+ kind = "dew"
+ case default
+ kind = "liquid-liquid"
+ end select
+
+ ! 0 = a*X(ns) + (1-a)*Xnew(ns) < Interpolation equation to get X(ns) = 0
+ a = -Xnew(ns)/(X(ns) - Xnew(ns))
+ Xc = a * X + (1-a)*Xnew
+
+ envelopes%cps = [&
+ envelopes%cps, CriticalPoint(T=exp(Xc(nc+1)), P=exp(Xc(nc+2))) &
+ ]
+ X = Xc + dXdS*dS
+ end if
+ end subroutine detect_critical
end function pt_envelope_2ph
subroutine write_PTEnvel2(pt2, unit, iotype, v_list, iostat, iomsg)
@@ -299,6 +330,7 @@ subroutine write_PTEnvel2(pt2, unit, iotype, v_list, iostat, iomsg)
integer :: i, nc
+ if (size(pt2%points) == 0) return
allocate(cps(0))
do i=1,size(pt2%cps)
cp = minloc(&
@@ -308,7 +340,7 @@ subroutine write_PTEnvel2(pt2, unit, iotype, v_list, iostat, iomsg)
cps = [cps, cp]
end do
- write(unit, "(A, /, /)") "#PTEnvel2"
+ write(unit, "(A, /, /)", iostat=iostat) "#PTEnvel2"
write(unit, "(A, /)") "#" // pt2%points(1)%kind
diff --git a/src/phase_equilibria/equilibria_state.f90 b/src/phase_equilibria/equilibria_state.f90
index 9903b673a..c4e2f8aa1 100644
--- a/src/phase_equilibria/equilibria_state.f90
+++ b/src/phase_equilibria/equilibria_state.f90
@@ -43,7 +43,7 @@ subroutine write_EquilibriaState(eq, unit, iotype, v_list, iostat, iomsg)
character(*), parameter :: nl = new_line("G")
- write(unit, *) eq%kind, eq%T, eq%P, eq%x, eq%y
+ write(unit, *) eq%kind, eq%T, eq%P, eq%beta, eq%x, eq%y
end subroutine write_EquilibriaState
end module yaeos__equilibria_equilibria_state
diff --git a/src/phase_equilibria/flash.f90 b/src/phase_equilibria/flash.f90
index 3de9618b3..b658181b4 100644
--- a/src/phase_equilibria/flash.f90
+++ b/src/phase_equilibria/flash.f90
@@ -2,7 +2,6 @@ module yaeos__equilibria_flash
use yaeos__constants, only: pr
use yaeos__models, only: ArModel
use yaeos__equilibria_equilibria_state, only: EquilibriaState
- use yaeos__thermoprops, only: fugacity_vt, fugacity_tp, pressure
use yaeos__phase_equilibria_rachford_rice, only: betato01, betalimits, rachford_rice, solve_rr
use yaeos__phase_equilibria_auxiliar, only: k_wilson
implicit none
@@ -72,7 +71,7 @@ type(EquilibriaState) function flash(model, z, t, v_spec, p_spec, k0, iters)
Vx = 0.0
if (.not. present(k0)) then
! the EoS one-phase pressure will be used to estimate Wilson K factors
- call pressure(model, z, v_spec, t, p=p)
+ call model%pressure(z, v_spec, t, p=p)
if (P < 0) P = 1.0
end if
end if
@@ -110,11 +109,11 @@ type(EquilibriaState) function flash(model, z, t, v_spec, p_spec, k0, iters)
case("TV")
! find Vy,Vx (vV and vL) from V balance and P equality equations
call tv_loop_solve_pressures(model, T, V, beta, x, y, Vx, Vy, P)
- call fugacity_tp(model, y, T, P, V=Vy, root_type="stable", lnphip=lnfug_y)
- call fugacity_tp(model, x, T, P, V=Vx, root_type="liquid", lnphip=lnfug_x)
+ call model%lnphi_pt(y, P, T, V=Vy, root_type="stable", lnPhi=lnfug_y)
+ call model%lnphi_pt(x, P, T, V=Vx, root_type="liquid", lnPhi=lnfug_x)
case("TP")
- call fugacity_tp(model, y, T, P, V=Vy, root_type="stable", lnphip=lnfug_y)
- call fugacity_tp(model, x, T, P, V=Vx, root_type="liquid", lnphip=lnfug_x)
+ call model%lnphi_pt(y, P, T, V=Vy, root_type="stable", lnPhi=lnfug_y)
+ call model%lnphi_pt(x, P, T, V=Vx, root_type="liquid", lnPhi=lnfug_x)
end select
dKold = dK
@@ -161,6 +160,7 @@ type(EquilibriaState) function flash(model, z, t, v_spec, p_spec, k0, iters)
if (spec == 'TP') v = beta*Vy + (1 - beta)*Vx
if (maxval(K) < 1.001 .and. minval(K) > 0.999) then ! trivial solution
+ flash%kind = "failed"
P = -1.0
flash%x = x/x
flash%y = y/y
@@ -170,6 +170,7 @@ type(EquilibriaState) function flash(model, z, t, v_spec, p_spec, k0, iters)
return
end if
+ flash%kind = "split"
flash%iters = iters
flash%p = p
flash%t = t
@@ -184,7 +185,6 @@ end function flash
subroutine tv_loop_solve_pressures(model, T, V, beta, x, y, vx, vy, P)
!! Solve pressure equality between two phases at a given temperature,
!! total volume, vapor molar fractions and compositions.
- use yaeos__thermoprops, only: fugacity_vt, pressure
use iso_fortran_env, only: error_unit
class(ArModel), intent(in) :: model
@@ -216,11 +216,11 @@ subroutine tv_loop_solve_pressures(model, T, V, beta, x, y, vx, vy, P)
! First evaluation will be with Vx = 1.5*Bx
if (Vx < Bx) Vx = 1.625_pr*Bx
- call pressure(model, x, Vx, T, Px, dpdv=dPxdV)
+ call model%pressure(x, Vx, T, Px, dpdv=dPxdV)
do while (Px < 0 .or. dPxdV >= 0)
Vx = Vx - 0.2*(Vx - Bx)
- call pressure(model, x, Vx, T, Px, dpdv=dPxdV)
+ call model%pressure(x, Vx, T, Px, dpdv=dPxdV)
end do
Vy = (V - (1 - beta)*Vx)/beta
@@ -231,8 +231,8 @@ subroutine tv_loop_solve_pressures(model, T, V, beta, x, y, vx, vy, P)
! Newton for solving P equality, with Vx as independent variable
its = its + 1
- call pressure(model, x, Vx, T, Px, dpdv=dPxdV)
- call pressure(model, y, Vy, T, Py, dpdv=dPydV)
+ call model%pressure(x, Vx, T, Px, dpdv=dPxdV)
+ call model%pressure(y, Vy, T, Py, dpdv=dPydV)
h = Py - Px
dh = -dPydV * dVydVx - dPxdV
@@ -256,8 +256,8 @@ subroutine tv_loop_solve_pressures(model, T, V, beta, x, y, vx, vy, P)
end if
end do
- call pressure(model, x, Vx, T, Px)
- call pressure(model, y, Vy, T, Py)
+ call model%pressure(x, Vx, T, Px)
+ call model%pressure(y, Vy, T, Py)
P = (Px + Py) * 0.5_pr
end subroutine tv_loop_solve_pressures
end module yaeos__equilibria_flash
diff --git a/src/phase_equilibria/saturations_points.f90 b/src/phase_equilibria/saturations_points.f90
index b30a12ddf..4dc1a8e22 100644
--- a/src/phase_equilibria/saturations_points.f90
+++ b/src/phase_equilibria/saturations_points.f90
@@ -1,7 +1,6 @@
module yaeos__equilibria_saturation_points
use yaeos__constants, only: pr
use yaeos__models, only: ArModel
- use yaeos__thermoprops, only: fugacity_vt, fugacity_tp
use yaeos__equilibria_equilibria_state, only: EquilibriaState
use yaeos__phase_equilibria_auxiliar, only: k_wilson
@@ -22,7 +21,6 @@ type(EquilibriaState) function saturation_pressure(model, n, t, kind, p0, y0, ma
!! - Dew point: `kind="dew"`
!! - Liquid-Liquid point: `kind="liquid-liquid"`
use stdlib_optval, only: optval
- use yaeos__thermoprops, only: pressure
class(ArModel), intent(in) :: model
real(pr), intent(in) :: n(:) !! Composition vector [moles / molar fraction]
real(pr), intent(in) :: t !! Temperature [K]
@@ -50,7 +48,7 @@ type(EquilibriaState) function saturation_pressure(model, n, t, kind, p0, y0, ma
if (present (p0)) then
p = p0
else
- call pressure(model, z, T, 10._pr, P=P)
+ call model%pressure(z, T, 10._pr, P=P)
end if
if (present(y0)) then
@@ -85,8 +83,8 @@ type(EquilibriaState) function saturation_pressure(model, n, t, kind, p0, y0, ma
! ------------------------------------------------------------------------
do its=1, iterations
y = k*z
- call fugacity_tp(model, y, T, P, vy, incipient, lnphip=lnfug_y, dlnphidp=dlnphi_dp_y)
- call fugacity_tp(model, z, T, P, vz, main, lnphip=lnfug_z, dlnphidp=dlnphi_dp_z)
+ call model%lnphi_pt(y, P, T, vy, incipient, lnPhi=lnfug_y, dlnphidp=dlnphi_dp_y)
+ call model%lnphi_pt(z, P, T, vz, main, lnPhi=lnfug_z, dlnphidp=dlnphi_dp_z)
k = exp(lnfug_z - lnfug_y)
@@ -132,7 +130,6 @@ type(EquilibriaState) function saturation_temperature(model, n, p, kind, t0, y0,
!! - Dew point: `kind="dew"`
!! - Liquid-Liquid point: `kind="liquid-liquid"`
use stdlib_optval, only: optval
- use yaeos__thermoprops, only: pressure
class(ArModel), intent(in) :: model
real(pr), intent(in) :: n(:) !! Composition vector [moles / molar fraction]
real(pr), intent(in) :: p !! Pressure [bar]
@@ -195,8 +192,8 @@ type(EquilibriaState) function saturation_temperature(model, n, p, kind, t0, y0,
! ------------------------------------------------------------------------
do its=1, iterations
y = k*z
- call fugacity_tp(model, y, T, P, vy, incipient, lnphip=lnfug_y, dlnphidt=dlnphi_dt_y)
- call fugacity_tp(model, z, T, P, vz, main, lnphip=lnfug_z, dlnphidt=dlnphi_dt_z)
+ call model%lnphi_pt(y, P, T, vy, incipient, lnPhi=lnfug_y, dlnphidt=dlnphi_dt_y)
+ call model%lnphi_pt(z, P, T, vz, main, lnPhi=lnfug_z, dlnphidt=dlnphi_dt_z)
k = exp(lnfug_z - lnfug_y)
f = sum(z*k) - 1
diff --git a/src/phase_equilibria/stability.f90 b/src/phase_equilibria/stability.f90
new file mode 100644
index 000000000..c351cd906
--- /dev/null
+++ b/src/phase_equilibria/stability.f90
@@ -0,0 +1,177 @@
+module yaeos__phase_equilibria_stability
+ !! # Phase Stability module
+ !! Phase stability related calculations.
+ !!
+ !! # Description
+ !! Contains the basics rotuines to make phase stability analysis for
+ !! phase-equilibria detection.
+ !!
+ !! - `tpd(model, z, w, P, T)`: reduced Tangent-Plane-Distance
+ !! - `min_tpd(model, z, P, T, mintpd, w)`: Find minimal tpd for a multicomponent mixture
+ !!
+ !! # Examples
+ !!
+ !! ```fortran
+ !! ! Obtain the minimal tpd for a binary mixture at \(z_1 = 0.13\)
+ !! model = PengRobinson76(tc, pc, ac, kij, lij)
+ !!
+ !! z = [0.13, 1-0.13]
+ !! w = [0.1, 0.9]
+ !!
+ !! P = 45.6_pr
+ !! T = 190._pr
+ !!
+ !! z = z/sum(z)
+ !! -----------------------------------------------
+ !! ```
+ !!
+ !! # References
+ !! 1. Thermodynamic Models: Fundamental and Computational Aspects, Michael L.
+ !! Michelsen, Jørgen M. Mollerup. Tie-Line Publications, Denmark (2004)
+ !! [doi](http://dx.doi.org/10.1016/j.fluid.2005.11.032)
+ use yaeos__constants, only: pr, r
+ use yaeos__models_ar, only: ArModel
+ implicit none
+
+contains
+
+ real(pr) function tm(model, z, w, P, T, d, dtpd)
+ !! # Alternative formulation of tangent-plane-distance
+ !! Michelsen's modified \(tpd\) function, \(tm\).
+ !!
+ !! # Description
+ !! Alternative formulation of the reduced tangent plane \(tpd\) function,
+ !! where the test phase is defined in moles, which enables for unconstrained
+ !! minimization.
+ !! \[
+ !! tm(W) = 1 + \sum_i W_i (\ln W_i + \ln \phi_i(W) - d_i - 1)
+ !! \]
+ !!
+ !! # Examples
+ !!
+ !! ## Calculation of `tm`
+ !! ```fortran
+ !! tm = tpd(model, z, w, P, T)
+ !! ---------------------------
+ !! ```
+ !!
+ !! ## Using precalculated trial-phase data
+ !! It is possible to calculate externaly the `d_i` vector and use it for
+ !! later calculations.
+ !! ```fortran
+ !! call fugacity_tp(&
+ !! model, z, T=T, P=P, V=Vz, root_type="stable", lnphip=lnphi_z&
+ !! )
+ !! lnphi_z = lnphi_z - log(P)
+ !! di = log(z) + lnphi_z
+ !! tm = tpd(model, z, w, P, T, d=di)
+ !! ---------------------------
+ !! ```
+ !!
+ !! # References
+ !! 1. Thermodynamic Models: Fundamental and Computational Aspects, Michael L.
+ !! Michelsen, Jørgen M. Mollerup. Tie-Line Publications, Denmark (2004)
+ !! [doi](http://dx.doi.org/10.1016/j.fluid.2005.11.032)
+ class(ArModel), intent(in) :: model !! Thermodynamic model
+ real(pr), intent(in) :: z(:) !! Feed composition
+ real(pr), intent(in) :: w(:) !! Test-phase mole numbers vector
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), optional, intent(in) :: d(:) !! \(d_i\) vector
+ real(pr), optional, intent(out) :: dtpd(:)
+
+ real(pr) :: di(size(z)), vz, vw
+ real(pr) :: lnphi_z(size(z)), lnphi_w(size(z))
+
+ call model%lnphi_pt(&
+ w, T=T, P=P, V=Vw, root_type="stable", lnPhi=lnPhi_w &
+ )
+
+ if (.not. present(d)) then
+ call model%lnphi_pt(&
+ z, T=T, P=P, V=Vz, root_type="stable", lnPhi=lnPhi_z&
+ )
+ di = log(z) + lnphi_z
+ else
+ di = d
+ end if
+
+
+ ! tpd = sum(w * (log(w) + lnphi_w - di))
+ tm = 1 + sum(w * (log(w) + lnPhi_w - di - 1))
+
+ if (present(dtpd)) then
+ dtpd = log(w) + lnPhi_w - di
+ end if
+ end function tm
+
+ subroutine min_tpd(model, z, P, T, mintpd, w, all_minima)
+ use nlopt_wrap, only: create, destroy, nlopt_opt, nlopt_algorithm_enum
+ use nlopt_callback, only: nlopt_func, create_nlopt_func
+ class(ArModel) :: model
+ real(pr), intent(in) :: z(:) !! Feed composition
+ real(pr), intent(in) :: P !! Pressure [bar]
+ real(pr), intent(in) :: T !! Temperature [K]
+ real(pr), intent(out) :: w(:) !! Trial composition
+ real(pr), intent(out) :: mintpd !! Minimal value of \(tm\)
+ real(pr), optional, intent(out) :: all_minima(:, :)
+ !! All the found minima
+
+ real(pr) :: dx(size(w))
+ real(pr) :: lnphi_z(size(z)), di(size(z))
+
+ real(pr) :: mins(size(w)), ws(size(w), size(w)), V
+ integer :: i
+
+ type(nlopt_opt) :: opt !! Optimizer
+ type(nlopt_func) :: f !! Function to optimize
+
+ integer :: stat
+
+ f = create_nlopt_func(foo)
+ dx = 0.001_pr
+
+ ! Calculate feed di
+ call model%lnphi_pt(z, T=T, P=P, V=V, root_type="stable", lnPhi=lnPhi_z)
+ di = log(z) + lnphi_z
+
+
+ ! ==============================================================
+ ! Setup optimizer
+ ! --------------------------------------------------------------
+ opt = nlopt_opt(nlopt_algorithm_enum%LN_NELDERMEAD, size(w))
+ call opt%set_ftol_rel(0.001_pr)
+ call opt%set_ftol_abs(0.00001_pr)
+ call opt%set_min_objective(f)
+ call opt%set_initial_step(dx)
+
+ ! ==============================================================
+ ! Minimize for each component using each quasi-pure component
+ ! as initialization.
+ ! --------------------------------------------------------------
+ !$OMP PARALLEL DO PRIVATE(i, w, mintpd, stat) SHARED(opt, ws, mins)
+ do i=1,size(w)
+ w = 0.001_pr
+ w(i) = 0.999_pr
+ call opt%optimize(w, mintpd, stat)
+ mins(i) = mintpd
+ ws(i, :) = w
+ end do
+ !$OMP END PARALLEL DO
+
+ i = minloc(mins, dim=1)
+ mintpd = mins(i)
+ w = ws(i, :)
+
+ if(present(all_minima)) all_minima = ws
+
+ call destroy(opt)
+ contains
+ real(pr) function foo(x, gradient, func_data)
+ real(pr), intent(in) :: x(:)
+ real(pr), optional, intent(in out) :: gradient(:)
+ class(*), optional, intent(in) :: func_data
+ foo = tm(model, z, x, P, T, d=di)
+ end function foo
+ end subroutine min_tpd
+end module yaeos__phase_equilibria_stability
diff --git a/src/thermoprops.f90 b/src/thermoprops.f90
deleted file mode 100644
index 86dbe7115..000000000
--- a/src/thermoprops.f90
+++ /dev/null
@@ -1,425 +0,0 @@
-module yaeos__thermoprops
- !! Residual thermodyamic properties using residual Helmholtz model.
- !!
- !! Available properties:
- !!
- !! - pressure(n, V, T)
- !! - fugacity(n, V, T)
- !! - fugacity(n, P, T, root=[vapor, liquid, stable])
- !! - volume
- !!
- !! Calculate thermodynamic properties using Helmholtz energy as a basis.
- !! All the routines in this module work with the logic:
- !!
- !! ```fortran
- !! call foo(x, V, T, [dfoodv, dfoodt, ...])
- !! ```
- !! Where the user can call the routine of the desired property. And include
- !! as optional values the desired derivatives of said properties.
- use yaeos__constants, only: R, pr
- use yaeos__models_ar, only: ArModel
- implicit none
-contains
- subroutine pressure(eos, n, v, t, p, dpdv, dpdt, dpdn)
- !! Pressure calculation.
- !!
- !! Calculate pressure using residual helmholtz models.
- !!
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: p !! Pressure [bar]
- real(pr), optional, intent(out) :: dpdv !! \(\frac{dP}}{dV}\)
- real(pr), optional, intent(out) :: dpdt !! \(\frac{dP}}{dT}\)
- real(pr), optional, intent(out) :: dpdn(:) !! \(\frac{dP}}{dn_i}\)
-
- real(pr) :: totn
-
- real(pr) :: Ar, ArV, ArV2, ArTV, ArVn(size(n))
- integer :: nc
-
- TOTN = sum(n)
- nc = size(n)
-
- call eos%residual_helmholtz(&
- n, v, t, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, ArVn=ArVn &
- )
- P = TOTN*R*T/V - ArV
- if (present(dPdV)) dPdV = -ArV2 - R*t*TOTN/V**2
- if (present(dPdT)) dPdT = -ArTV + TOTN*R/V
- if (present(dPdN)) dPdN(:) = R*T/V - ArVn(:)
- end subroutine pressure
-
- subroutine fugacity_tp(eos, &
- n, T, P, V, root_type, lnphip, dlnPhidP, dlnphidT, dlnPhidn &
- )
- !! Calculate logarithm of fugacity, given pressure and temperature.
- !!
- !! This routine will obtain the desired volume root at the specified
- !! pressure and calculate fugacity at that point.
- !!
- !! @note
- !! While the natural output variable is \(ln f_i\). The calculated
- !! derivatives will be the derivatives of the fugacity coefficient
- !! \(ln \phi_i\)
- !! @endnote
- !!
- use iso_fortran_env, only: error_unit
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Mixture mole numbers
- character(len=*), intent(in) :: root_type !! Type of root desired ["liquid", "vapor", "stable"]
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: p !! Pressure [bar]
-
- real(pr), optional, intent(out) :: lnphip(size(n)) !! \(\ln(f_i)\) vector
- real(pr), optional, intent(out) :: v !! Volume [L]
- real(pr), optional, intent(out) :: dlnphidt(size(n)) !! ln(phi) Temp derivative
- real(pr), optional, intent(out) :: dlnphidp(size(n)) !! ln(phi) Presssure derivative
- real(pr), optional, intent(out) :: dlnphidn(size(n), size(n)) !! ln(phi) compositional derivative
-
- real(pr) :: v_in, p_in
-
- call volume(eos, n, P, T, V_in, root_type)
- call fugacity_vt(eos, n, v_in, T, P_in, lnphip, dlnphidp, dlnphidt, dlnphidn)
- if(present(v)) v = v_in
- if(abs(P_in - p) > 1e-2) then
- write(error_unit, *) "WARN: possible bad root solving: ", p_in, p
- end if
- end subroutine fugacity_tp
-
- subroutine fugacity_vt(eos, &
- n, V, T, P, lnphip, dlnPhidP, dlnphidT, dlnPhidn, dPdV, dPdT, dPdN &
- )
- !! Calculate fugacity coefficent given volume and temperature.
- !!
- !!@note
- !!While the natural output variable is \(ln \phi_i P\). The calculated
- !!derivatives will be the derivatives of the fugacity coefficient
- !!\(ln \phi_i\)
- !!@endnote
- !!
- class(ArModel) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Mixture mole numbers
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(in) :: t !! Temperature [K]
-
- real(pr), optional, intent(out) :: p !! Pressure [bar]
- real(pr), optional, intent(out) :: lnphip(size(n)) !! \(\ln(\phi_i*P)\) vector
- real(pr), optional, intent(out) :: dlnphidt(size(n)) !! \(ln(phi_i)\) Temp derivative
- real(pr), optional, intent(out) :: dlnphidp(size(n)) !! \(ln(phi_i)\) Presssure derivative
- real(pr), optional, intent(out) :: dlnphidn(size(n), size(n)) !! \(ln(phi_i)\) compositional derivative
- real(pr), optional, intent(out) :: dPdV !! \(\frac{dP}{dV}\)
- real(pr), optional, intent(out) :: dPdT !! \(\frac{dP}{dT}\)
- real(pr), optional, intent(out) :: dPdN(:) !! \(\frac{dP}{dn_i}\)
-
- real(pr) :: Ar, ArTV, ArV, ArV2
- real(pr), dimension(size(n)) :: Arn, ArVn, ArTn
- real(pr) :: Arn2(size(n), size(n))
-
- real(pr) :: dPdV_in, dPdT_in, dPdN_in(size(n))
- real(pr) :: P_in
-
- real(pr) :: RT, Z
-
- real(pr) :: totn
- integer :: nc, i, j
-
-
- totn = sum(n)
- nc = size(n)
-
- RT = R*T
- Z = V/(TOTN*RT) ! this is Z/P
-
- if (present(lnphip) .and. .not. (&
- present(dlnphidn) &
- .or. present(dlnphidp) &
- .or. present(dlnphidt) &
- .or. present(p) &
- )) then
- call eos%residual_helmholtz(n, v, t, Arn=Arn)
- lnphip(:) = Arn(:)/RT - log(Z)
- return
- else if (present(dlnphidn)) then
- call eos%residual_helmholtz(&
- n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, &
- Arn=Arn, ArVn=ArVn, ArTn=ArTn, Arn2=Arn2 &
- )
- else
- call eos%residual_helmholtz(&
- n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2, ArTV=ArTV, &
- Arn=Arn, ArVn=ArVn, ArTn=ArTn &
- )
- end if
-
- lnphip(:) = Arn(:)/RT - log(Z)
-
- P_in = TOTN*RT/V - ArV
- if (present(P)) P = P_in
-
- dPdV_in = -ArV2 - RT*TOTN/V**2
- dPdT_in = -ArTV + TOTN*R/V
- dPdN_in = RT/V - ArVn
-
- if (present(dlnphidp)) then
- dlnphidp(:) = -dPdN_in(:)/dPdV_in/RT - 1._pr/P_in
- end if
- if (present(dlnphidt)) then
- dlnphidt(:) = (ArTn(:) - Arn(:)/T)/RT + dPdN_in(:)*dPdT_in/dPdV_in/RT + 1._pr/T
- end if
-
- if (present(dlnphidn)) then
- do i = 1, nc
- do j = i, nc
- dlnphidn(i, j) = 1._pr/TOTN + (Arn2(i, j) + dPdN_in(i)*dPdN_in(j)/dPdV_in)/RT
- dlnphidn(j, i) = dlnphidn(i, j)
- end do
- end do
- end if
-
- if (present(dPdV)) dPdV = dPdV_in
- if (present(dPdT)) dPdT = dPdT_in
- if (present(dPdN)) dPdN = dPdN_in
- end subroutine fugacity_vt
-
- subroutine volume(eos, n, P, T, V, root_type, max_iters)
- !! Volume solver at a given pressure.
- !!
- !! Obtain the volume using the method described by Michelsen and Møllerup.
- !! While \(P(V, T)\) can be obtained with a simple Newton method, a better
- !! approach is solving \(P(B/V, T)\) where \(B\) is the EoS covolume.
- !! This method is easier to solve because:
- !! \[
- !! V(P, T) \in [0, \infty)
- !! \]
- !! and
- !! \[
- !! \frac{B}{V}(P, T) \in [0, 1]
- !! \]
- !!
- !! At chapter 3 page 94 of Michelsen and Møllerup's book a more complete
- !! explanation can be seen
- use iso_fortran_env, only: error_unit
- use stdlib_optval, only: optval
- class(ArModel), intent(in) :: eos
- real(pr), intent(in) :: n(:) !! Mixture moles
- real(pr), intent(in) :: T !! Temperature [K]
- real(pr), intent(in) :: P !! Pressure [bar]
- real(pr), intent(out) :: V !! Volume [L]
- character(len=*), optional, intent(in) :: root_type !! Type of root ["vapor" | "liquid" | "stable"]
- integer, optional, intent(in) :: max_iters !! Maxiumum number of iterations, defaults to 100
-
- character(len=10) :: root
-
- real(pr) :: Ar, ArV, ArV2
-
- real(pr) :: totn
- real(pr) :: B !! Covolume
- real(pr) :: ZETMIN, ZETA, ZETMAX
- real(pr) :: pcalc, AT, AVAP, VVAP
-
- integer :: iter, maximum_iterations
-
- maximum_iterations = optval(max_iters, 100)
- root = optval(root_type, "stable")
-
- TOTN = sum(n)
- B = eos%get_v0(n, p, t)
- ITER = 0
-
- ! Limits
- ZETMIN = 0._pr
- ZETMAX = 1._pr
-
- select case(root_type)
- case("liquid")
- ZETA = 0.5_pr
- call solve_point(P, V, Pcalc, AT, iter)
- case("vapor","stable")
- ZETA = min(0.5_pr, B*P/(TOTN*R*T))
- call solve_point(P, V, Pcalc, AT, iter)
-
- if (root_type == "stable") then
- ! Run first for vapor and then for liquid
- VVAP = V
- AVAP = AT
- ZETA = 0.5_pr
- ZETMAX = 1._pr
- call solve_point(P, V, Pcalc, AT, iter)
- if (AT .gt. AVAP) V = VVAP
- end if
- case default
- write(error_unit, *) "ERROR [VCALC]: Wrong specification"
- error stop 1
- end select
- contains
- subroutine solve_point(P, V, Pcalc, AT, iter)
- real(pr), intent(in) :: P !! Objective pressure [bar]
- real(pr), intent(out) :: V !! Obtained volume [L]
- real(pr), intent(out) :: Pcalc !! Calculated pressure at V [bar]
- real(pr), intent(out) :: AT !!
- integer, intent(out) :: iter
-
- real(pr) :: del, der
-
- iter = 0
- DEL = 1
- pcalc = 2*p
- do while(abs(DEL) > 1.e-10_pr .and. iter < maximum_iterations)
- V = B/ZETA
- iter = iter + 1
- call eos%residual_helmholtz(n, V, T, Ar=Ar, ArV=ArV, ArV2=ArV2)
-
- Pcalc = TOTN*R*T/V - ArV
-
- if (Pcalc .gt. P) then
- ZETMAX = ZETA
- else
- ZETMIN = ZETA
- end if
-
- ! AT is something close to Gr(P,T)
- AT = (Ar + V*P)/(T*R) - TOTN*log(V)
-
- DER = (ArV2*V**2 + TOTN*R*T)/B ! this is dPdrho/B
- DEL = -(Pcalc - P)/DER
- ZETA = ZETA + max(min(DEL, 0.1_pr), -.1_pr)
-
- if (ZETA .gt. ZETMAX .or. ZETA .lt. ZETMIN) then
- ZETA = 0.5_pr*(ZETMAX + ZETMIN)
- end if
- end do
-
- if (iter >= maximum_iterations) write(error_unit, *) &
- "WARN: Volume solver exceeded maximum number of iterations"
- end subroutine solve_point
- end subroutine volume
-
- ! ==========================================================================
- ! Residual Enthalpy
- ! --------------------------------------------------------------------------
- subroutine enthalpy_residual_vt(eos, n, v, t, Hr, HrT, HrV, Hrn)
- !! Calculate residual enthalpy given volume and temperature.
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: Hr !! Residual enthalpy [bar L / mol]
- real(pr), optional, intent(out) :: HrT !! \(\frac{dH^r}}{dT}\)
- real(pr), optional, intent(out) :: HrV !! \(\frac{dH^r}}{dV}\)
- real(pr), optional, intent(out) :: Hrn(size(n)) !! \(\frac{dH^r}}{dn}\)
-
- real(pr) :: Ar, ArV, ArT, Arn(size(n))
- real(pr) :: ArV2, ArT2, ArTV, ArVn(size(n)), ArTn(size(n))
-
- call eos%residual_helmholtz(&
- n, v, t, Ar=Ar, ArV=ArV, ArT=ArT, ArTV=ArTV, ArV2=ArV2, ArT2=ArT2, Arn=Arn, ArVn=ArVn, ArTn=ArTn &
- )
-
- Hr = Ar - t*ArT - v*ArV
-
- if (present(HrT)) HrT = - t*ArT2 - v*ArTV
- if (present(HrV)) HrV = - t*ArTV - v*ArV2
- if (present(HrN)) HrN(:) = Arn(:) - t*ArTn(:) - v*ArVn(:)
- end subroutine enthalpy_residual_vt
-
- ! ==========================================================================
- ! Residual Gibbs energy
- ! --------------------------------------------------------------------------
- subroutine gibbs_residual_vt(eos, n, v, t, Gr, GrT, GrV, Grn)
- !! Calculate residual Gibbs energy given volume and temperature.
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: Gr !! Gibbs energy [bar L / mol]
- real(pr), optional, intent(out) :: GrT !! \(\frac{dG^r}}{dT}\)
- real(pr), optional, intent(out) :: GrV !! \(\frac{dG^r}}{dV}\)
- real(pr), optional, intent(out) :: Grn(size(n)) !! \(\frac{dG^r}}{dn}\)
-
- real(pr) :: Ar, ArV, ArT, Arn(size(n))
- real(pr) :: p, dpdv, dpdt, dpdn(size(n)), z, ntot
-
- ntot = sum(n)
- call pressure(eos, n, v, t, p, dpdv=dpdv, dpdt=dpdt, dpdn=dpdn)
- z = p*v/(ntot*R*t)
-
- call eos%residual_helmholtz(n, v, t, Ar=Ar, ArV=ArV, ArT=ArT, Arn=Arn)
-
- Gr = Ar + p*v - ntot*R*t
-
- if (present(GrT)) GrT = ArT + v*dpdt - ntot*R
- if (present(GrV)) GrV = ArV + v*dpdv + p
- if (present(GrN)) GrN(:) = Arn(:) + v*dpdn(:) - R*t
- end subroutine gibbs_residual_vt
-
- ! ==========================================================================
- ! Residual entropy
- ! --------------------------------------------------------------------------
- subroutine entropy_residual_vt(eos, n, v, t, Sr, SrT, SrV, Srn)
- !! Calculate residual entropy given volume and temperature.
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: Sr !! Entropy [bar L / K / mol]
- real(pr), optional, intent(out) :: SrT !! \(\frac{dS^r}}{dT}\)
- real(pr), optional, intent(out) :: SrV !! \(\frac{dS^r}}{dV}\)
- real(pr), optional, intent(out) :: Srn(size(n)) !! \(\frac{dS^r}}{dn}\)
-
- real(pr) :: Ar, ArT, ArT2, ArTV, ArTn(size(n))
-
- call eos%residual_helmholtz(&
- n, v, t, Ar=Ar, ArT=ArT, ArTV=ArTV, ArT2=ArT2, ArTn=ArTn &
- )
-
- Sr = - ArT
-
- if (present(SrT)) SrT = - ArT2
- if (present(SrV)) SrV = - ArTV
- if (present(SrN)) SrN = - ArTn
- end subroutine entropy_residual_vt
-
- ! ==========================================================================
- ! Residual Cv
- ! --------------------------------------------------------------------------
- subroutine Cv_residual_vt(eos, n, v, t, Cv)
- !! Calculate residual heat capacity volume constant given v and t.
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: Cv !! heat capacity v constant [bar L / K / mol]
-
- real(pr) :: Ar, ArT2
-
- call eos%residual_helmholtz(n, v, t, Ar=Ar, ArT2=ArT2)
-
- Cv = -t*ArT2
- end subroutine Cv_residual_vt
-
- ! ==========================================================================
- ! Residual Cp
- ! --------------------------------------------------------------------------
- subroutine Cp_residual_vt(eos, n, v, t, Cp)
- !! Calculate residual heat capacity pressure constant given v and t.
- class(ArModel), intent(in) :: eos !! Model
- real(pr), intent(in) :: n(:) !! Moles number vector
- real(pr), intent(in) :: t !! Temperature [K]
- real(pr), intent(in) :: v !! Volume [L]
- real(pr), intent(out) :: Cp !! heat capacity p constant [bar L / K / mol]
-
- real(pr) :: Ar, ArT2, Cv, p, dpdt, dpdv, ntot
-
- ntot = sum(n)
-
- call eos%residual_helmholtz(n, v, t, Ar=Ar, ArT2=ArT2)
-
- call Cv_residual_vt(eos, n, v, t, Cv)
-
- call pressure(eos, n, v, t, p, dpdv=dpdv, dpdt=dpdt)
-
- Cp = Cv - t*dpdt**2/dpdv - ntot*R
- end subroutine Cp_residual_vt
-end module yaeos__thermoprops
diff --git a/src/yaeos.f90 b/src/yaeos.f90
index 86bf7ffce..e2320667d 100644
--- a/src/yaeos.f90
+++ b/src/yaeos.f90
@@ -9,13 +9,11 @@ module yaeos
!! - [[yaeos__consistency(module)]]: Tools to evalaute the consistency of Ar and Ge models.
!! - [[yaeos__substance(module)]]: Derived type that holds the important data (for example, critical constants) from a mixture.
!! - [[yaeos__models(module)]]: All the implemented models, also their base types for making extensions.
- !! - [[yaeos__thermoprops(module)]]: Available thermodynamic properties to calculate.
!! - [[yaeos__equilibria(module)]]: Phase equilibria related procedures.
use yaeos__constants
use yaeos__consistency
use yaeos__substance
use yaeos__models
- use yaeos__thermoprops
use yaeos__equilibria
- character(len=*), parameter :: version="0.3.0" !! This version.
+ character(len=*), parameter :: version="1.0.0" !! This version.
end module
diff --git a/test/fixtures/taperobinson.f90 b/test/fixtures/taperobinson.f90
index b2e4b004f..936b3ec35 100644
--- a/test/fixtures/taperobinson.f90
+++ b/test/fixtures/taperobinson.f90
@@ -16,6 +16,7 @@
MODULE autodiff_tapenade_pr76
USE YAEOS__CONSTANTS, ONLY : pr, r
USE YAEOS__TAPENADE_AR_API, ONLY : armodeltapenade
+ use yaeos__tapenade_interfaces
IMPLICIT NONE
type, extends(ArModelTapenade) :: TPR76
REAL(pr), ALLOCATABLE :: kij(:, :), lij(:, :)
@@ -800,12 +801,6 @@ SUBROUTINE AR_D_B(model, n, nb, nd, ndb, v, vb, vd, vdb, t, tb, td, &
INTEGER :: ad_from
INTEGER :: ad_to
INTEGER :: ad_to0
- EXTERNAL PUSHREAL8ARRAY
- EXTERNAL PUSHINTEGER4
- EXTERNAL PUSHREAL8
- EXTERNAL POPREAL8
- EXTERNAL POPINTEGER4
- EXTERNAL POPREAL8ARRAY
INTEGER :: arg12
LOGICAL, DIMENSION(SIZE(n)) :: mask1
LOGICAL, DIMENSION(SIZE(n)) :: mask2
diff --git a/test/flash_tv.f90 b/test/flash_tv.f90
deleted file mode 100644
index 85e45d670..000000000
--- a/test/flash_tv.f90
+++ /dev/null
@@ -1,215 +0,0 @@
-program flash_tv
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp, pressure
- use yaeos__math_linalg, only: solve_system
- use fixtures_models, only: binary_PR76
-
- implicit none
-
- integer, parameter :: nc = 2
-
- real(pr) :: z(nc) = [0.4, 0.6]
- real(pr) :: x(nc) = [0.32424471950363210, 0.67575531029866709]
- real(pr) :: y(nc) = [0.91683466155334536, 8.3165368249135715E-002]
- real(pr) :: vx = 8.4918883298198036E-002
- real(pr) :: vy = 0.32922132295944545
-
- real(pr) :: F(nc+3), dF(nc+3, nc+3)
- real(pr) :: Fdx(nc+3),dFdx(nc+3, nc+3)
- real(pr) :: dxold(nc+3)
-
- real(pr) :: K(nc), T=200, V, P
- real(pr) :: beta=0.12
-
- real(pr) :: vars(nc+3), dx(nc+3)
-
- class(ArModel), allocatable :: model
- type(EquilibriaState) :: flash_result
-
- integer :: its
-
- model = binary_PR76()
-
- V = beta*vy + (1-beta) * vx
-
- K = y/x
- dfdX=0
- df = 0
-
- flash_result = flash(model, z, T, p_spec=5._pr, iters=its)
-
- x = flash_result%x
- y = flash_result%y
- y(1) = y(1) + 0.2
- y = y/sum(y)
- beta = flash_result%beta
- vx = flash_result%vx
- vy = flash_result%vy
-
- K = (model%components%Pc/5._pr) &
- * exp(5.373_pr*(1 + model%components%w)&
- * (1 - model%components%Tc/T))
-
- V = beta *vy + (1-beta)*vx
-
- print *, "true Results"
- print *, flash_result%vx, flash_result%vy, flash_result%beta, beta * vy + (1-beta)*vx
- print *, flash_result%x
- print *, flash_result%y
- print *, "------------"
-
- call flash_TV_DF(model, z, T, V, log(K), beta, vx, vy, F, dF)
- print *, "numdiff"
- do its = 1,nc+3
- print *, df(its, :)
- end do
-
- call flash_TV_F(model, z, T, V, log(K), beta, vx, vy, F, dF)
- print *, "anadiff"
- do its = 1,nc+3
- print *, df(its, :)
- end do
-
- stop
-
- print *, "solve?"
- do its=1,1000
- call flash_TV_DF(model, z, T, V, K, beta, vx, vy, F, dF)
-
- dxold = dx
- dx = solve_system(dF, -F)
-
- ! if (any(isnan(dx)) .or. any(isnan(F))) then
- ! K = K - dxold(:nc)
- ! beta = beta - dxold(nc+1)
- ! vx = vx - dxold(nc+2)
- ! vy = vy - dxold(nc+3)
-
- ! dx = dxold/2
- ! end if
-
- print *, its, F
-
- do while (beta + dx(nc+1) > 1 .or. beta + dx(nc+1) < 0)
- dx = dx/5
- end do
-
- K = K + dx(:nc)
- beta = beta + dx(nc+1)
- vx = vx + dx(nc+2)
- vy = vy + dx(nc+3)
-
- if (maxval(abs(F)) < 1e-3) then
- print *, "conv"
- exit
- end if
- end do
-
- x = z / (beta * (K - 1) + 1)
- y = K * x
- print *, vx, vy, beta, beta*vy + (1-beta)*vx
- print *, x
- print *, y
-
-contains
- subroutine flash_TV_F(model, z, T, V, lnK, beta, vx, vy, F, dF)
- use yaeos, only: fugacity_vt
- class(ArModel), intent(in) :: model
- real(pr), intent(in) :: z(:)
- real(pr), intent(in) :: T
- real(pr), intent(in) :: V
- real(pr), intent(in) :: lnK(:)
- real(pr), intent(in) :: beta
- real(pr), intent(in) :: vx
- real(pr), intent(in) :: vy
- real(pr), intent(out) :: F(:)
- real(pr), optional, intent(out) :: dF(:, :)
-
- real(pr) :: K(nc)
- real(pr) :: x(nc), Px, dPxdn(nc), lnphip_x(nc), dlnPhidx(nc, nc), dPxdV
- real(pr) :: y(nc), Py, dPydn(nc), lnphip_y(nc), dlnPhidy(nc, nc), dPydV
-
- real(pr) :: dxdK(nc), dydK(nc), dxdbeta(nc), dydbeta(nc)
- real(pr) :: dVxdbeta, dVydbeta
-
- integer :: i, j
-
- F = 0
- K = exp(lnK)
-
- x = z / (beta * (K - 1) + 1)
- y = K * x
-
- dxdbeta = z * (1-k)/ (beta*(K - 1) + 1)**2
- dydbeta = K * dxdbeta
-
- dxdK = - beta * z / (beta*(K - 1)+1)**2
- dydK = x + K * dxdK
-
- call fugacity_vt(model, x, vx, T, P=Px, dPdN=dPxdn, lnphip=lnphip_x, dlnphidn=dlnPhidx, dPdV=dPxdV)
- call fugacity_vt(model, y, vy, T, P=Py, dPdN=dPydn, lnphip=lnphip_y, dlnphidn=dlnPhidy, dPdV=dPydV)
-
- F(:nc) = lnK - lnphip_x + lnphip_y
- F(nc + 1) = Px !- Py
- F(nc + 2) = V - (beta*Vy + (1-beta)*Vx)
- F(nc + 3) = sum((z * (1 - K)) /(1 + beta*(K - 1)))
-
- if (present(df)) then
- df = 0
- do i=1,nc
- do j=1,nc
- end do
- end do
-
- df(nc+1, :nc) = K * (dPxdn * dxdK - dPydn * dydK)
-
- df(nc+2, :nc) = 0
- df(nc+2, nc+1) = Vx - Vy
-
- df(nc+3, :nc) = K*(beta * z * (K-1)/(beta*(K-1)+1)**2 - z/(beta*(K-1)+1))
- end if
- end subroutine flash_TV_F
-
- subroutine flash_TV_DF(model, z, T, V, lnK, beta, vx, vy, F, dF)
- class(ArModel), intent(in) :: model
- real(pr), intent(in) :: z(:)
- real(pr), intent(in) :: T
- real(pr), intent(in) :: V
- real(pr), intent(in) :: lnK(:)
- real(pr), intent(in) :: beta
- real(pr), intent(in) :: vx
- real(pr), intent(in) :: vy
- real(pr), intent(out) :: F(:)
- real(pr), intent(out) :: dF(:, :)
-
- real(pr) :: dx
- integer :: i, nc
- real(pr) :: lnKdx(size(z)), betadx, vxdx, vydx, Fdx(size(F))
-
- nc = size(z)
-
- dx = 1e-5
-
- f = 0
- df = 0
- call flash_TV_F(model, z, T, V, lnK, beta, vx, vy, F, dF)
-
- do i=1, nc
- lnKdx = lnK
- lnKdx(i) = lnK(i) + dx
- call flash_TV_F(model, z, T, V, lnKdx, beta, vx, vy, Fdx)
- df(:, i) = (Fdx - F)/dx
- end do
-
- betadx = beta + dx
- call flash_TV_F(model, z, T, V, lnK, betadx, vx, vy, Fdx)
- df(:, nc+1) = (Fdx - F)/dx
-
- vxdx = vx + dx
- call flash_TV_F(model, z, T, V, lnK, beta, vxdx, vy, Fdx)
- df(:, nc+2) = (Fdx - F)/dx
-
- vydx = vy + dx
- call flash_TV_F(model, z, T, V, lnK, beta, vydx, vy, Fdx)
- df(:, nc+3) = (Fdx - F)/dx
- end subroutine flash_TV_DF
-end program flash_tv
\ No newline at end of file
diff --git a/test/test_fitting/test_fitting.f90 b/test/test_fitting/test_fitting.f90
index 7eb9f4e93..8fa7dd6dc 100644
--- a/test/test_fitting/test_fitting.f90
+++ b/test/test_fitting/test_fitting.f90
@@ -9,7 +9,9 @@ subroutine collect_suite(testsuite)
!> Collection of tests
type(unittest_type), allocatable, intent(out) :: testsuite(:)
- testsuite = [new_unittest("FitKijLij", test_fit_kij_lij) &
+ testsuite = [&
+ new_unittest("FitKijLij", test_fit_kij_lij), &
+ new_unittest("FitMHVNRTL", test_fit_MHV_NRTL) &
]
end subroutine collect_suite
@@ -20,7 +22,7 @@ subroutine test_fit_kij_lij(error)
use yaeos__equilibria, only: EquilibriaState
type(error_type), allocatable, intent(out) :: error
class(ArModel), allocatable :: model
- type(EquilibriaState) :: exp_point
+ type(EquilibriaState) :: exp_points
real(pr) :: Tc(2) = [126.2, 568.7]
real(pr) :: pc(2) = [33.98, 24.90]
@@ -30,14 +32,15 @@ subroutine test_fit_kij_lij(error)
type(FitKijLij) :: fitting_problem
- exp_point = EquilibriaState( &
+ exp_points = &
+ EquilibriaState( &
kind="bubble", T=344.5_pr, P=23.9_pr, &
x=[0.0309_pr, 1 - 0.0309_pr], y=[0.9883_pr, 1 - 0.9883_pr], &
Vx=0._pr, Vy=0._pr, beta=0.0_pr &
)
fitting_problem%model = SoaveRedlichKwong(tc, pc, w)
- fitting_problem%experimental_points = [exp_point]
+ fitting_problem%experimental_points = [exp_points]
fitting_problem%parameter_step = [0.1, 0.1]
fitting_problem%fit_kij = .true.
@@ -49,9 +52,75 @@ subroutine test_fit_kij_lij(error)
call check(error, err_kij < err0)
fitting_problem%fit_lij = .true.
+ fitting_problem%verbose = .true.
X = 0
err_kij_lij = optimize(X, fitting_problem)
call check(error, err_kij_lij < err_kij)
end subroutine
+
+ subroutine test_fit_mhv_nrtl(error)
+ use yaeos__fitting, only: optimize, error_function
+ use yaeos__fitting_fit_nrtl_mhv, only: FitMHVNRTL
+ use yaeos__models, only: CubicEoS, GeModel, NRTL, SoaveRedlichKwong, MHV
+ use yaeos__equilibria, only: EquilibriaState
+ type(error_type), allocatable, intent(out) :: error
+ type(CubicEoS) :: model
+ type(NRTL) :: ge_model
+ type(MHV) :: mixrule
+ type(EquilibriaState) :: exp_point
+
+ real(pr) :: Tc(2) = [126.2, 568.7]
+ real(pr) :: pc(2) = [33.98, 24.90]
+ real(pr) :: w(2) = [3.7e-2_pr, 0.397_pr]
+ real(pr) :: X(7)
+ real(pr) :: err0, err_lij, err_ge, err_ge_lij
+
+ type(FitMHVNRTL) :: fitting_problem
+
+ exp_point = EquilibriaState( &
+ kind="bubble", T=344.5_pr, P=23.9_pr, &
+ x=[0.0309_pr, 1 - 0.0309_pr], y=[0.9883_pr, 1 - 0.9883_pr], &
+ Vx=0._pr, Vy=0._pr, beta=0.0_pr &
+ )
+
+
+ ! Provide initials for the NRTL model
+ ! reshape (a11 a12 a21 a22)
+ ge_model%a=reshape([0.0, 3.1, 0.1, 0.0], [2, 2])
+ ge_model%b=reshape([0.0, 503.1, 200.1, 0.0], [2, 2])
+ ge_model%c=reshape([0.0, 0.1, 0.1, 0.0], [2, 2])
+
+
+ model = SoaveRedlichKwong(tc, pc, w)
+ mixrule = MHV(ge=ge_model, q=-0.593_pr, b=model%b)
+ deallocate(model%mixrule)
+ model%mixrule = mixrule
+
+ fitting_problem%experimental_points = [exp_point]
+
+ X = [3.1, 0.1, -500.00, 200.00, 0.1, 0.1, 0.0]
+ fitting_problem%model = model
+ fitting_problem%fit_lij = .true.
+ err0 = error_function(x, func_data=fitting_problem)
+ err_lij = optimize(X, fitting_problem)
+
+ X = [3.1, 0.1, -500.00, 200.00, 0.1, 0.1, 0.0]
+ fitting_problem%model = model
+ fitting_problem%fit_lij = .false.
+ fitting_problem%fit_nrtl = .true.
+ err_ge = optimize(X, fitting_problem)
+
+ X = [3.1, 0.1, -500.00, 200.00, 0.1, 0.1, 0.0]
+ fitting_problem%model = model
+ fitting_problem%fit_lij = .true.
+ fitting_problem%fit_nrtl = .true.
+ err_ge_lij = optimize(X, fitting_problem)
+
+
+ call check(error, err_lij < err0)
+ call check(error, err_ge < err_lij)
+ call check(error, err_ge_lij < err_lij)
+
+ end subroutine
end module test_fitting
diff --git a/test/test_flash.f90 b/test/test_flash.f90
index 9aa9151a7..53dd1a03d 100644
--- a/test/test_flash.f90
+++ b/test/test_flash.f90
@@ -11,12 +11,55 @@ subroutine collect_suite(testsuite)
new_unittest("FlashPT", test_flash_pt), &
new_unittest("FlashTV", test_flash_tv), &
new_unittest("FlashPT Failed", test_flash_pt_failed), &
- new_unittest("FlashPT Bad Specification", test_flash_pt_bad_spec) &
+ new_unittest("FlashPT Bad Specification", test_flash_pt_bad_spec), &
+ new_unittest("Stability tm minimization", test_tm) &
]
end subroutine collect_suite
+ subroutine test_tm(error)
+ use forsus, only: Substance, forsus_dir
+ use yaeos
+ use yaeos__phase_equilibria_stability, only: tm, min_tpd
+ use yaeos, only: flash
+ implicit none
+ type(error_type), allocatable, intent(out) :: error
+
+ integer, parameter :: nc=2
+
+ class(ArModel), allocatable :: model
+ type(Substance) :: sus(nc)
+ real(pr) :: tc(nc), pc(nc), ac(nc)
+ real(pr) :: z(nc), T, P
+ real(pr) :: w(nc), mintpd
+
+ forsus_dir = "build/dependencies/forsus/data/json"
+ sus(1) = Substance("methane")
+ sus(2) = Substance("hydrogen sulfide")
+
+ z = [0.13, 1-0.13]
+ z = z/sum(z)
+
+ P = 20.0_pr
+ T = 190._pr
+
+ tc = sus%critical%critical_temperature%value
+ pc = sus%critical%critical_pressure%value/1e5_pr
+ ac = sus%critical%acentric_factor%value
+
+ model = SoaveRedlichKwong(tc, pc, ac)
+
+ call min_tpd(model, z, P, T, mintpd, w)
+ call check(error, abs(mintpd - 5.3e-6_pr) < 1e-5)
+
+ P = 15
+ call min_tpd(model, z, P, T, mintpd, w)
+ call check(error, abs(mintpd - (-0.1883_pr)) < 1e-4)
+
+ call check(error, abs(tm(model, z, w, p, t) - mintpd) < 1e-10_pr)
+ end subroutine test_tm
+
subroutine test_flash_pt(error)
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
type(error_type), allocatable, intent(out) :: error
integer, parameter :: nc = 2
@@ -52,7 +95,7 @@ subroutine test_flash_pt(error)
end subroutine test_flash_pt
subroutine test_flash_tv(error)
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
use fixtures_models, only: binary_PR76
type(error_type), allocatable, intent(out) :: error
@@ -61,7 +104,7 @@ subroutine test_flash_tv(error)
real(pr) :: x(nc) = [6.8598497458814592E-002, 0.93140153234346601]
real(pr) :: y(nc) = [0.61055654015073813, 0.38944348965161085]
real(pr) :: vx = 9.3682339483042124E-002
- real(pr) :: vy = 2.3935064128338039
+ real(pr) :: vy = 2.3935064128338039
real(pr) :: beta = 0.61148923421371815
real(pr) :: P = 6.097517429661468
@@ -78,8 +121,8 @@ subroutine test_flash_tv(error)
V = 1.5_pr
t = 210
k0 = (model%components%Pc/10._pr) &
- * exp(5.373_pr*(1 + model%components%w)&
- * (1 - model%components%Tc/T))
+ * exp(5.373_pr*(1 + model%components%w)&
+ * (1 - model%components%Tc/T))
flash_result = flash(model, n, t=t, v_spec=v, k0=k0, iters=iters)
@@ -92,7 +135,7 @@ subroutine test_flash_tv(error)
end subroutine test_flash_tv
subroutine test_flash_pt_failed(error)
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
type(error_type), allocatable, intent(out) :: error
integer, parameter :: nc = 2
@@ -124,7 +167,7 @@ subroutine test_flash_pt_failed(error)
end subroutine test_flash_pt_failed
subroutine test_flash_pt_bad_spec(error)
- use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel, fugacity_tp
+ use yaeos, only: pr, EquilibriaState, flash, PengRobinson76, ArModel
type(error_type), allocatable, intent(out) :: error
integer, parameter :: nc = 2
diff --git a/test/test_implementations/ar_models/cubics/test_pr76.f90 b/test/test_implementations/ar_models/cubics/test_pr76.f90
index 8df8e1eca..61459b8ab 100644
--- a/test/test_implementations/ar_models/cubics/test_pr76.f90
+++ b/test/test_implementations/ar_models/cubics/test_pr76.f90
@@ -96,11 +96,11 @@ subroutine test_pr76_cons_mixture(error)
Ar=Ar_num, Arn2=Arn2_num)
! Calling individually just because coverage
- call ar_consistency(model, n, v, t, eq31=eq31)
- call ar_consistency(model, n, v, t, eq33=eq33)
- call ar_consistency(model, n, v, t, eq34=eq34)
- call ar_consistency(model, n, v, t, eq36=eq36)
- call ar_consistency(model, n, v, t, eq37=eq37)
+ call ar_consistency(model, n, V, T, eq31=eq31)
+ call ar_consistency(model, n, V, T, eq33=eq33)
+ call ar_consistency(model, n, V, T, eq34=eq34)
+ call ar_consistency(model, n, V, T, eq36=eq36)
+ call ar_consistency(model, n, V, T, eq37=eq37)
! Numeric derivatives
call check(error, rel_error(Ar, Ar_num) < 1e-6)
@@ -115,11 +115,11 @@ subroutine test_pr76_cons_mixture(error)
call check(error, maxval(rel_error(Arn2, Arn2_num)) < 1e-5)
! Consistency tests
- call check(error, abs(eq31) <= 1e-15)
- call check(error, maxval(abs(eq33)) < 1e-15)
+ call check(error, abs(eq31) <= 1e-14)
+ call check(error, maxval(abs(eq33)) < 1e-14)
call check(error, maxval(abs(eq34)) < 1e-14)
- call check(error, abs(eq36) <= 1e-15)
- call check(error, abs(eq37) <= 1e-15)
+ call check(error, abs(eq36) <= 1e-14)
+ call check(error, abs(eq37) <= 1e-14)
! ========================================================================
! Model with kij and lij
@@ -241,7 +241,6 @@ end subroutine test_pr76_cons_pure
subroutine test_pr76_compressibility_factor(error)
! From original paper.
use yaeos, only: pr, R, PengRobinson76, ArModel
- use yaeos__thermoprops, only: volume
type(error_type), allocatable, intent(out) :: error
integer :: i
@@ -272,7 +271,7 @@ subroutine test_pr76_compressibility_factor(error)
Z1 = [0.151_pr, 0.248_pr, 0.482_pr, 0.707_pr, 0.926_pr]
do i=1,5
- call volume(model, z, P1(i), T, V=v, root_type="stable")
+ call model%volume(z, P1(i), T, V=v, root_type="stable")
Zcomp = P1(i) * v / (R * T)
call check(error, abs(Zcomp - Z1(i)) < 1e-3)
@@ -284,7 +283,7 @@ subroutine test_pr76_compressibility_factor(error)
Z2 = [0.289_pr, 0.482_pr, 0.665_pr, 0.840_pr]
do i=1,4
- call volume(model, z, P2(i), T, V=v, root_type="stable")
+ call model%volume(z, P2(i), T, V=v, root_type="stable")
Zcomp = P2(i) * v / (R * T)
call check(error, abs(Zcomp - Z2(i)) < 1e-3)
@@ -296,7 +295,7 @@ subroutine test_pr76_compressibility_factor(error)
Z3 = [0.804_pr, 0.696_pr, 0.643_pr, 0.744_pr, 0.869_pr]
do i=1,5
- call volume(model, z, P3(i), T, V=v, root_type="stable")
+ call model%volume(z, P3(i), T, V=v, root_type="stable")
Zcomp = P3(i) * v / (R * T)
call check(error, abs(Zcomp - Z3(i)) < 1e-3)
@@ -311,7 +310,7 @@ subroutine test_pr76_compressibility_factor(error)
Z4 = [0.215_pr, 0.404_pr, 0.580_pr, 0.750_pr]
do i=1,4
- call volume(model, z, P4(i), T, V=v, root_type="stable")
+ call model%volume(z, P4(i), T, V=v, root_type="stable")
Zcomp = P4(i) * v / (R * T)
call check(error, abs(Zcomp - Z4(i)) < 1e-3)
@@ -323,7 +322,7 @@ subroutine test_pr76_compressibility_factor(error)
Z5 = [0.782_pr, 0.638_pr, 0.545_pr, 0.645_pr, 0.765_pr]
do i=1,5
- call volume(model, z, P5(i), T, V=v, root_type="stable")
+ call model%volume( z, P5(i), T, V=v, root_type="stable")
Zcomp = P5(i) * v / (R * T)
call check(error, abs(Zcomp - Z5(i)) < 1e-3)
@@ -335,7 +334,7 @@ subroutine test_pr76_compressibility_factor(error)
Z6 = [0.920_pr, 0.870_pr, 0.796_pr, 0.806_pr, 0.877_pr]
do i=1,5
- call volume(model, z, P6(i), T, V=v, root_type="stable")
+ call model%volume(z, P6(i), T, V=v, root_type="stable")
Zcomp = P6(i) * v / (R * T)
call check(error, abs(Zcomp - Z6(i)) < 2e-2)
@@ -345,21 +344,23 @@ end subroutine test_pr76_compressibility_factor
subroutine test_pr76_co2_volume(error)
! From Elliot's book.
use yaeos, only : pr, PengRobinson76, ArModel
- use yaeos__thermoprops, only: volume
+ use yaeos__models_ar, only: volume
type(error_type), allocatable, intent(out) :: error
class(ArModel), allocatable :: model
real(pr) :: mw, V, n(1)
- integer :: i
model = PengRobinson76([304.2_pr], [73.82_pr], [0.228_pr])
n = [1.0_pr]
mw = 44.01 ! g / mol
- call volume(model, n, 8.0_pr, 310.0_pr, V=V, root_type="stable")
+ call model%volume(n, 8.0_pr, 310.0_pr, V=V, root_type="stable")
call check(error, abs(V / mw * 1000 - 70.37) < 0.06)
+ call model%volume(n, 75.0_pr, 310.0_pr, V=V, root_type="stable")
+ call check(error, abs(V / mw * 1000 - 3.84) < 0.01)
+
call volume(model, n, 75.0_pr, 310.0_pr, V=V, root_type="stable")
call check(error, abs(V / mw * 1000 - 3.84) < 0.01)
end subroutine test_pr76_co2_volume
@@ -367,12 +368,11 @@ end subroutine test_pr76_co2_volume
subroutine test_pr76_fugacities(error)
! K values of N2-CH4 (0.5, 0.5) mixture from Elliot's book.
use yaeos, only: pr, R, PengRobinson76, ArModel
- use yaeos__thermoprops, only: fugacity_tp, volume
type(error_type), allocatable, intent(out) :: error
class(ArModel), allocatable :: model
- real(pr) :: T, P, z_v(2), z_l(2), v_v, lnphip_l(2), lnphip_v(2)
+ real(pr) :: T, P, z_v(2), z_l(2), v_v, lnphi_l(2), lnphi_v(2)
T = 100 ! K
P = 4.119 ! bar
@@ -385,20 +385,20 @@ subroutine test_pr76_fugacities(error)
[0.040_pr, 0.011_pr] &
)
- call volume(model, z_v, P, T, root_type="vapor", V=v_v)
- call fugacity_tp(model, z_v, T, P, root_type="vapor", lnphip = lnphip_v)
- call fugacity_tp(model, z_l, T, P, root_type="liquid", lnphip = lnphip_l)
+ call model%volume(z_v, P, T, root_type="vapor", V=v_v)
+ call model%lnphi_pt(z_v, P, T, root_type="vapor", lnPhi = lnphi_v)
+ call model%lnphi_pt(z_l, P, T, root_type="liquid", lnPhi = lnphi_l)
! Elliot Z value of vapor
call check(error, abs(P * v_v / R / T - 0.9059) < 1e-4)
! Elliot vapor fugacities
- call check(error, abs(exp(lnphip_v(1) - log(P)) - 0.9162) < 1e-4)
- call check(error, abs(exp(lnphip_v(2) - log(P)) - 0.8473) < 1e-4)
+ call check(error, abs(exp(lnPhi_v(1)) - 0.9162) < 1e-4)
+ call check(error, abs(exp(lnPhi_v(2)) - 0.8473) < 1e-4)
! Elliot liquid fugacities
- call check(error, abs(exp(lnphip_l(1) - log(P)) - 1.791) < 1e-3)
- call check(error, abs(exp(lnphip_l(2) - log(P)) - 0.0937) < 1e-4)
+ call check(error, abs(exp(lnPhi_l(1)) - 1.791) < 1e-3)
+ call check(error, abs(exp(lnPhi_l(2)) - 0.0937) < 1e-4)
end subroutine test_pr76_fugacities
subroutine test_pr76_txy_methanol_benzene(error)
diff --git a/test/test_math/test_math.f90 b/test/test_math/test_math.f90
index b3b6bb5e3..9b94146c6 100644
--- a/test/test_math/test_math.f90
+++ b/test/test_math/test_math.f90
@@ -12,7 +12,10 @@ subroutine collect_suite(testsuite)
testsuite = [ &
new_unittest("Test dx_to_dn", test_dx_to_dn), &
- new_unittest("Test sq_error", test_sq_error) &
+ new_unittest("Test sq_error", test_sq_error), &
+ new_unittest("Test cardano", test_cardano_method), &
+ new_unittest("Test rosendo", test_rosendo_method), &
+ new_unittest("Test newton", test_newton_method) &
]
end subroutine collect_suite
@@ -45,6 +48,138 @@ subroutine test_sq_error(error)
call check(error, allclose(errors_sq, (sim - exps)**2, 1e10_pr))
end subroutine test_sq_error
-end module test_math
+ subroutine test_cardano_method(error)
+ use yaeos__math_linalg, only: pr, cubic_roots
+ type(error_type), allocatable, intent(out) :: error
+ real(pr) :: p(4)
+ real(pr) :: rr(3)
+ complex(pr) :: cr(3)
+ real(pr) :: num
+ integer :: flag
+
+ p = [1, -10, 35, -50]
+ call cubic_roots(p, rr, cr, flag)
+ call check(error, flag == 1)
+ call check(error, abs(rr(1) - 5.0_pr) < 1e-10_pr)
+
+ p = [0.1, -2.6, 1., 1.]
+ call cubic_roots(p, rr, cr, flag)
+ call check(error, flag == -1)
+ call check(error, &
+ maxval(abs(rr - [-0.454216, 0.8601986, 25.594016])) < 1e-5_pr &
+ )
+
+ ! =======================================================================
+ ! 3 Real roots
+ ! x1 = 1, x2 = 3, x3 = 4
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -8._pr, 19._pr, -12._pr]
+
+ call cubic_roots(p, rr, cr, flag)
+
+ call check(error, maxval(rr - [1.0_pr, 3.0_pr, 4.0_pr]) < 1e-7)
+ call check(error, flag == -1)
+
+ ! =======================================================================
+ ! 1 real root different, 2 equal real roots
+ ! x1 = 1, x2 = x3 = 4
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -9._pr, 24._pr, -16._pr]
+
+ call cubic_roots(p, rr, cr, flag)
+
+ call check(error, maxval(rr - [1.0_pr, 4.0_pr, 4.0_pr]) < 1e-7)
+ call check(error, flag == 0)
+
+ ! =======================================================================
+ ! 1 real root, 2 complex
+ ! x1 = 1, x2 = i, x3 = -i
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -1._pr, 1._pr, -1._pr]
+
+ call cubic_roots(p, rr, cr, flag)
+
+ call check(error, (rr(1) - 1.0_pr) < 1e-7)
+ call check(error, flag == 1)
+ end subroutine test_cardano_method
+
+ subroutine test_rosendo_method(error)
+ use yaeos__math_linalg, only: pr, cubic_roots_rosendo
+
+ type(error_type), allocatable, intent(out) :: error
+
+ real(pr) :: p(4)
+ real(pr) :: a, b
+ real(pr) :: roots(3)
+ complex(pr) :: c_roots(3)
+ integer :: flag
+ ! =======================================================================
+ ! 3 Real roots
+ ! x1 = 1, x2 = 3, x3 = 4
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -8._pr, 19._pr, -12._pr]
+
+ call cubic_roots_rosendo(p, roots, c_roots, flag)
+
+ call check(error, maxval(roots - [1.0_pr, 3.0_pr, 4.0_pr]) < 1e-7)
+ call check(error, flag == -1)
+
+ ! =======================================================================
+ ! 1 real root different, 2 equal real roots
+ ! x1 = 1, x2 = x3 = 4
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -9._pr, 24._pr, -16._pr]
+
+ call cubic_roots_rosendo(p, roots, c_roots, flag)
+
+ call check(error, maxval(roots - [1.0_pr, 4.0_pr, 4.0_pr]) < 1e-7)
+ call check(error, flag == -1)
+
+ ! =======================================================================
+ ! 1 real root, 2 complex
+ ! x1 = 1, x2 = i, x3 = -i
+ ! -----------------------------------------------------------------------
+ p = [1._pr, -1._pr, 1._pr, -1._pr]
+
+ call cubic_roots_rosendo(p, roots, c_roots, flag)
+
+ call check(error, maxval(roots - [1.0_pr, 1.0_pr, 1.0_pr]) < 1e-7)
+ call check(error, flag == 1)
+
+ ! =======================================================================
+ ! 1 real root and two small complex roots
+ ! x1 = 1, x2 = a+bi, x3 = a-bi
+ ! -----------------------------------------------------------------------
+ a = 1._pr
+ b = 1e-6_pr
+
+ p = [1._pr, -(2*a + 1), (a**2 + b**2 + 2 * a), -(a**2 + b**2)]
+
+ call cubic_roots_rosendo(p, roots, c_roots, flag)
+
+ call check(error, maxval(roots - [1.0_pr, 1.0_pr, 1.0_pr]) < 1e-7)
+ call check(error, flag == 1)
+ end subroutine test_rosendo_method
+
+ subroutine test_newton_method(error)
+ use yaeos__math, only: pr, newton
+ type(error_type), allocatable, intent(out) :: error
+ real(pr) :: x
+ real(pr) :: tol=1e-5
+ integer :: max_iters = 100
+
+ x = 0.5
+ call newton(foo, x, tol, max_iters)
+ call check(error, abs(x - sqrt(2._pr)) < tol)
+ contains
+ subroutine foo(xx, f, df)
+ real(pr), intent(in) :: xx
+ real(pr), intent(out) :: f
+ real(pr), intent(out) :: df
+ f = xx**2 - 2
+ df = 2*xx
+ end subroutine foo
+ end subroutine test_newton_method
+end module test_math
diff --git a/test/test_runner.f90 b/test/test_runner.f90
index 3d49bc456..50efbda3f 100644
--- a/test/test_runner.f90
+++ b/test/test_runner.f90
@@ -32,7 +32,7 @@ program tester
! -------------------------------------------------------------------------
use test_fitting, only: suite_fitting => collect_suite
- use stdlib_ansi, only: fg_color_green, fg_color_red, operator(//), style_reset
+ use stdlib_ansi, only: style_bold, fg_color_green, fg_color_red, operator(//), style_reset
implicit none
@@ -74,7 +74,8 @@ program tester
do is = 1, size(testsuites)
- write (error_unit, fmt) "Testing:", testsuites(is)%name
+ write (error_unit, fmt) "Testing:", &
+ style_bold // testsuites(is)%name // style_reset
call run_testsuite(testsuites(is)%collect, error_unit, stat)
end do
diff --git a/test/test_saturation.f90 b/test/test_saturation.f90
index 9c408dea7..36e1b807a 100644
--- a/test/test_saturation.f90
+++ b/test/test_saturation.f90
@@ -107,7 +107,7 @@ subroutine test_dew_temperature(error)
end subroutine
subroutine test_bubble_temperature(error)
- use yaeos, only: pr, EquilibriaState, saturation_temperature, ArModel
+ use yaeos, only: pr, EquilibriaState, saturation_temperature, ArModel, saturation_pressure, PTEnvel2, pt_envelope_2ph
use fixtures_models, only: binary_PR76
type(error_type), allocatable, intent(out) :: error
@@ -125,8 +125,7 @@ subroutine test_bubble_temperature(error)
n = [0.4_pr, 0.6_pr]
T = 200
model = binary_PR76()
-
- bubble = saturation_temperature(model, n, P, kind="bubble", t0=300._pr)
+ bubble = saturation_temperature(model, n, P, kind="bubble",t0=201._pr)
call check(error, maxval(abs(bubble%x - x)) < abs_tolerance)
call check(error, maxval(abs(bubble%y - y)) < abs_tolerance)
call check(error, abs(bubble%p - p) < abs_tolerance)
diff --git a/test/test_thermoprops.f90 b/test/test_thermoprops.f90
index fe3a5f1fc..9a7e495c8 100644
--- a/test/test_thermoprops.f90
+++ b/test/test_thermoprops.f90
@@ -21,7 +21,7 @@ end subroutine collect_suite
subroutine test_fugacity_VT(error)
use fixtures_models, only: binary_PR76
- use yaeos, only: pr, CubicEoS, fugacity_vt
+ use yaeos, only: pr, CubicEoS
type(error_type), allocatable, intent(out) :: error
type(CubicEoS) :: eos
@@ -33,7 +33,7 @@ subroutine test_fugacity_VT(error)
real(pr) :: lnfug_val(2), dlnphidp_val(2), dlnphidt_val(2)
- lnfug_val = [2.0758887796938881, -2.2852154042663555]
+ lnfug_val = [2.0785927055052529, -2.2825114783106386]
dlnphidp_val = [-0.99328668293856137, -0.9965756859512391]
dlnphidt_val = [3.0263825169536504E-002, 7.6204959316774373E-002]
@@ -43,14 +43,9 @@ subroutine test_fugacity_VT(error)
v = 8.8780451065729321E-002_pr
t = 150
- call fugacity_vt(eos, &
+ call eos%lnphi_vt(&
z, V, T, P, lnfug, dlnPhidP, dlnphidT, dlnPhidn &
)
-
- print * , lnfug
- print * , dlnphidP
- print * , dlnphidT
-
call check( &
error, maxval(abs(lnfug - lnfug_val)) < 1e-5 &
)
@@ -64,7 +59,7 @@ end subroutine test_fugacity_VT
subroutine test_fugacity_TP(error)
use fixtures_models, only: binary_PR76
- use yaeos, only: pr, CubicEoS, fugacity_tp
+ use yaeos, only: pr, CubicEoS
type(error_type), allocatable, intent(out) :: error
type(CubicEoS) :: eos
@@ -90,9 +85,8 @@ subroutine test_fugacity_TP(error)
t = 150
root_type = "liquid"
-
- call fugacity_tp(eos, &
- z, T, P, V, root_type, lnfug, dlnPhidP, dlnphidT, dlnPhidn&
+ call eos%lnphi_pt(&
+ z, P, T, V, root_type, lnfug, dlnPhidP, dlnphidT, dlnPhidn&
)
call check(&
@@ -111,7 +105,6 @@ end subroutine test_fugacity_TP
! --------------------------------------------------------------------------
subroutine test_enthalpy_residual_vt(error)
use yaeos, only: pr, R, CubicEoS, PengRobinson76
- use yaeos, only: enthalpy_residual_vt, fugacity_vt
type(error_type), allocatable, intent(out) :: error
@@ -143,11 +136,11 @@ subroutine test_enthalpy_residual_vt(error)
eos = PengRobinson76(tc, pc, w, kij, lij)
! yaeos residual enthalpies
- call enthalpy_residual_vt(eos, z, v, t, Hr, HrT=HrT, HrV=HrV, Hrn=Hrn)
+ call eos%enthalpy_residual_vt(z, v, t, Hr, HrT=HrT, HrV=HrV, Hrn=Hrn)
! test against fugacity coefficient derivatives
! (Michelsen and Mollerup chapter 2 eq 37)
- call fugacity_vt(eos, z, v, t, lnphip=lnfug, dlnphidt=dlnphidt)
+ call eos%lnphi_vt(z, v, t, lnPhi=lnfug, dlnphidt=dlnphidt)
Hr_fromphi = -1_pr * sum(z * dlnphidT) * R * t**2 ! Hr(T,P) = Hr(T,V)
@@ -157,7 +150,7 @@ subroutine test_enthalpy_residual_vt(error)
! numeric derivatives residual enthalpies
! HrT_num
- call enthalpy_residual_vt(eos, z, v, t + delta_t, Hr_delta_t)
+ call eos%enthalpy_residual_vt(z, v, t + delta_t, Hr_delta_t)
HrT_num = (Hr_delta_t - Hr) / delta_t
@@ -166,7 +159,7 @@ subroutine test_enthalpy_residual_vt(error)
)
! HrV_num
- call enthalpy_residual_vt(eos, z, v + delta_v, t, Hr_delta_v)
+ call eos%enthalpy_residual_vt(z, v + delta_v, t, Hr_delta_v)
HrV_num = (Hr_delta_v - Hr) / delta_v
@@ -176,10 +169,10 @@ subroutine test_enthalpy_residual_vt(error)
! Hrn_num
zd1 = [0.3_pr + delta_n, 0.7_pr]
- call enthalpy_residual_vt(eos, zd1, v, t, Hr_delta_n1)
+ call eos%enthalpy_residual_vt(zd1, v, t, Hr_delta_n1)
zd2 = [0.3_pr, 0.7_pr + delta_n]
- call enthalpy_residual_vt(eos, zd2, v, t, Hr_delta_n2)
+ call eos%enthalpy_residual_vt(zd2, v, t, Hr_delta_n2)
Hrn_num = [(Hr_delta_n1 - Hr) / delta_n, (Hr_delta_n2 - Hr) / delta_n]
@@ -194,7 +187,6 @@ end subroutine test_enthalpy_residual_vt
! --------------------------------------------------------------------------
subroutine test_gibss_residual_vt(error)
use yaeos, only: pr, R, CubicEoS, SoaveRedlichKwong
- use yaeos, only: gibbs_residual_vt, fugacity_vt, pressure
type(error_type), allocatable, intent(out) :: error
@@ -225,22 +217,22 @@ subroutine test_gibss_residual_vt(error)
eos = SoaveRedlichKwong(tc, pc, w, kij, lij)
- call pressure(eos, z, v, t, p)
+ call eos%pressure(z, v, t, p)
ntot = sum(z)
Zcomp = p*v/(ntot*R*t)
! yaeos residual gibbs
- call gibbs_residual_vt(eos, z, v, t, Gr, GrT=GrT, GrV=GrV, Grn=Grn)
+ call eos%gibbs_residual_vt(z, V, T, Gr, GrT=GrT, GrV=GrV, Grn=Grn)
! test against fugacity coefficient
! (Michelsen and Mollerup chapter 2 eq 31)
- call fugacity_vt(eos, z, v, t, lnphip=lnfug)
+ call eos%lnphi_vt(z, V, T, lnPhi=lnfug)
- lnfugcoeffs = lnfug - log(p) ! lnfug is = ln(phi * p)
+ lnfugcoeffs = lnfug
- Gr_tp = Gr - ntot*R*t*log(Zcomp) ! M and M chapter 1 Table 6
+ Gr_tp = Gr - ntot*R*T*log(Zcomp) ! M and M chapter 1 Table 6
- Gr_fromphi = sum(z * lnfugcoeffs) * R * t
+ Gr_fromphi = sum(z * lnfugcoeffs) * R * T
call check(&
error, rel_error(Gr_tp, Gr_fromphi) < 1e-14 &
@@ -248,7 +240,7 @@ subroutine test_gibss_residual_vt(error)
! numeric derivatives residual enthalpies
! GrT_num
- call gibbs_residual_vt(eos, z, v, t + delta_t, Gr_delta_t)
+ call eos%gibbs_residual_vt(z, v, t + delta_t, Gr_delta_t)
GrT_num = (Gr_delta_t - Gr) / delta_t
@@ -257,7 +249,7 @@ subroutine test_gibss_residual_vt(error)
)
! GrV_num
- call gibbs_residual_vt(eos, z, v + delta_v, t, Gr_delta_v)
+ call eos%gibbs_residual_vt(z, v + delta_v, t, Gr_delta_v)
GrV_num = (Gr_delta_v - Gr) / delta_v
@@ -267,10 +259,10 @@ subroutine test_gibss_residual_vt(error)
! Grn_num
zd1 = [0.3_pr + delta_n, 0.7_pr]
- call gibbs_residual_vt(eos, zd1, v, t, Gr_delta_n1)
+ call eos%gibbs_residual_vt(zd1, v, t, Gr_delta_n1)
zd2 = [0.3_pr, 0.7_pr + delta_n]
- call gibbs_residual_vt(eos, zd2, v, t, Gr_delta_n2)
+ call eos%gibbs_residual_vt(zd2, v, t, Gr_delta_n2)
Grn_num = [(Gr_delta_n1 - Gr) / delta_n, (Gr_delta_n2 - Gr) / delta_n]
@@ -284,10 +276,7 @@ end subroutine test_gibss_residual_vt
! Sr
! --------------------------------------------------------------------------
subroutine test_entropy_residual_vt(error)
- use yaeos, only: pr, R, CubicEoS, SoaveRedlichKwong, pressure
- use yaeos, only: entropy_residual_vt
- use yaeos, only: enthalpy_residual_vt
- use yaeos, only: gibbs_residual_vt
+ use yaeos, only: pr, R, CubicEoS, SoaveRedlichKwong
type(error_type), allocatable, intent(out) :: error
@@ -321,14 +310,14 @@ subroutine test_entropy_residual_vt(error)
eos = SoaveRedlichKwong(tc, pc, w, kij, lij)
- call pressure(eos, z, v, t, p)
+ call eos%pressure(z, v, t, p)
Zcomp = p*v/(ntot*R*t)
! yaeos residual gibbs
- call entropy_residual_vt(eos, z, v, t, Sr, SrT=SrT, SrV=SrV, Srn=Srn)
- call enthalpy_residual_vt(eos, z, v, t, Hr)
- call gibbs_residual_vt(eos, z, v, t, Gr)
+ call eos%entropy_residual_vt(z, v, t, Sr, SrT=SrT, SrV=SrV, Srn=Srn)
+ call eos%enthalpy_residual_vt(z, v, t, Hr)
+ call eos%gibbs_residual_vt(z, v, t, Gr)
! test against Hr and Gr
! (Michelsen and Mollerup chapter 2 eq 22)
@@ -341,7 +330,7 @@ subroutine test_entropy_residual_vt(error)
)
! SrT_num
- call entropy_residual_vt(eos, z, v, t + delta_t, Sr_delta_t)
+ call eos%entropy_residual_vt(z, v, t + delta_t, Sr_delta_t)
SrT_num = (Sr_delta_t - Sr) / delta_t
@@ -350,7 +339,7 @@ subroutine test_entropy_residual_vt(error)
)
! SrV_num
- call entropy_residual_vt(eos, z, v + delta_v, t, Sr_delta_v)
+ call eos%entropy_residual_vt(z, v + delta_v, t, Sr_delta_v)
SrV_num = (Sr_delta_v - Sr) / delta_v
@@ -360,10 +349,10 @@ subroutine test_entropy_residual_vt(error)
! Srn_num
zd1 = [0.3_pr + delta_n, 0.7_pr]
- call entropy_residual_vt(eos, zd1, v, t, Sr_delta_n1)
+ call eos%entropy_residual_vt(zd1, v, t, Sr_delta_n1)
zd2 = [0.3_pr, 0.7_pr + delta_n]
- call entropy_residual_vt(eos, zd2, v, t, Sr_delta_n2)
+ call eos%entropy_residual_vt(zd2, v, t, Sr_delta_n2)
Srn_num = [(Sr_delta_n1 - Sr) / delta_n, (Sr_delta_n2 - Sr) / delta_n]
@@ -377,8 +366,7 @@ end subroutine test_entropy_residual_vt
! --------------------------------------------------------------------------
subroutine cp_and_cv(error)
! TODO need derivatives dvdt to complete the test
- use yaeos, only: pr, R, CubicEoS, SoaveRedlichKwong, pressure
- use yaeos, only: Cp_residual_vt, Cv_residual_vt
+ use yaeos, only: pr, R, CubicEoS, SoaveRedlichKwong
type(error_type), allocatable, intent(out) :: error
@@ -406,12 +394,12 @@ subroutine cp_and_cv(error)
eos = SoaveRedlichKwong(tc, pc, w, kij, lij)
- call pressure(eos, z, v, t, p, dpdv=dpdv, dpdt=dpdt)
+ call eos%pressure(z, v, t, p, dpdv=dpdv, dpdt=dpdt)
! Dumb test need derivative dvdt to complete the test
! Michelsen and Mollerup chapter 2 eq 19
- call Cp_residual_vt(eos, z, v, t, Cpr)
- call Cv_residual_vt(eos, z, v, t, Cvr)
+ call eos%Cp_residual_vt(z, v, t, Cpr)
+ call eos%Cv_residual_vt(z, v, t, Cvr)
lefths = (Cpr - Cvr)/R
righths = -t/R*dpdt**2/dpdv - ntot
diff --git a/tools/notebooks/sympy.ipynb b/tools/notebooks/sympy.ipynb
new file mode 100644
index 000000000..d0a93f81a
--- /dev/null
+++ b/tools/notebooks/sympy.ipynb
@@ -0,0 +1,682 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import sympy as sp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - \\frac{K \\beta z}{\\left(\\beta \\left(K - 1\\right) + 1\\right)^{2}} + \\frac{z}{\\beta \\left(K - 1\\right) + 1}$"
+ ],
+ "text/plain": [
+ "-K*\\beta*z/(\\beta*(K - 1) + 1)**2 + z/(\\beta*(K - 1) + 1)"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "z, beta, K = sp.symbols(r\"z \\beta K\")\n",
+ "\n",
+ "x = z / (beta * (K - 1) + 1)\n",
+ "y = K * x\n",
+ "\n",
+ "dxdk = sp.diff(x, K)\n",
+ "sp.diff(y, K)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\frac{v_{x}}{v_{x} - v_{y}}$"
+ ],
+ "text/plain": [
+ "v_x/(v_x - v_y)"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "vx, vy, v = sp.symbols(r\"v_x, v_y, v\")\n",
+ "\n",
+ "v = beta * vy + (1-beta)*vx\n",
+ "\n",
+ "sp.solve(v, beta)[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " -\\beta*v_y/(\\beta - 1)**2 + v_y/(\\beta - 1)\n"
+ ]
+ }
+ ],
+ "source": [
+ "sp.print_fcode(sp.diff(sp.solve(v, vx)[0], beta))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\frac{v_{x}}{\\beta^{2}}$"
+ ],
+ "text/plain": [
+ "v_x/\\beta**2"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sp.diff(sp.solve(v, vy)[0], beta)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " -\\beta*z*(K - 1)/(\\beta*(K - 1) + 1)**2 + z/(\\beta*(K - 1) + 1)\n"
+ ]
+ }
+ ],
+ "source": [
+ "sp.print_fcode(sp.diff(z * (K - 1)/(1 + beta*(K-1)), K))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c1, c2, c3, Tr = sp.symbols(\"c1 c2 c3 Tr\")\n",
+ "\n",
+ "# sqrt_Tr = sp.Function(\"(1-\\sqrt{Tr})\")(Tr) # 1 - sp.sqrt(Tr)\n",
+ "\n",
+ "sqrt_Tr = 1 - sp.sqrt(Tr)\n",
+ "\n",
+ "a = (1 + c1 * (sqrt_Tr) + c2 * (sqrt_Tr) + c3 * (sqrt_Tr))**2\n",
+ "dadt = sp.diff(a, Tr)\n",
+ "dadt2 = sp.diff(dadt, Tr)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " -k*(3/(Tr + 2))**k/(Tr + 2)\n",
+ " k*(3/(Tr + 2))**k*(k + 1)/(Tr + 2)**2\n"
+ ]
+ }
+ ],
+ "source": [
+ "k, Tr = sp.symbols(\"k Tr\")\n",
+ "a = (3/(2 + Tr))**k\n",
+ "\n",
+ "dadtr = sp.diff(a, Tr).simplify()\n",
+ "dadtr2 = sp.diff(dadtr, Tr).simplify()\n",
+ "\n",
+ "sp.print_fcode(dadtr.simplify())\n",
+ "sp.print_fcode(dadtr2.simplify())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " (c1 + c2 + c3)*(c1*(sqrt(Tr) - 1) + c2*(sqrt(Tr) - 1) + c3*(sqrt(\n",
+ " @ Tr) - 1) - 1)/sqrt(Tr)\n",
+ " (1.0d0/2.0d0)*(c1**2 + 2*c1*c2 + 2*c1*c3 + c1 + c2**2 + 2*c2*c3 +\n",
+ " @ c2 + c3**2 + c3)/Tr**(3.0d0/2.0d0)\n"
+ ]
+ }
+ ],
+ "source": [
+ "sp.print_fcode(dadt.simplify())\n",
+ "sp.print_fcode(dadt2.simplify())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Combining rules"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "i, j = sp.symbols(\"i j\",cls=sp.Idx)\n",
+ "k = sp.IndexedBase(\"k\")\n",
+ "T = sp.symbols(\"T\")\n",
+ "ai = sp.Function(\"a_i\")(T)\n",
+ "aj = sp.Function(\"a_j\")(T)\n",
+ "\n",
+ "daijdt = sp.diff(sp.sqrt(ai*aj) * (1 - k[i,j]), T).simplify()\n",
+ "daijdt2 = sp.diff(daijdt, T)#.simplify()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - \\frac{\\sqrt{a_{i}{\\left(T \\right)} a_{j}{\\left(T \\right)}} \\left(\\frac{a_{i}{\\left(T \\right)} \\frac{d}{d T} a_{j}{\\left(T \\right)}}{2} + \\frac{a_{j}{\\left(T \\right)} \\frac{d}{d T} a_{i}{\\left(T \\right)}}{2}\\right) \\left(a_{i}{\\left(T \\right)} \\frac{d}{d T} a_{j}{\\left(T \\right)} + a_{j}{\\left(T \\right)} \\frac{d}{d T} a_{i}{\\left(T \\right)}\\right) \\left({k}_{i,j} - 1\\right)}{2 a_{i}^{2}{\\left(T \\right)} a_{j}^{2}{\\left(T \\right)}} + \\frac{\\sqrt{a_{i}{\\left(T \\right)} a_{j}{\\left(T \\right)}} \\left(a_{i}{\\left(T \\right)} \\frac{d}{d T} a_{j}{\\left(T \\right)} + a_{j}{\\left(T \\right)} \\frac{d}{d T} a_{i}{\\left(T \\right)}\\right) \\left({k}_{i,j} - 1\\right) \\frac{d}{d T} a_{j}{\\left(T \\right)}}{2 a_{i}{\\left(T \\right)} a_{j}^{2}{\\left(T \\right)}} + \\frac{\\sqrt{a_{i}{\\left(T \\right)} a_{j}{\\left(T \\right)}} \\left(a_{i}{\\left(T \\right)} \\frac{d}{d T} a_{j}{\\left(T \\right)} + a_{j}{\\left(T \\right)} \\frac{d}{d T} a_{i}{\\left(T \\right)}\\right) \\left({k}_{i,j} - 1\\right) \\frac{d}{d T} a_{i}{\\left(T \\right)}}{2 a_{i}^{2}{\\left(T \\right)} a_{j}{\\left(T \\right)}} - \\frac{\\sqrt{a_{i}{\\left(T \\right)} a_{j}{\\left(T \\right)}} \\left({k}_{i,j} - 1\\right) \\left(a_{i}{\\left(T \\right)} \\frac{d^{2}}{d T^{2}} a_{j}{\\left(T \\right)} + a_{j}{\\left(T \\right)} \\frac{d^{2}}{d T^{2}} a_{i}{\\left(T \\right)} + 2 \\frac{d}{d T} a_{i}{\\left(T \\right)} \\frac{d}{d T} a_{j}{\\left(T \\right)}\\right)}{2 a_{i}{\\left(T \\right)} a_{j}{\\left(T \\right)}}$"
+ ],
+ "text/plain": [
+ "-sqrt(a_i(T)*a_j(T))*(a_i(T)*Derivative(a_j(T), T)/2 + a_j(T)*Derivative(a_i(T), T)/2)*(a_i(T)*Derivative(a_j(T), T) + a_j(T)*Derivative(a_i(T), T))*(k[i, j] - 1)/(2*a_i(T)**2*a_j(T)**2) + sqrt(a_i(T)*a_j(T))*(a_i(T)*Derivative(a_j(T), T) + a_j(T)*Derivative(a_i(T), T))*(k[i, j] - 1)*Derivative(a_j(T), T)/(2*a_i(T)*a_j(T)**2) + sqrt(a_i(T)*a_j(T))*(a_i(T)*Derivative(a_j(T), T) + a_j(T)*Derivative(a_i(T), T))*(k[i, j] - 1)*Derivative(a_i(T), T)/(2*a_i(T)**2*a_j(T)) - sqrt(a_i(T)*a_j(T))*(k[i, j] - 1)*(a_i(T)*Derivative(a_j(T), (T, 2)) + a_j(T)*Derivative(a_i(T), (T, 2)) + 2*Derivative(a_i(T), T)*Derivative(a_j(T), T))/(2*a_i(T)*a_j(T))"
+ ]
+ },
+ "execution_count": 29,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "daijdt2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - \\frac{{n}_{i} \\sum_{i=1}^{N} 1}{\\left(\\sum_{i=1}^{N} {n}_{i}\\right)^{2}} + \\frac{1}{\\sum_{i=1}^{N} {n}_{i}}$"
+ ],
+ "text/plain": [
+ "-n[i]*Sum(1, (i, 1, N))/Sum(n[i], (i, 1, N))**2 + 1/Sum(n[i], (i, 1, N))"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "i, N = sp.symbols('i N', integer=True)\n",
+ "n = sp.IndexedBase(\"n\", shape=(N))\n",
+ "\n",
+ "zi = n[i]/sp.Sum(n[i], (i, 1, N))\n",
+ "\n",
+ "sp.diff(zi, n[i])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Huron-Vidal -like"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\sum_{i=1}^{N} \\frac{a{\\left(T \\right)} {n}_{i}}{{b}_{i}} + \\frac{G^{E}{\\left(n{\\left({n}_{i} \\right)},T \\right)} + \\sum_{i=1}^{N} R T \\log{\\left(\\frac{B{\\left(n{\\left({n}_{i} \\right)} \\right)}}{n{\\left({n}_{i} \\right)} {b}_{i}} \\right)} {n}_{i}}{q}$"
+ ],
+ "text/plain": [
+ "Sum(a(T)*n[i]/b[i], (i, 1, N)) + (G^E(n(n[i]), T) + Sum(R*T*log(B(n(n[i]))/(n(n[i])*b[i]))*n[i], (i, 1, N)))/q"
+ ]
+ },
+ "execution_count": 52,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import sympy as sp\n",
+ "def sum_i(exp):\n",
+ " N = sp.Idx(\"N\")\n",
+ " return sp.Sum(exp, (i, 1, N))\n",
+ "\n",
+ "q, R, T = sp.symbols(\"q R T\")\n",
+ "ni, bi = sp.symbols(\"n b\", cls=sp.IndexedBase)\n",
+ "i = sp.Idx(\"i\")\n",
+ "j = sp.Idx(\"j\")\n",
+ "ni = ni[i]\n",
+ "bi = bi[i]\n",
+ "\n",
+ "i = sp.Idx(\"i\")\n",
+ "a = sp.Function(\"a\")(T)\n",
+ "n = sp.Function(\"n\")(ni)\n",
+ "B = sp.Function(\"B\")(n)\n",
+ "\n",
+ "ge = sp.Function(r\"G^E\")(n, T)\n",
+ "\n",
+ "DB = sum_i(ni * a/bi) + 1/q * (ge + sum_i(ni * R*T*sp.log(B/(n*bi))))\n",
+ "DB"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\log{\\left(\\frac{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}{\\left({n}_{1} + {n}_{2} + {n}_{3}\\right) {b}_{1}} \\right)} {n}_{1} + \\log{\\left(\\frac{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}{\\left({n}_{1} + {n}_{2} + {n}_{3}\\right) {b}_{2}} \\right)} {n}_{2} + \\log{\\left(\\frac{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}{\\left({n}_{1} + {n}_{2} + {n}_{3}\\right) {b}_{3}} \\right)} {n}_{3}$"
+ ],
+ "text/plain": [
+ "log(B(n[1], n[2], n[3])/((n[1] + n[2] + n[3])*b[1]))*n[1] + log(B(n[1], n[2], n[3])/((n[1] + n[2] + n[3])*b[2]))*n[2] + log(B(n[1], n[2], n[3])/((n[1] + n[2] + n[3])*b[3]))*n[3]"
+ ]
+ },
+ "execution_count": 53,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\n",
+ "n = sp.symbols(\"N\")\n",
+ "ni, bi = sp.symbols(\"n b\", cls=sp.IndexedBase)\n",
+ "n1, b1 = ni[1], bi[1]\n",
+ "n2, b2 = ni[2], bi[2]\n",
+ "n3, b3 = ni[3], bi[3]\n",
+ "\n",
+ "B = sp.Function(\"B\")(n1, n2, n3)\n",
+ "\n",
+ "lnB = (\n",
+ " n1 * sp.log(B/((n1 + n2 + n3)*b1)) + \n",
+ " n2 * sp.log(B/((n1 + n2 + n3)*b2)) +\n",
+ " n3 * sp.log(B/((n1 + n2 + n3)*b3))\n",
+ ")\n",
+ "dD1 = sp.diff(lnB, n1).simplify()\n",
+ "dD12 = sp.diff(dD1, n2).simplify()\n",
+ "\n",
+ "lnB"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\frac{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} \\log{\\left(\\frac{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}{\\left({n}_{1} + {n}_{2} + {n}_{3}\\right) {b}_{1}} \\right)} - B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} + \\frac{\\partial}{\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{1} + \\frac{\\partial}{\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{2} + \\frac{\\partial}{\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{3}}{B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}$"
+ ],
+ "text/plain": [
+ "(B(n[1], n[2], n[3])*log(B(n[1], n[2], n[3])/((n[1] + n[2] + n[3])*b[1])) - B(n[1], n[2], n[3]) + Derivative(B(n[1], n[2], n[3]), n[1])*n[1] + Derivative(B(n[1], n[2], n[3]), n[1])*n[2] + Derivative(B(n[1], n[2], n[3]), n[1])*n[3])/B(n[1], n[2], n[3])"
+ ]
+ },
+ "execution_count": 51,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "lnB.diff(n1).simplify()#.diff(n2).simplify()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\sum_{i=1}^{N} \\begin{cases} \\frac{\\left(\\log{\\left(\\frac{B{\\left({n}_{j} \\right)}}{{b}_{j} \\sum_{i=1}^{N} {n}_{i}} \\right)} - 1 + \\frac{\\frac{\\partial}{\\partial {n}_{j}} B{\\left({n}_{j} \\right)} {n}_{j}}{B{\\left({n}_{j} \\right)}}\\right) {n}_{j}}{\\sum_{i=1}^{N} {n}_{i}} & \\text{for}\\: N \\geq j \\wedge j \\geq 1 \\\\0 & \\text{otherwise} \\end{cases}$"
+ ],
+ "text/plain": [
+ "Sum(Piecewise(((log(B(n[j])/(b[j]*Sum(n[i], (i, 1, N)))) - 1 + Derivative(B(n[j]), n[j])*n[j]/B(n[j]))*n[j]/Sum(n[i], (i, 1, N)), (j >= 1) & (N >= j)), (0, True)), (i, 1, N))"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "B=sp.Function(\"B\")(ni[i])\n",
+ "logB_nbi = sum_i(ni[i] * sp.log(B/(sum_i(ni[i]) * bi[i])))\n",
+ "\n",
+ "logB_nbi.diff(ni[j]).simplify()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\frac{- \\left({n}_{1} + {n}_{2} + {n}_{3}\\right) \\frac{\\partial}{\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} \\frac{\\partial}{\\partial {n}_{2}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} + \\left(\\frac{\\partial}{\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} + \\frac{\\partial^{2}}{\\partial {n}_{2}\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{1} + \\frac{\\partial^{2}}{\\partial {n}_{2}\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{2} + \\frac{\\partial^{2}}{\\partial {n}_{2}\\partial {n}_{1}} B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)} {n}_{3}\\right) B{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}{B^{2}{\\left({n}_{1},{n}_{2},{n}_{3} \\right)}}$"
+ ],
+ "text/plain": [
+ "(-(n[1] + n[2] + n[3])*Derivative(B(n[1], n[2], n[3]), n[1])*Derivative(B(n[1], n[2], n[3]), n[2]) + (Derivative(B(n[1], n[2], n[3]), n[1]) + Derivative(B(n[1], n[2], n[3]), n[1], n[2])*n[1] + Derivative(B(n[1], n[2], n[3]), n[1], n[2])*n[2] + Derivative(B(n[1], n[2], n[3]), n[1], n[2])*n[3])*B(n[1], n[2], n[3]))/B(n[1], n[2], n[3])**2"
+ ]
+ },
+ "execution_count": 50,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dBi = sp.diff(B, n1)\n",
+ "\n",
+ "coso = (\n",
+ " n1 * dBi + n2 * dBi + n3 * dBi\n",
+ ")/B\n",
+ "\n",
+ "coso.diff(n2).simplify()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Ge Models"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle \\frac{E e^{- \\frac{E}{T}}}{T^{2}}$"
+ ],
+ "text/plain": [
+ "E*exp(-E/T)/T**2"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "t, e = sp.symbols(\"T E\")\n",
+ "\n",
+ "psi = sp.exp(-e / t)\n",
+ "\n",
+ "sp.diff(psi, t)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'psi' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m sp\u001b[38;5;241m.\u001b[39mdiff(sp\u001b[38;5;241m.\u001b[39mdiff(\u001b[43mpsi\u001b[49m, t),t)\u001b[38;5;241m.\u001b[39msimplify()\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'psi' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "sp.diff(sp.diff(psi, t),t).simplify()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Cubic roots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import sympy as sp\n",
+ "P, R, T, v, b, a, d1, d2 = sp.symbols(r\"P R T v b a \\delta_1 \\delta_2\")\n",
+ "zero = R*T/(v-b) - a/((v+d1*b)*(v+d2*b)) - P"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - P - \\frac{R T}{b - v} - \\frac{a}{\\left(\\delta_{1} b + v\\right) \\left(\\delta_{2} b + v\\right)}$"
+ ],
+ "text/plain": [
+ "-P - R*T/(b - v) - a/((\\delta_1*b + v)*(\\delta_2*b + v))"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "zero.simplify()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - P \\left(- b + v\\right) \\left(\\delta_{1} b + v\\right) \\left(\\delta_{2} b + v\\right) + R T \\left(\\delta_{1} b + v\\right) \\left(\\delta_{2} b + v\\right) - a \\left(- b + v\\right)$"
+ ],
+ "text/plain": [
+ "-P*(-b + v)*(\\delta_1*b + v)*(\\delta_2*b + v) + R*T*(\\delta_1*b + v)*(\\delta_2*b + v) - a*(-b + v)"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "exp_2 = (v+d1*b)*(v+d2*b)# v**2 + (d1+d2)*b*v + d1*d2*b**2\n",
+ "exp_1 = v - b\n",
+ "\n",
+ "exp = R*T*exp_2 - a * exp_1 - P * exp_1 * exp_2\n",
+ "exp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "poly = sp.Poly(exp, gens=v)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - P$"
+ ],
+ "text/plain": [
+ "-P"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "poly.coeffs()[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - P \\delta_{1} b - P \\delta_{2} b + P b + R T$"
+ ],
+ "text/plain": [
+ "-P*\\delta_1*b - P*\\delta_2*b + P*b + R*T"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "poly.coeffs()[1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle - P \\delta_{1} \\delta_{2} b^{2} + P \\delta_{1} b^{2} + P \\delta_{2} b^{2} + R T \\delta_{1} b + R T \\delta_{2} b - a$"
+ ],
+ "text/plain": [
+ "-P*\\delta_1*\\delta_2*b**2 + P*\\delta_1*b**2 + P*\\delta_2*b**2 + R*T*\\delta_1*b + R*T*\\delta_2*b - a"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "poly.coeffs()[2]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/latex": [
+ "$\\displaystyle P \\delta_{1} \\delta_{2} b^{3} + R T \\delta_{1} \\delta_{2} b^{2} + a b$"
+ ],
+ "text/plain": [
+ "P*\\delta_1*\\delta_2*b**3 + R*T*\\delta_1*\\delta_2*b**2 + a*b"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\n",
+ "poly.coeffs()[3]\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "thermo",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/tools/tapenade_diff/ge_models/gen_ge_tapemodel.sh b/tools/tapenade_diff/ge_models/gen_ge_tapemodel.sh
index 150e54985..bf9885832 100644
--- a/tools/tapenade_diff/ge_models/gen_ge_tapemodel.sh
+++ b/tools/tapenade_diff/ge_models/gen_ge_tapemodel.sh
@@ -60,63 +60,9 @@ mv tapeout/${name}_d_d_d_b_b.f90 tapeout/${name}_diff.f90
sed -i "s/$modflag//g" tapeout/${name}_diff.f90
sed -i "s/TYPE(UNKNOWNTYPE).*//g" tapeout/${name}_diff.f90
sed -i "s/TYPE(NRTL) :: model/CLASS(NRTL) :: model/" tapeout/${name}_diff.f90
+
# sed -i "s/model%\(.*\) \(=\) \(.*\)/model%\1 => \3/g" tapeout/${name}_diff.f90
sed -i 's/REAL\*8/REAL(pr)/' tapeout/${name}_diff.f90
-# cp tapeout/${name}_diff.f90 ../example/taperobinson.f90
-# findent < tapeout/${name}_diff.f90 > tapeout/${name}_diff.f90
-
-# lfortran fmt -i tapeout/${infile}_diff.f90
-# =============================================================================
-
-
-# Tapenade 3.16 (develop) - 13 Sep 2023 12:36 - Java 17.0.9 Linux
-# @@ TAPENADE_HOME=/home/ruther/downs/tapenade_3.16/bin/..
-# Builds a differentiated program.
-# Usage: tapenade [options]* filenames
-# options:
-# -head, -root set the differentiation root procedure(s)
-# See FAQ for refined invocation syntax, e.g.
-# independent and dependent arguments, multiple heads...
-# -tangent, -d differentiate in forward/tangent mode (default)
-# -reverse, -b differentiate in reverse/adjoint mode
-# -vector, -multi turn on "vector" mode (i.e. multi-directional)
-# -specializeactivity Allow for several activity patterns per routine
-# -primal, -p turn off differentiation. Show pointer destinations
-# -output, -o put all generated code into a single
-# -splitoutputfiles split generated code, one file per top unit
-# -outputdirectory, -O put all generated files in (default: .)
-# -I add a new search path for include files
-# -tgtvarname set extension for tangent variables (default %d)
-# -tgtfuncname set extension for tangent procedures (default %_d)
-# -tgtmodulename set extension for tangent modules and types (default %_diff)
-# -adjvarname set extension for adjoint variables (default %b)
-# -adjfuncname set extension for adjoint procedures (default %_b)
-# -adjmodulename set extension for adjoint modules and types (default %_diff)
-# -modulename set extension for tangent&adjoint modules and types (default %_diff)
-# -inputlanguage language of input files (fortran, fortran90,
-# fortran95, or C)
-# -outputlanguage language of output files (fortran, fortran90,
-# fortran95, or C)
-# -ext incorporate external library description
-# -nolib don't load standard libraries descriptions
-# -i count bytes for an integer (default -i4)
-# -r count bytes for a real (default -r4)
-# -dr count bytes for a double real (default -dr8)
-# -p count bytes for a pointer (default -p8)
-# -fixinterface don't use activity to filter user-given (in)dependent vars
-# -noinclude inline include files
-# -debugTGT insert instructions for debugging tangent mode
-# -debugADJ insert instructions for debugging adjoint mode
-# -tracelevel set the level of detail of trace milestones
-# -msglevel set the level of detail of error messages
-# -msginfile insert error messages in output files
-# -dump write a dump
-# -html display results in a web browser
-# -nooptim turn off optimization (in {activity, difftypes,
-# diffarguments, stripprimalmodules, spareinit, splitdiff,
-# mergediff, saveonlyused, tbr, snapshot, diffliveness,
-# deadcontrol, recomputeintermediates,
-# everyoptim}
-# -version display Tapenade version information
-# Report bugs to .
+# remove all the external definition of functions. we use interfaces now
+sed -i '/EXTERNAL.*/d' tapeout/${name}_diff.f90
\ No newline at end of file
diff --git a/tools/tapenade_diff/ge_models/template.f90 b/tools/tapenade_diff/ge_models/template.f90
index 12e7a552c..bca93d67c 100644
--- a/tools/tapenade_diff/ge_models/template.f90
+++ b/tools/tapenade_diff/ge_models/template.f90
@@ -1,6 +1,7 @@
module tapenade_ge_model_template
use yaeos__constants, only: pr, R
use yaeos__tapenade_ge_api, only: GeModelTapenade
+ use yaeos__tapenade_interfaces
implicit none
diff --git a/tools/tapenade_diff/gen_tapemodel.sh b/tools/tapenade_diff/gen_tapemodel.sh
index b0c3d44be..a7c5e02cc 100644
--- a/tools/tapenade_diff/gen_tapemodel.sh
+++ b/tools/tapenade_diff/gen_tapemodel.sh
@@ -76,6 +76,9 @@ sed -i "s/REAL :: r//g" tapeout/${name}_diff.f90
# make the types into classes for polymorphism
sed -i 's/TYPE(\(.*\)),/class(\1),/' tapeout/${name}_diff.f90
+# remove all the external definition of functions. we use interfaces now
+sed -i '/EXTERNAL.*/d' tapeout/${name}_diff.f90
+
# Options to format document
# fprettify -i 3 --case 1 1 1 1
# findent < tapeout/${name}_diff.f90 > tapeout/${name}_diff.f90
diff --git a/tools/tapenade_diff/template.f90 b/tools/tapenade_diff/template.f90
index 780760b94..f93f5b5d3 100644
--- a/tools/tapenade_diff/template.f90
+++ b/tools/tapenade_diff/template.f90
@@ -1,5 +1,6 @@
module tapenade_model_template
use yaeos__tapenade_ar_api, only: ArModelTapenade
+ use yaeos__tapenade_interfaces
use yaeos, only: R !! Ideal gas constants used on yaeos
implicit none