Newer
Older
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Multi-fluid EOS\n",
"\n",
"Peering into the innards of teqp"
]
},
{
"cell_type": "code",
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:06.606089Z",
"iopub.status.busy": "2022-07-06T18:40:06.605465Z",
"iopub.status.idle": "2022-07-06T18:40:07.147629Z",
"shell.execute_reply": "2022-07-06T18:40:07.146669Z"
}
},
"source": [
"import timeit, json\n",
"import pandas\n",
"import numpy as np\n",
"import teqp\n",
"teqp.__version__"
]
},
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ancillary Equations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ancillary equations are provided along with multiparameter equations of state. The give a good *approximation* to the phase equilibrium densities. There are routines in teqp to use the ancillary equations provided with the EOS. First a class containing the ancillary equations is obtained, then methods on that class are called"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model = teqp.build_multifluid_model([\"Methane\"], teqp.get_datapath())\n",
"anc = model.build_ancillaries()\n",
"T = 100.0 # [K]\n",
"rhoL, rhoV = anc.rhoL(T), anc.rhoV(T)\n",
"print('Densities are:', rhoL, rhoV, 'mol/m^3')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But those densities do not correspond to the *true* phase equilibrium solution, so we need to polish the solution:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Niter = 10\n",
"rhoLtrue, rhoVtrue = model.pure_VLE_T(T, rhoL, rhoV, Niter)\n",
"print('VLE densities are:', rhoLtrue, rhoVtrue, 'mol/m^3')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And looking the densities, they are slightly different after the phase equilibrium calculation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pure fluid loading"
]
},
{
"cell_type": "code",
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:07.163785Z",
"iopub.status.busy": "2022-07-06T18:40:07.163785Z",
"iopub.status.idle": "2022-07-06T18:40:17.280030Z",
"shell.execute_reply": "2022-07-06T18:40:17.278333Z"
}
},
"source": [
"# By default teqp looks for fluids relative to the set of fluids in ROOT/dev/fluids\n",
"# The name (case-sensitive) should match the .json file, without the json extension.\n",
"%timeit model = teqp.build_multifluid_model([\"Methane\"], teqp.get_datapath())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:17.286031Z",
"iopub.status.busy": "2022-07-06T18:40:17.285350Z",
"iopub.status.idle": "2022-07-06T18:40:27.300085Z",
"shell.execute_reply": "2022-07-06T18:40:27.299050Z"
}
},
"source": [
"# And if you provide valid aliases, alias lookup will be used to resolve the name\n",
"# But beware, this is rather a lot slower than the above because all fluid files need to be read\n",
"# in to build the alias map\n",
"%timeit model = teqp.build_multifluid_model([\"n-C1H4\"], teqp.get_datapath())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So, how to make it faster? Only do it once and cache"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:27.307115Z",
"iopub.status.busy": "2022-07-06T18:40:27.307115Z",
"iopub.status.idle": "2022-07-06T18:40:34.876155Z",
"shell.execute_reply": "2022-07-06T18:40:34.875146Z"
}
},
"source": [
"# Here is the set of possible aliases to absolute paths of files\n",
"# Building this map takes a little while (somewhat faster in C++) due to all the file reads\n",
"# If you know your files will not change, good idea to build this alias map yourself.\n",
"%timeit aliasmap = teqp.build_alias_map(teqp.get_datapath())\n",
"aliasmap = teqp.build_alias_map(teqp.get_datapath())\n",
"list(aliasmap.keys())[0:10] # the first 10 aliases in the dict"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:34.879157Z",
"iopub.status.busy": "2022-07-06T18:40:34.879157Z",
"iopub.status.idle": "2022-07-06T18:40:42.930387Z",
"shell.execute_reply": "2022-07-06T18:40:42.930079Z"
}
},
"source": [
"# Then load the absolute paths from the alias map, \n",
"# which will guarantee that you hit exactly what you were looking for,\n",
"# resolving aliases as needed\n",
"identifiers = [aliasmap[n] for n in [\"n-C1H4\"]]\n",
"%timeit model = teqp.build_multifluid_model(identifiers, teqp.get_datapath())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At some point soon teqp will support in-memory loading of JSON data for the pure components, without requiring reads from the operating system"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:42.932720Z",
"iopub.status.busy": "2022-07-06T18:40:42.932720Z",
"iopub.status.idle": "2022-07-06T18:40:42.946939Z",
"shell.execute_reply": "2022-07-06T18:40:42.945927Z"
}
},
"outputs": [],
"source": [
"# And you can also load the JSON that teqp is loading for the pure fluids\n",
"pureJSON = teqp.collect_component_json(['Neon','Hydrogen'], teqp.get_datapath())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mixture model loading"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:42.949975Z",
"iopub.status.busy": "2022-07-06T18:40:42.948972Z",
"iopub.status.idle": "2022-07-06T18:40:42.962308Z",
"shell.execute_reply": "2022-07-06T18:40:42.961547Z"
}
},
"outputs": [],
"source": [
"# Load the default JSON for the binary interaction parameters\n",
"BIP = json.load(open(teqp.get_datapath()+'/dev/mixtures/mixture_binary_pairs.json'))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:42.965595Z",
"iopub.status.busy": "2022-07-06T18:40:42.964944Z",
"iopub.status.idle": "2022-07-06T18:40:42.978409Z",
"shell.execute_reply": "2022-07-06T18:40:42.977232Z"
}
},
"source": [
"# You can obtain interaction parameters either by pairs of names, where name is the name that teqp uses, the [\"INFO\"][\"NAME\"] field\n",
"params, swap_needed = teqp.get_BIPdep(BIP, ['Methane','Ethane'])\n",
"params"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:42.981288Z",
"iopub.status.busy": "2022-07-06T18:40:42.981288Z",
"iopub.status.idle": "2022-07-06T18:40:42.993879Z",
"shell.execute_reply": "2022-07-06T18:40:42.993281Z"
}
},
"source": [
"# Or also by CAS#\n",
"params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','74-84-0'])\n",
"params"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {
"iopub.execute_input": "2022-07-06T18:40:42.996338Z",
"iopub.status.busy": "2022-07-06T18:40:42.996338Z",
"iopub.status.idle": "2022-07-06T18:40:43.423368Z",
"shell.execute_reply": "2022-07-06T18:40:43.422895Z"
Ian Bell
committed
},
"tags": [
"raises-exception"
]
"source": [
"# But mixing is not allowed\n",
"params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','Ethane'])\n",
"params"
]
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Estimation of interaction parameters\n",
"\n",
"Estimation of interaction parameters can be used when no mixture model is present. The ``flags`` keyword argument allows the user to control how estimation is applied. The ``flags`` keyword argument should be a dictionary, with keys of ``\"estimate\"`` to provide the desired estimation scheme as-needed. For now, the only allowed estimation scheme is ``Lorentz-Berthelot``. \n",
"\n",
"If it is desired to force the estimation, the ``\"force-estimate\"`` to force the use of the provided esimation scheme for all binaries, even when one is available. The value associated with ``\"force-estimate\"`` is ignored."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','74-84-0'], flags={'force-estimate':'yes', 'estimate': 'Lorentz-Berthelot'})\n",
"params"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# And without the force, the forcing is ignored\n",
"params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','74-84-0'], flags={'estimate': 'Lorentz-Berthelot'})\n",
"params"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# And the same flags can be passed to the multifluid model constructor\n",
"model = teqp.build_multifluid_model(\n",
" ['74-82-8','74-84-0'], \n",
" teqp.get_datapath(), \n",
" flags={'force-estimate':'yes', 'estimate': 'Lorentz-Berthelot'})"
]
"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",