openpnm 1.0.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- OpenPNM-1.1/MANIFEST.in +2 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__FickianDiffusion__.py +67 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__FourierConduction__.py +63 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__GenericAlgorithm__.py +235 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__GenericLinearTransport__.py +641 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolationForImbibition__.py +703 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolationTimed__.py +702 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolation__.py +156 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__OhmicConduction__.py +64 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__OrdinaryPercolation__.py +402 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__StokesFlow__.py +64 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__Tortuosity__.py +91 -0
- OpenPNM-1.1/OpenPNM/Algorithms/__init__.py +48 -0
- OpenPNM-1.1/OpenPNM/Base/__Controller__.py +480 -0
- OpenPNM-1.1/OpenPNM/Base/__Core__.py +1522 -0
- OpenPNM-1.1/OpenPNM/Base/__ModelsDict__.py +345 -0
- OpenPNM-1.1/OpenPNM/Base/__Tools__.py +72 -0
- OpenPNM-1.1/OpenPNM/Base/__init__.py +32 -0
- OpenPNM-1.1/OpenPNM/Geometry/__Boundary__.py +80 -0
- OpenPNM-1.1/OpenPNM/Geometry/__Cube_and_Cuboid__.py +64 -0
- OpenPNM-1.1/OpenPNM/Geometry/__GenericGeometry__.py +106 -0
- OpenPNM-1.1/OpenPNM/Geometry/__SGL10__.py +67 -0
- OpenPNM-1.1/OpenPNM/Geometry/__Stick_and_Ball__.py +68 -0
- OpenPNM-1.1/OpenPNM/Geometry/__TestGeometry__.py +51 -0
- OpenPNM-1.1/OpenPNM/Geometry/__Toray090__.py +68 -0
- OpenPNM-1.1/OpenPNM/Geometry/__Voronoi__.py +98 -0
- OpenPNM-1.1/OpenPNM/Geometry/__init__.py +47 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/__init__.py +33 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_area.py +27 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_centroid.py +35 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_diameter.py +127 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_misc.py +55 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_seed.py +212 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_surface_area.py +28 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_vertices.py +19 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/pore_volume.py +133 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_area.py +47 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_centroid.py +80 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_diameter.py +106 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_length.py +95 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_misc.py +42 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_normal.py +31 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_offset_vertices.py +191 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_perimeter.py +26 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_seed.py +12 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_shape_factor.py +37 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_surface_area.py +44 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_vector.py +27 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_vertices.py +19 -0
- OpenPNM-1.1/OpenPNM/Geometry/models/throat_volume.py +45 -0
- OpenPNM-1.1/OpenPNM/Network/__Cubic__.py +316 -0
- OpenPNM-1.1/OpenPNM/Network/__DelaunayCubic__.py +127 -0
- OpenPNM-1.1/OpenPNM/Network/__Delaunay__.py +600 -0
- OpenPNM-1.1/OpenPNM/Network/__GenericNetwork__.py +1184 -0
- OpenPNM-1.1/OpenPNM/Network/__MatFile__.py +331 -0
- OpenPNM-1.1/OpenPNM/Network/__TestNet__.py +109 -0
- OpenPNM-1.1/OpenPNM/Network/__init__.py +40 -0
- OpenPNM-1.1/OpenPNM/Network/models/__init__.py +12 -0
- OpenPNM-1.1/OpenPNM/Network/models/pore_topology.py +106 -0
- OpenPNM-1.1/OpenPNM/Phases/__Air__.py +63 -0
- OpenPNM-1.1/OpenPNM/Phases/__GenericPhase__.py +146 -0
- OpenPNM-1.1/OpenPNM/Phases/__Mercury__.py +71 -0
- OpenPNM-1.1/OpenPNM/Phases/__TestPhase__.py +46 -0
- OpenPNM-1.1/OpenPNM/Phases/__Water__.py +56 -0
- OpenPNM-1.1/OpenPNM/Phases/__init__.py +38 -0
- OpenPNM-1.1/OpenPNM/Phases/models/__init__.py +22 -0
- OpenPNM-1.1/OpenPNM/Phases/models/contact_angle.py +34 -0
- OpenPNM-1.1/OpenPNM/Phases/models/density.py +81 -0
- OpenPNM-1.1/OpenPNM/Phases/models/diffusivity.py +95 -0
- OpenPNM-1.1/OpenPNM/Phases/models/electrical_conductivity.py +10 -0
- OpenPNM-1.1/OpenPNM/Phases/models/misc.py +125 -0
- OpenPNM-1.1/OpenPNM/Phases/models/molar_density.py +69 -0
- OpenPNM-1.1/OpenPNM/Phases/models/molar_mass.py +31 -0
- OpenPNM-1.1/OpenPNM/Phases/models/surface_tension.py +104 -0
- OpenPNM-1.1/OpenPNM/Phases/models/thermal_conductivity.py +98 -0
- OpenPNM-1.1/OpenPNM/Phases/models/vapor_pressure.py +69 -0
- OpenPNM-1.1/OpenPNM/Phases/models/viscosity.py +103 -0
- OpenPNM-1.1/OpenPNM/Physics/__GenericPhysics__.py +111 -0
- OpenPNM-1.1/OpenPNM/Physics/__Standard__.py +51 -0
- OpenPNM-1.1/OpenPNM/Physics/__TestPhysics__.py +50 -0
- OpenPNM-1.1/OpenPNM/Physics/__init__.py +30 -0
- OpenPNM-1.1/OpenPNM/Physics/models/__init__.py +18 -0
- OpenPNM-1.1/OpenPNM/Physics/models/capillary_pressure.py +122 -0
- OpenPNM-1.1/OpenPNM/Physics/models/diffusive_conductance.py +82 -0
- OpenPNM-1.1/OpenPNM/Physics/models/electrical_conductance.py +59 -0
- OpenPNM-1.1/OpenPNM/Physics/models/generic_source_term.py +564 -0
- OpenPNM-1.1/OpenPNM/Physics/models/hydraulic_conductance.py +76 -0
- OpenPNM-1.1/OpenPNM/Physics/models/multiphase.py +133 -0
- OpenPNM-1.1/OpenPNM/Physics/models/thermal_conductance.py +67 -0
- OpenPNM-1.1/OpenPNM/Postprocessing/Graphics.py +251 -0
- OpenPNM-1.1/OpenPNM/Postprocessing/Plots.py +369 -0
- OpenPNM-1.1/OpenPNM/Postprocessing/__init__.py +10 -0
- OpenPNM-1.1/OpenPNM/Utilities/IO.py +277 -0
- OpenPNM-1.1/OpenPNM/Utilities/Shortcuts.py +17 -0
- OpenPNM-1.1/OpenPNM/Utilities/__init__.py +16 -0
- OpenPNM-1.1/OpenPNM/Utilities/misc.py +226 -0
- OpenPNM-1.1/OpenPNM/Utilities/transformations.py +1923 -0
- OpenPNM-1.1/OpenPNM/Utilities/vertexops.py +824 -0
- OpenPNM-1.1/OpenPNM/__init__.py +56 -0
- OpenPNM-1.1/OpenPNM.egg-info/PKG-INFO +11 -0
- OpenPNM-1.1/OpenPNM.egg-info/SOURCES.txt +107 -0
- OpenPNM-1.1/OpenPNM.egg-info/dependency_links.txt +1 -0
- OpenPNM-1.1/OpenPNM.egg-info/requires.txt +1 -0
- OpenPNM-1.1/OpenPNM.egg-info/top_level.txt +1 -0
- OpenPNM-1.1/PKG-INFO +11 -0
- OpenPNM-1.1/README.txt +88 -0
- OpenPNM-1.1/setup.cfg +7 -0
- OpenPNM-1.1/setup.py +39 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
===============================================================================
|
|
4
|
+
GenericGeometry -- Base class to manage pore scale geometry
|
|
5
|
+
===============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import scipy as sp
|
|
10
|
+
from OpenPNM.Base import Core
|
|
11
|
+
from OpenPNM.Base import logging
|
|
12
|
+
from OpenPNM.Network import GenericNetwork
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
import OpenPNM.Geometry.models
|
|
15
|
+
|
|
16
|
+
class GenericGeometry(Core):
|
|
17
|
+
r"""
|
|
18
|
+
GenericGeometry - Base class to construct a Geometry object
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
network : OpenPNM Network Object
|
|
23
|
+
|
|
24
|
+
pores and/or throats : array_like
|
|
25
|
+
The list of pores and throats where this physics applies. If either are
|
|
26
|
+
left blank this will apply the physics nowhere. The locations can be
|
|
27
|
+
change after instantiation using ``set_locations()``.
|
|
28
|
+
|
|
29
|
+
name : string
|
|
30
|
+
A unique name to apply to the object. This name will also be used as a
|
|
31
|
+
label to identify where this this geometry applies.
|
|
32
|
+
|
|
33
|
+
Examples
|
|
34
|
+
--------
|
|
35
|
+
>>> pn = OpenPNM.Network.TestNet()
|
|
36
|
+
>>> Ps = pn.pores() # Get all pores
|
|
37
|
+
>>> Ts = pn.throats() # Get all throats
|
|
38
|
+
>>> geom = OpenPNM.Geometry.GenericGeometry(network=pn,pores=Ps,throats=Ts)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self,network=None,pores=[],throats=[],seed=None,**kwargs):
|
|
42
|
+
r"""
|
|
43
|
+
Initialize
|
|
44
|
+
"""
|
|
45
|
+
super(GenericGeometry,self).__init__(**kwargs)
|
|
46
|
+
logger.name = self.name
|
|
47
|
+
|
|
48
|
+
if network is None:
|
|
49
|
+
self._net = GenericNetwork()
|
|
50
|
+
else:
|
|
51
|
+
self._net = network # Attach network to self
|
|
52
|
+
self._net._geometries.append(self) # Register self with network.geometries
|
|
53
|
+
|
|
54
|
+
#Initialize a label dictionary in the associated network
|
|
55
|
+
self._net['pore.'+self.name] = False
|
|
56
|
+
self._net['throat.'+self.name] = False
|
|
57
|
+
self.set_locations(pores=pores,throats=throats)
|
|
58
|
+
self._seed = seed
|
|
59
|
+
|
|
60
|
+
def __getitem__(self,key):
|
|
61
|
+
element = key.split('.')[0]
|
|
62
|
+
# Convert self.name into 'all'
|
|
63
|
+
if key.split('.')[-1] == self.name:
|
|
64
|
+
key = element + '.all'
|
|
65
|
+
|
|
66
|
+
if key in self.keys(): # Look for data on self...
|
|
67
|
+
return super(GenericGeometry,self).__getitem__(key)
|
|
68
|
+
if key == 'throat.conns': # Handle specifically
|
|
69
|
+
[P1,P2] = self._net['throat.conns'][self._net[element+'.'+self.name]].T
|
|
70
|
+
Pmap = sp.zeros((self._net.Np,),dtype=int)-1
|
|
71
|
+
Pmap[self._net.pores(self.name)] = self.Ps
|
|
72
|
+
conns = sp.array([Pmap[P1],Pmap[P2]]).T
|
|
73
|
+
# Replace -1's with nans
|
|
74
|
+
if sp.any(conns==-1):
|
|
75
|
+
conns = sp.array(conns,dtype=object)
|
|
76
|
+
conns[sp.where(conns==-1)] = sp.nan
|
|
77
|
+
return conns
|
|
78
|
+
else: # ...Then check Network
|
|
79
|
+
return self._net[key][self._net[element+'.'+self.name]]
|
|
80
|
+
|
|
81
|
+
def set_locations(self,pores=[],throats=[],mode='add'):
|
|
82
|
+
r'''
|
|
83
|
+
Set the pore and throat locations of the Geometry object
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
pores and throats : array_like
|
|
88
|
+
The list of pores and/or throats in the Network where the object
|
|
89
|
+
should be applied
|
|
90
|
+
mode : string
|
|
91
|
+
Indicates whether list of pores or throats is to be added or removed
|
|
92
|
+
from the object. Options are 'add' (default) or 'remove'.
|
|
93
|
+
|
|
94
|
+
'''
|
|
95
|
+
if len(pores) > 0:
|
|
96
|
+
pores = sp.array(pores,ndmin=1)
|
|
97
|
+
self._set_locations(element='pore',locations=pores,mode=mode)
|
|
98
|
+
if len(throats) > 0:
|
|
99
|
+
throats = sp.array(throats,ndmin=1)
|
|
100
|
+
self._set_locations(element='throat',locations=throats,mode=mode)
|
|
101
|
+
|
|
102
|
+
if __name__ == '__main__':
|
|
103
|
+
#Run doc tests
|
|
104
|
+
import doctest
|
|
105
|
+
doctest.testmod(verbose=True)
|
|
106
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
===============================================================================
|
|
4
|
+
SGL10 -- A geometry model for SGL10 type Gas Diffusion Layers
|
|
5
|
+
===============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from OpenPNM.Geometry import models as gm
|
|
10
|
+
from OpenPNM.Geometry import GenericGeometry
|
|
11
|
+
|
|
12
|
+
class SGL10(GenericGeometry):
|
|
13
|
+
r"""
|
|
14
|
+
SGL10 subclass of GenericGeometry.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, **kwargs):
|
|
19
|
+
r"""
|
|
20
|
+
Initialize
|
|
21
|
+
"""
|
|
22
|
+
super(SGL10,self).__init__(**kwargs)
|
|
23
|
+
self._generate()
|
|
24
|
+
|
|
25
|
+
def _generate(self):
|
|
26
|
+
r'''
|
|
27
|
+
'''
|
|
28
|
+
self.models.add(propname='pore.seed',
|
|
29
|
+
model=gm.pore_misc.random,
|
|
30
|
+
num_range=[0,0.8834],
|
|
31
|
+
seed=self._seed,
|
|
32
|
+
regen_mode='constant')
|
|
33
|
+
self.models.add(propname='throat.seed',
|
|
34
|
+
model=gm.throat_misc.neighbor,
|
|
35
|
+
pore_prop='pore.seed',
|
|
36
|
+
mode='min')
|
|
37
|
+
self.models.add(propname='pore.diameter',
|
|
38
|
+
model=gm.pore_diameter.sphere,
|
|
39
|
+
psd_name='weibull_min',
|
|
40
|
+
psd_shape=3.07,
|
|
41
|
+
psd_loc=1.97e-6,
|
|
42
|
+
psd_scale=1.6e-5,
|
|
43
|
+
psd_offset=18e-6)
|
|
44
|
+
self.models.add(propname='pore.area',
|
|
45
|
+
model=gm.pore_area.spherical)
|
|
46
|
+
self.models.add(propname='pore.volume',
|
|
47
|
+
model=gm.pore_volume.sphere)
|
|
48
|
+
self.models.add(propname='throat.diameter',
|
|
49
|
+
model=gm.throat_diameter.cylinder,
|
|
50
|
+
tsd_name='weibull_min',
|
|
51
|
+
tsd_shape=3.07,
|
|
52
|
+
tsd_loc=1.97e-6,
|
|
53
|
+
tsd_scale=1.6e-5,
|
|
54
|
+
tsd_offset=18e-6)
|
|
55
|
+
self.models.add(propname='throat.length',
|
|
56
|
+
model=gm.throat_length.straight)
|
|
57
|
+
self.models.add(propname='throat.volume',
|
|
58
|
+
model=gm.throat_volume.cylinder)
|
|
59
|
+
self.models.add(propname='throat.area',
|
|
60
|
+
model=gm.throat_area.cylinder)
|
|
61
|
+
self.models.add(propname='throat.surface_area',
|
|
62
|
+
model=gm.throat_surface_area.cylinder)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == '__main__':
|
|
66
|
+
pn = OpenPNM.Network.TestNet()
|
|
67
|
+
pass
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
===============================================================================
|
|
4
|
+
Stick_and_Ball -- A standard 'stick & ball' geometrical model
|
|
5
|
+
===============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from OpenPNM.Geometry import models as gm
|
|
10
|
+
from OpenPNM.Geometry import GenericGeometry
|
|
11
|
+
|
|
12
|
+
class Stick_and_Ball(GenericGeometry):
|
|
13
|
+
r"""
|
|
14
|
+
Stick and Ball subclass of GenericGeometry. This subclass is meant as a
|
|
15
|
+
basic default geometry to get started quickly.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
name : string
|
|
20
|
+
The name of the object, which is also used as the label where this
|
|
21
|
+
geometry is defined.
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, **kwargs):
|
|
26
|
+
r"""
|
|
27
|
+
Initialize
|
|
28
|
+
"""
|
|
29
|
+
super(Stick_and_Ball,self).__init__(**kwargs)
|
|
30
|
+
self._generate()
|
|
31
|
+
|
|
32
|
+
def _generate(self):
|
|
33
|
+
self.models.add(propname='pore.seed',
|
|
34
|
+
model=gm.pore_misc.random,
|
|
35
|
+
regen_mode='constant',
|
|
36
|
+
seed=self._seed)
|
|
37
|
+
self.models.add(propname='throat.seed',
|
|
38
|
+
model=gm.throat_misc.neighbor,
|
|
39
|
+
mode='min')
|
|
40
|
+
self.models.add(propname='pore.diameter',
|
|
41
|
+
model=gm.pore_diameter.sphere,
|
|
42
|
+
psd_name='weibull_min',
|
|
43
|
+
psd_shape=2.5,
|
|
44
|
+
psd_loc=0,
|
|
45
|
+
psd_scale=0.5)
|
|
46
|
+
self.models.add(propname='pore.area',
|
|
47
|
+
model=gm.pore_area.spherical)
|
|
48
|
+
self.models.add(propname='pore.volume',
|
|
49
|
+
model=gm.pore_volume.sphere)
|
|
50
|
+
self.models.add(propname='throat.diameter',
|
|
51
|
+
model=gm.throat_diameter.cylinder,
|
|
52
|
+
tsd_name='weibull_min',
|
|
53
|
+
tsd_shape=2.5,
|
|
54
|
+
tsd_loc=0,
|
|
55
|
+
tsd_scale=0.5)
|
|
56
|
+
self.models.add(propname='throat.length',
|
|
57
|
+
model=gm.throat_length.straight)
|
|
58
|
+
self.models.add(propname='throat.volume',
|
|
59
|
+
model=gm.throat_volume.cylinder)
|
|
60
|
+
self.models.add(propname='throat.area',
|
|
61
|
+
model=gm.throat_area.cylinder)
|
|
62
|
+
self.models.add(propname='throat.surface_area',
|
|
63
|
+
model=gm.throat_surface_area.cylinder)
|
|
64
|
+
|
|
65
|
+
if __name__ == '__main__':
|
|
66
|
+
#Run doc tests
|
|
67
|
+
import doctest
|
|
68
|
+
doctest.testmod(verbose=True)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
===============================================================================
|
|
4
|
+
TestGeometry -- A Geomery for Toray TGPH090 gas diffusion layers
|
|
5
|
+
===============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import scipy as _sp
|
|
10
|
+
from OpenPNM.Geometry import models as gm
|
|
11
|
+
from OpenPNM.Geometry import GenericGeometry
|
|
12
|
+
|
|
13
|
+
class TestGeometry(GenericGeometry):
|
|
14
|
+
r"""
|
|
15
|
+
Toray090 subclass of GenericGeometry
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, **kwargs):
|
|
20
|
+
r"""
|
|
21
|
+
Initialize
|
|
22
|
+
"""
|
|
23
|
+
super(TestGeometry,self).__init__(**kwargs)
|
|
24
|
+
self._generate()
|
|
25
|
+
|
|
26
|
+
def _generate(self):
|
|
27
|
+
r'''
|
|
28
|
+
'''
|
|
29
|
+
self.models.add(propname='pore.seed',
|
|
30
|
+
model=gm.pore_misc.random,
|
|
31
|
+
regen_mode='constant',
|
|
32
|
+
seed=1)
|
|
33
|
+
self.models.add(propname='throat.seed',
|
|
34
|
+
model=gm.throat_misc.neighbor,
|
|
35
|
+
pore_prop='pore.seed',
|
|
36
|
+
mode='min')
|
|
37
|
+
self['pore.diameter'] = self['pore.seed']
|
|
38
|
+
self['throat.diameter'] = self['throat.seed']
|
|
39
|
+
self['pore.volume']=_sp.pi/6*self['pore.diameter']**3
|
|
40
|
+
self['pore.area']=_sp.constants.pi/4*self['pore.diameter']**2
|
|
41
|
+
|
|
42
|
+
self.models.add(propname='throat.length',
|
|
43
|
+
model=gm.throat_length.straight)
|
|
44
|
+
self['throat.volume'] = _sp.pi/4*self['throat.length']*self['throat.diameter']**2
|
|
45
|
+
self['throat.area'] = _sp.constants.pi/4*(self['throat.diameter'])**2
|
|
46
|
+
self['throat.surface_area'] = _sp.constants.pi/(self['throat.diameter'])*self['throat.length']
|
|
47
|
+
|
|
48
|
+
if __name__ == '__main__':
|
|
49
|
+
import OpenPNM
|
|
50
|
+
pn = OpenPNM.Network.TestNet()
|
|
51
|
+
pass
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
module __Toray090__: Subclass of GenericGeometry for a standard Toray TGPH090
|
|
3
|
+
gas diffusion layer.s
|
|
4
|
+
===============================================================================
|
|
5
|
+
|
|
6
|
+
.. warning:: The classes of this module should be loaded through the 'Geometry.__init__.py' file.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from OpenPNM.Geometry import models as gm
|
|
11
|
+
from OpenPNM.Geometry import GenericGeometry
|
|
12
|
+
|
|
13
|
+
class Toray090(GenericGeometry):
|
|
14
|
+
r"""
|
|
15
|
+
Toray090 subclass of GenericGeometry
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, **kwargs):
|
|
20
|
+
r"""
|
|
21
|
+
Initialize
|
|
22
|
+
"""
|
|
23
|
+
super(Toray090,self).__init__(**kwargs)
|
|
24
|
+
self._generate()
|
|
25
|
+
|
|
26
|
+
def _generate(self):
|
|
27
|
+
r'''
|
|
28
|
+
'''
|
|
29
|
+
self.models.add(propname='pore.seed',
|
|
30
|
+
model=gm.pore_misc.random,
|
|
31
|
+
num_range=[0,0.95],
|
|
32
|
+
seed=self._seed,
|
|
33
|
+
regen_mode='constant')
|
|
34
|
+
self.models.add(propname='throat.seed',
|
|
35
|
+
model=gm.throat_misc.neighbor,
|
|
36
|
+
pore_prop='pore.seed',
|
|
37
|
+
mode='min')
|
|
38
|
+
self.models.add(propname='pore.diameter',
|
|
39
|
+
model=gm.pore_diameter.sphere,
|
|
40
|
+
psd_name='weibull_min',
|
|
41
|
+
psd_shape=2.77,
|
|
42
|
+
psd_loc=6.9e-7,
|
|
43
|
+
psd_scale=9.8e-6,
|
|
44
|
+
psd_offset=10e-6)
|
|
45
|
+
self.models.add(propname='pore.area',
|
|
46
|
+
model=gm.pore_area.spherical)
|
|
47
|
+
self.models.add(propname='pore.volume',
|
|
48
|
+
model=gm.pore_volume.sphere)
|
|
49
|
+
self.models.add(propname='throat.diameter',
|
|
50
|
+
model=gm.throat_diameter.cylinder,
|
|
51
|
+
tsd_name='weibull_min',
|
|
52
|
+
tsd_shape=2.77,
|
|
53
|
+
tsd_loc=6.9e-7,
|
|
54
|
+
tsd_scale=9.8e-6,
|
|
55
|
+
tsd_offset=10e-6)
|
|
56
|
+
self.models.add(propname='throat.length',
|
|
57
|
+
model=gm.throat_length.straight)
|
|
58
|
+
self.models.add(propname='throat.volume',
|
|
59
|
+
model=gm.throat_volume.cylinder)
|
|
60
|
+
self.models.add(propname='throat.area',
|
|
61
|
+
model=gm.throat_area.cylinder)
|
|
62
|
+
self.models.add(propname='throat.surface_area',
|
|
63
|
+
model=gm.throat_surface_area.cylinder)
|
|
64
|
+
|
|
65
|
+
if __name__ == '__main__':
|
|
66
|
+
import OpenPNM
|
|
67
|
+
pn = OpenPNM.Network.TestNet()
|
|
68
|
+
pass
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
===============================================================================
|
|
4
|
+
Voronoi --Subclass of GenericGeometry for a standard Geometry created from a
|
|
5
|
+
Voronoi Diagram Used with Delaunay Network but could work for others (not tested)
|
|
6
|
+
===============================================================================
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import scipy as sp
|
|
12
|
+
from OpenPNM.Geometry import models as gm
|
|
13
|
+
from OpenPNM.Geometry import GenericGeometry
|
|
14
|
+
|
|
15
|
+
class Voronoi(GenericGeometry):
|
|
16
|
+
r"""
|
|
17
|
+
Voronoi subclass of GenericGeometry.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, fibre_rad = 3e-06, load_gen='gen', **kwargs):
|
|
26
|
+
r"""
|
|
27
|
+
Initialize
|
|
28
|
+
"""
|
|
29
|
+
if int(sp.__version__.split('.')[1]) < 13:
|
|
30
|
+
raise Exception('The installed version of Scipy is too old, Voronoi cannot run')
|
|
31
|
+
super(Voronoi,self).__init__(**kwargs)
|
|
32
|
+
if load_gen == 'gen':
|
|
33
|
+
self._generate(fibre_rad)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _generate(self,fibre_rad):
|
|
37
|
+
r'''
|
|
38
|
+
'''
|
|
39
|
+
|
|
40
|
+
self.models.add(propname='pore.vertices',
|
|
41
|
+
model=gm.pore_vertices.voronoi)
|
|
42
|
+
self.models.add(propname='throat.vertices',
|
|
43
|
+
model=gm.throat_vertices.voronoi)
|
|
44
|
+
self.models.add(propname='throat.normal',
|
|
45
|
+
model=gm.throat_normal.voronoi)
|
|
46
|
+
self.models.add(propname='throat.offset_vertices',
|
|
47
|
+
model=gm.throat_offset_vertices.distance_transform,
|
|
48
|
+
offset=fibre_rad,
|
|
49
|
+
set_dependent = True)
|
|
50
|
+
"Remove throats that are fully occluded and pores with no connections"
|
|
51
|
+
self._net.trim_occluded_throats()
|
|
52
|
+
|
|
53
|
+
self.models.add(propname='pore.seed',
|
|
54
|
+
model=gm.pore_misc.random,
|
|
55
|
+
seed=self._seed)
|
|
56
|
+
self.models.add(propname='throat.seed',
|
|
57
|
+
model=gm.throat_misc.neighbor,
|
|
58
|
+
pore_prop='pore.seed',
|
|
59
|
+
mode='min')
|
|
60
|
+
self.models.add(propname='pore.volume',
|
|
61
|
+
model=gm.pore_volume.voronoi)
|
|
62
|
+
self.models.add(propname='pore.diameter',
|
|
63
|
+
model=gm.pore_diameter.voronoi)
|
|
64
|
+
self.models.add(propname='pore.area',
|
|
65
|
+
model=gm.pore_area.spherical)
|
|
66
|
+
self.models.add(propname='throat.diameter',
|
|
67
|
+
model=gm.throat_diameter.voronoi)
|
|
68
|
+
self.models.add(propname='throat.length',
|
|
69
|
+
model=gm.throat_length.constant,
|
|
70
|
+
const=fibre_rad*2)
|
|
71
|
+
self.models.add(propname='throat.volume',
|
|
72
|
+
model=gm.throat_volume.extrusion)
|
|
73
|
+
self.models.add(propname='throat.surface_area',
|
|
74
|
+
model=gm.throat_surface_area.extrusion)
|
|
75
|
+
|
|
76
|
+
"Old Methods Replaced by Distance Transform"
|
|
77
|
+
#self.add_model(propname='throat.area',
|
|
78
|
+
# model=gm.throat_area.voronoi)
|
|
79
|
+
#self.add_model(propname='throat.perimeter',
|
|
80
|
+
# model=gm.throat_perimeter.voronoi)
|
|
81
|
+
#self.add_model(propname='throat.centroid',
|
|
82
|
+
# model=gm.throat_centroid.centre_of_mass)
|
|
83
|
+
#self.add_model(propname='pore.centroid',
|
|
84
|
+
# model=gm.pore_centroid.centre_of_mass)
|
|
85
|
+
#self.add_model(propname='pore.indiameter',
|
|
86
|
+
# model=gm.pore_diameter.insphere)
|
|
87
|
+
#self.add_model(propname='throat.indiameter',
|
|
88
|
+
# model=gm.throat_diameter.incircle)
|
|
89
|
+
"Shift the pore coords to the centroids"
|
|
90
|
+
#vo.pore2centroid(self._net)
|
|
91
|
+
|
|
92
|
+
if __name__ == '__main__':
|
|
93
|
+
import OpenPNM
|
|
94
|
+
pn = OpenPNM.Network.Delaunay(name='test_net')
|
|
95
|
+
pn.generate(num_pores=100, domain_size=[0.0001,0.0001,0.0001])
|
|
96
|
+
pn.add_boundaries()
|
|
97
|
+
test = OpenPNM.Geometry.Voronoi(pores=pn.Ps,throats=pn.Ts,network=pn)
|
|
98
|
+
pn.regenerate_geometries()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
###############################################################################
|
|
3
|
+
:mod:`OpenPNM.Geometry`: Classes related to the creation of pore-scale geometry
|
|
4
|
+
###############################################################################
|
|
5
|
+
|
|
6
|
+
Contents
|
|
7
|
+
--------
|
|
8
|
+
GenericGeometry: The init statement performs the important tasks of registering
|
|
9
|
+
itself with the network and creating data dictionaries of the necessary size
|
|
10
|
+
|
|
11
|
+
Subclasses: These can be custom made by users to represent specfic geometries.
|
|
12
|
+
It is necessary for their init's to call the init of the GenericGeometry class
|
|
13
|
+
in order to be properly instantiated. OpenPNM comes with a few basic
|
|
14
|
+
pre-written materials. New classes added to this directory will be
|
|
15
|
+
automatically imported and available.
|
|
16
|
+
|
|
17
|
+
Classes
|
|
18
|
+
-------
|
|
19
|
+
|
|
20
|
+
.. autoclass:: GenericGeometry
|
|
21
|
+
:members:
|
|
22
|
+
|
|
23
|
+
.. autoclass:: Stick_and_Ball
|
|
24
|
+
:members:
|
|
25
|
+
|
|
26
|
+
.. autoclass:: Cube_and_Cuboid
|
|
27
|
+
:members:
|
|
28
|
+
|
|
29
|
+
.. autoclass:: Boundary
|
|
30
|
+
:members:
|
|
31
|
+
|
|
32
|
+
.. autoclass:: Voronoi
|
|
33
|
+
:members:
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from .__GenericGeometry__ import GenericGeometry
|
|
38
|
+
from .__Cube_and_Cuboid__ import Cube_and_Cuboid
|
|
39
|
+
from .__Stick_and_Ball__ import Stick_and_Ball
|
|
40
|
+
from .__TestGeometry__ import TestGeometry
|
|
41
|
+
from .__Boundary__ import Boundary
|
|
42
|
+
from .__Voronoi__ import Voronoi
|
|
43
|
+
from .__Toray090__ import Toray090
|
|
44
|
+
from .__SGL10__ import SGL10
|
|
45
|
+
from . import models
|
|
46
|
+
|
|
47
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
*******************************************************************************
|
|
3
|
+
models -- Classes for calculating pore-scale properties
|
|
4
|
+
*******************************************************************************
|
|
5
|
+
|
|
6
|
+
Contents
|
|
7
|
+
--------
|
|
8
|
+
Contains Models for applying pore and throat geometry
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from . import pore_area
|
|
13
|
+
from . import pore_centroid
|
|
14
|
+
from . import pore_diameter
|
|
15
|
+
from . import pore_misc
|
|
16
|
+
from . import pore_seed
|
|
17
|
+
from . import pore_volume
|
|
18
|
+
from . import pore_surface_area
|
|
19
|
+
from . import pore_vertices
|
|
20
|
+
from . import throat_vertices
|
|
21
|
+
from . import throat_normal
|
|
22
|
+
from . import throat_offset_vertices
|
|
23
|
+
from . import throat_area
|
|
24
|
+
from . import throat_centroid
|
|
25
|
+
from . import throat_diameter
|
|
26
|
+
from . import throat_length
|
|
27
|
+
from . import throat_misc
|
|
28
|
+
from . import throat_perimeter
|
|
29
|
+
from . import throat_seed
|
|
30
|
+
from . import throat_surface_area
|
|
31
|
+
from . import throat_vector
|
|
32
|
+
from . import throat_volume
|
|
33
|
+
from . import throat_shape_factor
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
===============================================================================
|
|
3
|
+
pore_area -- Models for cross-sectional area of a pore body
|
|
4
|
+
===============================================================================
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import scipy as _sp
|
|
8
|
+
|
|
9
|
+
def spherical(geometry,
|
|
10
|
+
pore_diameter='pore.diameter',
|
|
11
|
+
**kwargs):
|
|
12
|
+
r"""
|
|
13
|
+
Calculate cross-sectional area for a spherical pore
|
|
14
|
+
"""
|
|
15
|
+
diams = geometry[pore_diameter]
|
|
16
|
+
value = _sp.constants.pi/4*(diams)**2
|
|
17
|
+
return value
|
|
18
|
+
|
|
19
|
+
def cubic(geometry,
|
|
20
|
+
pore_diameter='pore.diameter',
|
|
21
|
+
**kwargs):
|
|
22
|
+
r"""
|
|
23
|
+
Calculate cross-sectional pore area for a cubic pore
|
|
24
|
+
"""
|
|
25
|
+
diams = geometry[pore_diameter]
|
|
26
|
+
value = (diams)**2
|
|
27
|
+
return value
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
===============================================================================
|
|
3
|
+
pore_centroid -- N.B Neither method is accurate but is quicker than that implemented in pore.volume
|
|
4
|
+
===============================================================================
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import scipy as _sp
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def voronoi(geometry,
|
|
11
|
+
pore_vertices='pore.vertices',
|
|
12
|
+
**kwargs):
|
|
13
|
+
r"""
|
|
14
|
+
Calculate the centroid of the pore from the voronoi vertices - C.O.M
|
|
15
|
+
"""
|
|
16
|
+
verts = geometry[pore_vertices]
|
|
17
|
+
value = _sp.ndarray([len(verts),3])
|
|
18
|
+
for i,vert in enumerate(verts):
|
|
19
|
+
value[i] = _sp.array([vert[:,0].mean(),vert[:,1].mean(),vert[:,2].mean()])
|
|
20
|
+
return value
|
|
21
|
+
|
|
22
|
+
def voronoi2(geometry,
|
|
23
|
+
vertices='throat.centroid',
|
|
24
|
+
**kwargs):
|
|
25
|
+
r"""
|
|
26
|
+
Calculate the centroid from the mean of the throat centroids
|
|
27
|
+
"""
|
|
28
|
+
value = _sp.ndarray([geometry.num_pores(),3])
|
|
29
|
+
pore_map = geometry.map_pores(geometry.pores(),geometry._net)
|
|
30
|
+
for geom_pore,net_pore in pore_map:
|
|
31
|
+
net_throats = geometry._net.find_neighbor_throats(net_pore)
|
|
32
|
+
geom_throats = geometry._net.map_throats(net_throats,geometry)[:,1]
|
|
33
|
+
verts = geometry[vertices][geom_throats]
|
|
34
|
+
value[geom_pore]=_sp.array([verts[:,0].mean(),verts[:,1].mean(),verts[:,2].mean()])
|
|
35
|
+
return value
|