Skip to content

Commit

Permalink
Release v0.3.0 (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
prehner authored Jan 27, 2025
1 parent 023a28b commit ca87248
Show file tree
Hide file tree
Showing 56 changed files with 2,334 additions and 13,049 deletions.
21 changes: 0 additions & 21 deletions .github/workflows/test.yml

This file was deleted.

8 changes: 2 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
**/target
Cargo.lock
.vscode
knitro.log
**/.ipynb_checkpoints
*.ipynb
target
Cargo.lock
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2025-01-27
### Changed
- Completely revamped the library, by switching from Knitro to open-source solvers and using automatic implicit differentiation for the calculation of Jacobians and Hessians.

## [0.2.1] - 2024-06-28
### Fixed
- Fix bug in OptimizationProblem::build_eos in https://github.com/feos-org/feos-campd/pull/3
Expand Down
40 changes: 14 additions & 26 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "feos-campd"
version = "0.2.1"
version = "0.3.0"
authors = ["Philipp Rehner <[email protected]>"]
edition = "2021"
readme = "README.md"
Expand All @@ -11,36 +11,24 @@ repository = "https://github.com/feos-org/feos-campd"
keywords = ["process_engineering", "molecular_design", "optimization"]
categories = ["science"]

[lib]
name = "feos_campd"
crate-type = ["rlib", "cdylib"]

[dependencies]
feos-core = { version = "0.6", optional = true }
feos = { version = "0.6", features = ["pcsaft", "gc_pcsaft"] }
ndarray = "0.15"
petgraph = "0.6"
num-dual = { version = "0.11", features = ["linalg"] }
quantity = { version = "0.10", features = ["num-dual"] }
nalgebra = "0.33"
feos-core = "0.8"
ndarray = "0.16"
feos-ad = "0.2"
num-traits = "0.2"
good_lp = { version = "1.11", default-features = false }
ipopt = "0.6"
ipopt-ad = "0.1"
serde = "1.0"
serde_json = "1.0"
itertools = "0.12"
knitro_rs = { version = "0.2", path = "knitro_rs", optional = true }
pyo3 = { version = "0.20", features = [
"extension-module",
"abi3",
"abi3-py37",
"indexmap",
], optional = true }
numpy = { version = "0.20", optional = true }
quantity = { version = "0.7", optional = true }
typenum = "1.17"
indexmap = "2.2"

[dev-dependencies]
approx = "0.5"
anyhow = "1.0"
itertools = "0.14"
good_lp = { version = "1.11", features = ["highs"], default-features = false }

[features]
default = []
knitro_12 = ["knitro_rs/knitro_12"]
knitro_13 = ["knitro_rs/knitro_13"]
python = ["pyo3", "numpy", "knitro_12", "quantity/python", "feos-core/python"]
highs = ["good_lp/highs"]
130 changes: 55 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,109 +6,89 @@
Computer-aided molecular and process design based on the [`FeOs`](https://github.com/feos-org/feos) framework.

The package provides infrastructure to perform a computer-aided molecular and process design. It consists of
- NLP/MIQCP solver bindings (Artelys Knitro)
- Implementation of a custom outer-approximation algorithms to solve the resulting MINLP
- Molecular representations (group counts (CoMT-CAMD) and molecule superstructures)
- Property models (PC-SAFT and (heterosegmented) gc-PC-SAFT)

and the surrounding framework that is used to run the optimization problems for arbitrary process models. The framework is implemented in Rust and can be accessed directly or through the Python interface.

Currently, solving CAMPD problems is only possible with an installation of Artelys Knitro 12. A switch to open-source implementations is heavily favored, but currently not immediately planned due to time constraints. Please contact the maintainers if you are interested in contributing.
The underlying NLP subproblems are solved using [IPOPT](https://coin-or.github.io/Ipopt/) via the [`ipopt-ad`](https://github.com/prehner/ipopt-ad) crate. For the solution of th MILP master problems, the solver is linked to the [`good_lp`](https://github.com/rust-or/good_lp) crate that offers a common interface to various open-source MILP solvers.

## Installation
### Rust
Just add the dependency to your `Cargo.toml`
```toml
feos-campd = "0.2"
```

### Python
If you have a Rust compiler installed, you can build the package directly from source using:
```
pip install git+https://github.com/feos-org/feos-campd
feos-campd = "0.3"
```

## Usage
The following sections demonstrates the usage of the framework in Python. The API in Rust and Python is kept as consistent as possible within the boundaries of the languages. Therefore, the basic steps are identical for a design implemented in Rust, for the API details, check out the [documentation](https://docs.rs/feos-campd).
The following sections demonstrates the usage of the framework, for the API details, check out the [documentation](https://docs.rs/feos-campd).

### Molecular representation
```python
# define the molecular representation using a molecule superstructure
molecule = SuperMolecule.alkane(size)
# or a combination of superstructures
molecule = SuperMolecule.non_associating(size)

# or provide a list of molecules to choose from
molecule = CoMTCAMD.from_molecules(list_of_identifiers)
molecule = CoMTCAMD.from_json_molecules(list_of_identifiers)

# or provide an input file with group and structure definitions for CoMT-CAMD
molecule = CoMTCAMD.from_json(list_of_identifiers)
```rust
// define the molecular representation using a molecule superstructure
let molecule = SuperMolecule::alkane(min_size, size);
// or a combination of superstructures
let molecule = SuperMolecule::non_associating(min_size, size);
// or use group and structure definitions for CoMT-CAMD
// (currently not further customizable)
let molecule = CoMTCAMD;
```
### Property model
```python
# The available property models are compatible with the parameter files in FeOs
property_model = GcPcSaftPropertyModel.from_json([molecule], "sauer2014_hetero.json", "joback1987.json")
property_model = PcSaftPropertyModel.from_json_molecules("gross2001.json", "poling2000.json")
property_model = PcSaftPropertyModel.from_json_groups("sauer2014_homo.json", "joback1987.json")
```rust
// The property model for heterosegmented gc-PC-SAFT is not customizable. It does not include association.
let property_model = GcPcSaftPropertyModel;
// For homosegmented PC-SAFT, the group parameters can be passes as arguments
// and it is available as the full model
let property_model = PcSaftPropertyModel::full("rehner2023_homo.json", Some("rehner2023_homo_binary.json"));
// or non-associating (ignoring all associating groups)
let property_model = PcSaftPropertyModel::non_associating("rehner2023_homo.json", Some("rehner2023_homo_binary.json"));
```
### Process model
```python
#To implement a process model in Python, define a class with the following methods:
class ORC:
# For each process variable: the lower bound, the upper bound, and the initial value
def variables(self):
return [[lb_0, ub_0, init_0], [lb_1, ub_1, init_1], ...]

# The number of equality constraints (h(x) = 0)
def equality_constraints(self):
return ...

# The number of inequality constraints (g(x) >= 0)
def inequality_constraints(self):
return ...

# For given equation of state and process variables x, return the target, and the values of
# equality and inequality constraints
def solve(self, eos, x):
# eos - the equation of state object as used in FeOs, e.g.,
state = State(eos, temperature=300*KELVIN, pressure=BAR)

# x - the list of process degrees of freedom, e.g.,
T_in, p_des, ... = x

# The function is called with regular Python data types (floats), so the implementation
# of the process model can be as flexible as desired and involve external function calls
```rust
//To define a process model in Rust, implement the `ProcessModel` trait for your struct.
impl<E: TotalHelmholtzEnergy<N: ...>> ProcessModel<E, N_X: ..., N: ...> for YourModel {
fn variables(&self) -> [ContinuousVariable; N_X] {
[
ContinuousVariable::new(..., ..., ...),
...
]
}

fn constraints(&self) -> Vec<GeneralConstraint> {
vec![
GeneralConstraint::Inequality(..., ...),
GeneralConstraint::Equality(...),
...
]
}

fn evaluate<D: DualNum<f64> + Copy>(
&self,
eos: &HelmholtzEnergyWrapper<E, D, N>,
chemical_records: [&ChemicalRecord<D>; N],
x: [D; 3],
) -> EosResult<(D, Vec<D>)> {
...

return target, equality_constraints, inequality_constraints

}
}
```
### Optimization problem
```python
# combine molecular representation, property model, and process model in an optimization problem
# for a pure component
problem = OptimizationProblem.pure(molecule, property_model, process)

# or a binary mixture
problem = OptimizationProblem.pure([molecule1, molecule2], property_model, process)
```rust
// combine molecular representation, property model, and process model in an optimization problem
let campd = IntegratedDesign::new(molecule, property_model, process);

# use either of these algorithms
# (The boolean indicates whether the algorithm should update the lower bound of the outer approximation
# True can lead to local optima in non-convex problems)
algorithm = OuterApproximationAlgorithm.DuranGrossmann(True)
algorithm = OuterApproximationAlgorithm.DuranGrossmann(False)
algorithm = OuterApproximationAlgorithm.FletcherLeyffer
// and pass it to the outer approximation solver
let solver = OuterApproximation::new(&campd);

# to determine a ranking of the optimal molecules
problem.outer_approximation_ranking(y0, algorithm, num_molecules, "options_NLP.opt", "options_MILP.opt")
// to determine a ranking of the optimal molecules for a pur component
solver.solve_ranking(y0, highs, runs, options);
// where highs can be replaced with any of the other MILP solvers provided by the good_lp crate.
```

Molecular representations and property models can be combined according to:
||PC-SAFT|gc-PC-SAFT|
|-|-|-|
| CoMTCAMD | yes | no |
| SuperMolecule | yes | yes |
| `CoMTCAMD` | yes | no |
| `SuperMolecule` | yes | yes |

### Cite us
If you find FeOs-torch useful for your own research, consider citing our [publication](https://pubs.rsc.org/en/content/articlelanding/2023/me/d2me00230b) from which this library resulted.
Expand Down
22 changes: 0 additions & 22 deletions knitro_rs/Cargo.toml

This file was deleted.

6 changes: 0 additions & 6 deletions knitro_rs/README.md

This file was deleted.

54 changes: 0 additions & 54 deletions knitro_rs/build.rs

This file was deleted.

1 change: 0 additions & 1 deletion knitro_rs/knitro12.h

This file was deleted.

1 change: 0 additions & 1 deletion knitro_rs/knitro13.h

This file was deleted.

1 change: 0 additions & 1 deletion knitro_rs/license-apache

This file was deleted.

1 change: 0 additions & 1 deletion knitro_rs/license-mit

This file was deleted.

Loading

0 comments on commit ca87248

Please sign in to comment.