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.
Files changed (108) hide show
  1. OpenPNM-1.1/MANIFEST.in +2 -0
  2. OpenPNM-1.1/OpenPNM/Algorithms/__FickianDiffusion__.py +67 -0
  3. OpenPNM-1.1/OpenPNM/Algorithms/__FourierConduction__.py +63 -0
  4. OpenPNM-1.1/OpenPNM/Algorithms/__GenericAlgorithm__.py +235 -0
  5. OpenPNM-1.1/OpenPNM/Algorithms/__GenericLinearTransport__.py +641 -0
  6. OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolationForImbibition__.py +703 -0
  7. OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolationTimed__.py +702 -0
  8. OpenPNM-1.1/OpenPNM/Algorithms/__InvasionPercolation__.py +156 -0
  9. OpenPNM-1.1/OpenPNM/Algorithms/__OhmicConduction__.py +64 -0
  10. OpenPNM-1.1/OpenPNM/Algorithms/__OrdinaryPercolation__.py +402 -0
  11. OpenPNM-1.1/OpenPNM/Algorithms/__StokesFlow__.py +64 -0
  12. OpenPNM-1.1/OpenPNM/Algorithms/__Tortuosity__.py +91 -0
  13. OpenPNM-1.1/OpenPNM/Algorithms/__init__.py +48 -0
  14. OpenPNM-1.1/OpenPNM/Base/__Controller__.py +480 -0
  15. OpenPNM-1.1/OpenPNM/Base/__Core__.py +1522 -0
  16. OpenPNM-1.1/OpenPNM/Base/__ModelsDict__.py +345 -0
  17. OpenPNM-1.1/OpenPNM/Base/__Tools__.py +72 -0
  18. OpenPNM-1.1/OpenPNM/Base/__init__.py +32 -0
  19. OpenPNM-1.1/OpenPNM/Geometry/__Boundary__.py +80 -0
  20. OpenPNM-1.1/OpenPNM/Geometry/__Cube_and_Cuboid__.py +64 -0
  21. OpenPNM-1.1/OpenPNM/Geometry/__GenericGeometry__.py +106 -0
  22. OpenPNM-1.1/OpenPNM/Geometry/__SGL10__.py +67 -0
  23. OpenPNM-1.1/OpenPNM/Geometry/__Stick_and_Ball__.py +68 -0
  24. OpenPNM-1.1/OpenPNM/Geometry/__TestGeometry__.py +51 -0
  25. OpenPNM-1.1/OpenPNM/Geometry/__Toray090__.py +68 -0
  26. OpenPNM-1.1/OpenPNM/Geometry/__Voronoi__.py +98 -0
  27. OpenPNM-1.1/OpenPNM/Geometry/__init__.py +47 -0
  28. OpenPNM-1.1/OpenPNM/Geometry/models/__init__.py +33 -0
  29. OpenPNM-1.1/OpenPNM/Geometry/models/pore_area.py +27 -0
  30. OpenPNM-1.1/OpenPNM/Geometry/models/pore_centroid.py +35 -0
  31. OpenPNM-1.1/OpenPNM/Geometry/models/pore_diameter.py +127 -0
  32. OpenPNM-1.1/OpenPNM/Geometry/models/pore_misc.py +55 -0
  33. OpenPNM-1.1/OpenPNM/Geometry/models/pore_seed.py +212 -0
  34. OpenPNM-1.1/OpenPNM/Geometry/models/pore_surface_area.py +28 -0
  35. OpenPNM-1.1/OpenPNM/Geometry/models/pore_vertices.py +19 -0
  36. OpenPNM-1.1/OpenPNM/Geometry/models/pore_volume.py +133 -0
  37. OpenPNM-1.1/OpenPNM/Geometry/models/throat_area.py +47 -0
  38. OpenPNM-1.1/OpenPNM/Geometry/models/throat_centroid.py +80 -0
  39. OpenPNM-1.1/OpenPNM/Geometry/models/throat_diameter.py +106 -0
  40. OpenPNM-1.1/OpenPNM/Geometry/models/throat_length.py +95 -0
  41. OpenPNM-1.1/OpenPNM/Geometry/models/throat_misc.py +42 -0
  42. OpenPNM-1.1/OpenPNM/Geometry/models/throat_normal.py +31 -0
  43. OpenPNM-1.1/OpenPNM/Geometry/models/throat_offset_vertices.py +191 -0
  44. OpenPNM-1.1/OpenPNM/Geometry/models/throat_perimeter.py +26 -0
  45. OpenPNM-1.1/OpenPNM/Geometry/models/throat_seed.py +12 -0
  46. OpenPNM-1.1/OpenPNM/Geometry/models/throat_shape_factor.py +37 -0
  47. OpenPNM-1.1/OpenPNM/Geometry/models/throat_surface_area.py +44 -0
  48. OpenPNM-1.1/OpenPNM/Geometry/models/throat_vector.py +27 -0
  49. OpenPNM-1.1/OpenPNM/Geometry/models/throat_vertices.py +19 -0
  50. OpenPNM-1.1/OpenPNM/Geometry/models/throat_volume.py +45 -0
  51. OpenPNM-1.1/OpenPNM/Network/__Cubic__.py +316 -0
  52. OpenPNM-1.1/OpenPNM/Network/__DelaunayCubic__.py +127 -0
  53. OpenPNM-1.1/OpenPNM/Network/__Delaunay__.py +600 -0
  54. OpenPNM-1.1/OpenPNM/Network/__GenericNetwork__.py +1184 -0
  55. OpenPNM-1.1/OpenPNM/Network/__MatFile__.py +331 -0
  56. OpenPNM-1.1/OpenPNM/Network/__TestNet__.py +109 -0
  57. OpenPNM-1.1/OpenPNM/Network/__init__.py +40 -0
  58. OpenPNM-1.1/OpenPNM/Network/models/__init__.py +12 -0
  59. OpenPNM-1.1/OpenPNM/Network/models/pore_topology.py +106 -0
  60. OpenPNM-1.1/OpenPNM/Phases/__Air__.py +63 -0
  61. OpenPNM-1.1/OpenPNM/Phases/__GenericPhase__.py +146 -0
  62. OpenPNM-1.1/OpenPNM/Phases/__Mercury__.py +71 -0
  63. OpenPNM-1.1/OpenPNM/Phases/__TestPhase__.py +46 -0
  64. OpenPNM-1.1/OpenPNM/Phases/__Water__.py +56 -0
  65. OpenPNM-1.1/OpenPNM/Phases/__init__.py +38 -0
  66. OpenPNM-1.1/OpenPNM/Phases/models/__init__.py +22 -0
  67. OpenPNM-1.1/OpenPNM/Phases/models/contact_angle.py +34 -0
  68. OpenPNM-1.1/OpenPNM/Phases/models/density.py +81 -0
  69. OpenPNM-1.1/OpenPNM/Phases/models/diffusivity.py +95 -0
  70. OpenPNM-1.1/OpenPNM/Phases/models/electrical_conductivity.py +10 -0
  71. OpenPNM-1.1/OpenPNM/Phases/models/misc.py +125 -0
  72. OpenPNM-1.1/OpenPNM/Phases/models/molar_density.py +69 -0
  73. OpenPNM-1.1/OpenPNM/Phases/models/molar_mass.py +31 -0
  74. OpenPNM-1.1/OpenPNM/Phases/models/surface_tension.py +104 -0
  75. OpenPNM-1.1/OpenPNM/Phases/models/thermal_conductivity.py +98 -0
  76. OpenPNM-1.1/OpenPNM/Phases/models/vapor_pressure.py +69 -0
  77. OpenPNM-1.1/OpenPNM/Phases/models/viscosity.py +103 -0
  78. OpenPNM-1.1/OpenPNM/Physics/__GenericPhysics__.py +111 -0
  79. OpenPNM-1.1/OpenPNM/Physics/__Standard__.py +51 -0
  80. OpenPNM-1.1/OpenPNM/Physics/__TestPhysics__.py +50 -0
  81. OpenPNM-1.1/OpenPNM/Physics/__init__.py +30 -0
  82. OpenPNM-1.1/OpenPNM/Physics/models/__init__.py +18 -0
  83. OpenPNM-1.1/OpenPNM/Physics/models/capillary_pressure.py +122 -0
  84. OpenPNM-1.1/OpenPNM/Physics/models/diffusive_conductance.py +82 -0
  85. OpenPNM-1.1/OpenPNM/Physics/models/electrical_conductance.py +59 -0
  86. OpenPNM-1.1/OpenPNM/Physics/models/generic_source_term.py +564 -0
  87. OpenPNM-1.1/OpenPNM/Physics/models/hydraulic_conductance.py +76 -0
  88. OpenPNM-1.1/OpenPNM/Physics/models/multiphase.py +133 -0
  89. OpenPNM-1.1/OpenPNM/Physics/models/thermal_conductance.py +67 -0
  90. OpenPNM-1.1/OpenPNM/Postprocessing/Graphics.py +251 -0
  91. OpenPNM-1.1/OpenPNM/Postprocessing/Plots.py +369 -0
  92. OpenPNM-1.1/OpenPNM/Postprocessing/__init__.py +10 -0
  93. OpenPNM-1.1/OpenPNM/Utilities/IO.py +277 -0
  94. OpenPNM-1.1/OpenPNM/Utilities/Shortcuts.py +17 -0
  95. OpenPNM-1.1/OpenPNM/Utilities/__init__.py +16 -0
  96. OpenPNM-1.1/OpenPNM/Utilities/misc.py +226 -0
  97. OpenPNM-1.1/OpenPNM/Utilities/transformations.py +1923 -0
  98. OpenPNM-1.1/OpenPNM/Utilities/vertexops.py +824 -0
  99. OpenPNM-1.1/OpenPNM/__init__.py +56 -0
  100. OpenPNM-1.1/OpenPNM.egg-info/PKG-INFO +11 -0
  101. OpenPNM-1.1/OpenPNM.egg-info/SOURCES.txt +107 -0
  102. OpenPNM-1.1/OpenPNM.egg-info/dependency_links.txt +1 -0
  103. OpenPNM-1.1/OpenPNM.egg-info/requires.txt +1 -0
  104. OpenPNM-1.1/OpenPNM.egg-info/top_level.txt +1 -0
  105. OpenPNM-1.1/PKG-INFO +11 -0
  106. OpenPNM-1.1/README.txt +88 -0
  107. OpenPNM-1.1/setup.cfg +7 -0
  108. OpenPNM-1.1/setup.py +39 -0
@@ -0,0 +1,111 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ===============================================================================
4
+ module __Physics__: Base class for mananging pore-scale Physics properties
5
+ ===============================================================================
6
+
7
+ """
8
+ from OpenPNM.Base import logging
9
+ logger = logging.getLogger(__name__)
10
+ from OpenPNM.Network import GenericNetwork
11
+ from OpenPNM.Phases import GenericPhase
12
+ import OpenPNM.Physics.models
13
+ import scipy as sp
14
+
15
+ class GenericPhysics(OpenPNM.Base.Core):
16
+ r"""
17
+ Generic class to generate Physics objects
18
+
19
+ Parameters
20
+ ----------
21
+ network : OpenPNM Network object
22
+ The network to which this Physics should be attached
23
+
24
+ phase : OpenPNM Phase object
25
+ The Phase object to which this Physics applies
26
+
27
+ geometry : OpenPNM Geometry object
28
+ The Geometry object that defines the pores/throats where this Physics
29
+ should be applied. If this argument is supplied, then pores and
30
+ throats cannot be specified.
31
+
32
+ pores and/or throats : array_like
33
+ The list of pores and throats where this physics applies. If either are
34
+ left blank this will apply the physics nowhere. The locations can be
35
+ change after instantiation using ``set_locations()``. If pores and
36
+ throats are supplied, than a geometry cannot be specified.
37
+
38
+ name : str, optional
39
+ A unique string name to identify the Physics object, typically same as
40
+ instance name but can be anything. If left blank, and name will be
41
+ generated that include the class name and a random string.
42
+
43
+
44
+
45
+ """
46
+
47
+ def __init__(self,network=None,phase=None,geometry=None,pores=[],throats=[],**kwargs):
48
+ super(GenericPhysics,self).__init__(**kwargs)
49
+ logger.name = self.name
50
+
51
+ #Associate with Network
52
+ if network is None:
53
+ self._net = GenericNetwork()
54
+ else:
55
+ self._net = network # Attach network to self
56
+ self._net._physics.append(self) # Register self with network
57
+
58
+ #Associate with Phase
59
+ if phase is None:
60
+ self._phases.append(GenericPhase())
61
+ else:
62
+ phase._physics.append(self) # Register self with phase
63
+ self._phases.append(phase) # Register phase with self
64
+
65
+ if geometry is not None:
66
+ if (pores != []) or (throats != []):
67
+ raise Exception('Cannot specify a Geometry AND pores or throats')
68
+ pores = self._net.toindices(self._net['pore.'+geometry.name])
69
+ throats = self._net.toindices(self._net['throat.'+geometry.name])
70
+
71
+ #Initialize a label dictionary in the associated fluid
72
+ self._phases[0]['pore.'+self.name] = False
73
+ self._phases[0]['throat.'+self.name] = False
74
+ self._net['pore.'+self.name] = False
75
+ self._net['throat.'+self.name] = False
76
+ self.set_locations(pores=pores,throats=throats)
77
+
78
+ def __getitem__(self,key):
79
+ element = key.split('.')[0]
80
+ # Convert self.name into 'all'
81
+ if key.split('.')[-1] == self.name:
82
+ key = element + '.all'
83
+
84
+ if key in self.keys(): # Look for data on self...
85
+ return super(GenericPhysics,self).__getitem__(key)
86
+ else: # ...Then check Network
87
+ return self._phases[0][key][self._phases[0][element+'.'+self.name]]
88
+
89
+ def set_locations(self,pores=[],throats=[],mode='add'):
90
+ r'''
91
+ Set the pore and throat locations of the Physics object
92
+
93
+ Parameters
94
+ ----------
95
+ pores and throats : array_like
96
+ The list of pores and/or throats where the object should be applied.
97
+ mode : string
98
+ Indicates whether list of pores or throats is to be added or removed
99
+ from the object. Options are 'add' (default) or 'remove'.
100
+ '''
101
+ if len(pores) > 0:
102
+ pores = sp.array(pores,ndmin=1)
103
+ self._set_locations(element='pore',locations=pores,mode=mode)
104
+ if len(throats) > 0:
105
+ throats = sp.array(throats,ndmin=1)
106
+ self._set_locations(element='throat',locations=throats,mode=mode)
107
+
108
+ if __name__ == '__main__':
109
+ print('none yet')
110
+
111
+
@@ -0,0 +1,51 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ===============================================================================
4
+ module Physics
5
+ ===============================================================================
6
+
7
+ """
8
+
9
+ from OpenPNM.Physics import models as pm
10
+ from OpenPNM.Physics.__GenericPhysics__ import GenericPhysics
11
+
12
+ class Standard(GenericPhysics):
13
+ r"""
14
+ Base class to generate a generic Physics object. The user must specify models
15
+ and parameters for the all the properties they require. Classes for several
16
+ common Physics are included with OpenPNM and can be found under OpenPNM.Physics.
17
+
18
+ Parameters
19
+ ----------
20
+ network : OpenPNM Network object
21
+ The network to which this Physics should be attached
22
+
23
+ phase : OpenPNM Phase object
24
+ The Phase object to which this Physics applies
25
+
26
+ pores and throats : array_like
27
+ The pores and throats where this Physics object applies
28
+
29
+ """
30
+
31
+ def __init__(self,**kwargs):
32
+ super(Standard,self).__init__(**kwargs)
33
+ self._generate()
34
+
35
+ def _generate(self):
36
+ for phase in self._phases:
37
+ temp = [item.split('.')[1] for item in phase.props()]
38
+ if 'viscosity' in temp:
39
+ self.models.add(propname='throat.hydraulic_conductance',
40
+ model=pm.hydraulic_conductance.hagen_poiseuille)
41
+ if 'diffusivity' in temp:
42
+ self.models.add(propname='throat.diffusive_conductance',
43
+ model=pm.diffusive_conductance.bulk_diffusion)
44
+ if 'surface_tension' in temp:
45
+ self.models.add(propname='throat.capillary_pressure',
46
+ model=pm.capillary_pressure.washburn)
47
+
48
+ if __name__ == '__main__':
49
+ print('none yet')
50
+
51
+
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ===============================================================================
4
+ module Physics
5
+ ===============================================================================
6
+
7
+ """
8
+
9
+ from OpenPNM.Physics import models as pm
10
+ from OpenPNM.Physics import GenericPhysics
11
+
12
+ class TestPhysics(GenericPhysics):
13
+ r"""
14
+ Base class to generate a generic Physics object. The user must specify models
15
+ and parameters for the all the properties they require. Classes for several
16
+ common Physics are included with OpenPNM and can be found under OpenPNM.Physics.
17
+
18
+ Parameters
19
+ ----------
20
+ network : OpenPNM Network object
21
+ The network to which this Physics should be attached
22
+
23
+ phase : OpenPNM Phase object
24
+ The Phase object to which this Physics applies
25
+
26
+ pores and throats : array_like
27
+ The pores and throats where this Physics object applies
28
+
29
+ """
30
+
31
+ def __init__(self,**kwargs):
32
+ super(TestPhysics,self).__init__(**kwargs)
33
+ self._generate()
34
+
35
+ def _generate(self):
36
+ for phase in self._phases:
37
+ temp = [item.split('.')[1] for item in phase.props()]
38
+ if 'viscosity' in temp:
39
+ self['throat.hydraulic_conductance'] = 1
40
+ if 'diffusivity' in temp:
41
+ self['throat.diffusive_conductance'] = 1
42
+ if 'surface_tension' in temp:
43
+ self['throat.capillary_pressure'] = 1/self._net['throat.diameter']
44
+ if 'thermal_conductivity' in temp:
45
+ self['throat.thermal_conductance'] = phase['throat.thermal_conductivity']*self._net['throat.diameter']/self._net['throat.length']
46
+
47
+ if __name__ == '__main__':
48
+ print('none yet')
49
+
50
+
@@ -0,0 +1,30 @@
1
+ r"""
2
+ ###############################################################################
3
+ :mod:`OpenPNM.Physics` -- Pore Scale Physics Models
4
+ ###############################################################################
5
+
6
+ Contents
7
+ --------
8
+ GenericPhysics: This base class is essentially an init statement that ensures
9
+ the Physics object registers itself with Phase and Network objects correctly.
10
+
11
+ Subclasses: OpenPNM includes one subclass called Standard which invokes the
12
+ typical pore scale physics models such as the Hagen-Poiseiulle model for
13
+ hydraulic conductance through a tube. Customized Physics classes can be
14
+ created by adding a file to the Physics directory, which will be imported
15
+ automatically.
16
+
17
+ Classes
18
+ -------
19
+ .. autoclass:: GenericPhysics
20
+ :members:
21
+
22
+ .. autoclass:: Standard
23
+ :members:
24
+
25
+ """
26
+
27
+ from .__GenericPhysics__ import GenericPhysics
28
+ from .__Standard__ import Standard
29
+ from .__TestPhysics__ import TestPhysics
30
+ from . import models
@@ -0,0 +1,18 @@
1
+ r"""
2
+ *******************************************************************************
3
+ models -- Functions for calculating pore-scale Physics models
4
+ *******************************************************************************
5
+
6
+ Contents
7
+ --------
8
+ This submodule contains all pore scale physics models applied to a pore network.
9
+
10
+ """
11
+
12
+ from . import capillary_pressure
13
+ from . import diffusive_conductance
14
+ from . import electrical_conductance
15
+ from . import thermal_conductance
16
+ from . import hydraulic_conductance
17
+ from . import multiphase
18
+ from . import generic_source_term
@@ -0,0 +1,122 @@
1
+ r"""
2
+ ===============================================================================
3
+ Submodule -- capillary_pressure
4
+ ===============================================================================
5
+
6
+ """
7
+
8
+ import scipy as _sp
9
+
10
+ def washburn(physics,
11
+ phase,
12
+ network,
13
+ surface_tension='pore.surface_tension',
14
+ contact_angle='pore.contact_angle',
15
+ throat_diameter='throat.diameter',
16
+ **kwargs):
17
+ r"""
18
+ Computes the capillary entry pressure assuming the throat is a cylindrical tube.
19
+
20
+ Parameters
21
+ ----------
22
+ network : OpenPNM Network Object
23
+ The Network object is
24
+ phase : OpenPNM Phase Object
25
+ Phase object for the invading phases containing the surface tension and
26
+ contact angle values.
27
+ sigma : dict key (string)
28
+ The dictionary key containing the surface tension values to be used. If
29
+ a pore property is given, it is interpolated to a throat list.
30
+ theta : dict key (string)
31
+ The dictionary key containing the contact angle values to be used. If
32
+ a pore property is given, it is interpolated to a throat list.
33
+ throat_diameter : dict key (string)
34
+ The dictionary key containing the throat diameter values to be used.
35
+
36
+ Notes
37
+ -----
38
+ The Washburn equation is:
39
+
40
+ .. math::
41
+ P_c = -\frac{2\sigma(cos(\theta))}{r}
42
+
43
+ This is the most basic approach to calculating entry pressure and is
44
+ suitable for highly non-wetting invading phases in most materials.
45
+
46
+ """
47
+ if surface_tension.split('.')[0] == 'pore':
48
+ sigma = phase[surface_tension]
49
+ sigma = phase.interpolate_data(data=sigma)
50
+ else:
51
+ sigma = phase[surface_tension]
52
+ if contact_angle.split('.')[0] == 'pore':
53
+ theta = phase[contact_angle]
54
+ theta = phase.interpolate_data(data=theta)
55
+ else:
56
+ theta = phase[contact_angle]
57
+ r = network[throat_diameter]/2
58
+ value = -2*sigma*_sp.cos(_sp.radians(theta))/r
59
+ value = value[phase.throats(physics.name)]
60
+ return value
61
+
62
+ def purcell(physics,
63
+ phase,
64
+ network,
65
+ r_toroid,
66
+ surface_tension='pore.surface_tension',
67
+ contact_angle='pore.contact_angle',
68
+ throat_diameter='throat.diameter',
69
+ **kwargs):
70
+ r"""
71
+ Computes the throat capillary entry pressure assuming the throat is a toroid.
72
+
73
+ Parameters
74
+ ----------
75
+ network : OpenPNM Network Object
76
+ The Network on which to apply the calculation
77
+ sigma : dict key (string)
78
+ The dictionary key containing the surface tension values to be used. If
79
+ a pore property is given, it is interpolated to a throat list.
80
+ theta : dict key (string)
81
+ The dictionary key containing the contact angle values to be used. If
82
+ a pore property is given, it is interpolated to a throat list.
83
+ throat_diameter : dict key (string)
84
+ The dictionary key containing the throat diameter values to be used.
85
+ r_toroid : float or array_like
86
+ The radius of the toroid surrounding the pore
87
+
88
+ Notes
89
+ -----
90
+ This approach accounts for the converging-diverging nature of many throat
91
+ types. Advancing the meniscus beyond the apex of the toroid requires an
92
+ increase in capillary pressure beyond that for a cylindical tube of the
93
+ same radius. The details of this equation are described by Mason and
94
+ Morrow [1]_, and explored by Gostick [2]_ in the context of a pore network
95
+ model.
96
+
97
+ References
98
+ ----------
99
+
100
+ .. [1] G. Mason, N. R. Morrow, Effect of contact angle on capillary displacement curvatures in pore throats formed by spheres. J. Colloid Interface Sci. 168, 130 (1994).
101
+ .. [2] J. Gostick, Random pore network modeling of fibrous PEMFC gas diffusion media using Voronoi and Delaunay tessellations. J. Electrochem. Soc. 160, F731 (2013).
102
+
103
+ TODO: Triple check the accuracy of this equation
104
+ """
105
+
106
+ if surface_tension.split('.')[0] == 'pore':
107
+ sigma = phase[surface_tension]
108
+ sigma = phase.interpolate_data(data=sigma)
109
+ else:
110
+ sigma = phase[surface_tension]
111
+ if contact_angle.split('.')[0] == 'pore':
112
+ theta = phase[contact_angle]
113
+ theta = phase.interpolate_data(data=theta)
114
+ else:
115
+ theta = phase[contact_angle]
116
+ r = network[throat_diameter]/2
117
+ R = r_toroid
118
+ alpha = theta - 180 + _sp.arcsin(_sp.sin(_sp.radians(theta)/(1+r/R)))
119
+ value = (-2*sigma/r)*(_sp.cos(_sp.radians(theta - alpha))/(1 + R/r*(1-_sp.cos(_sp.radians(alpha)))))
120
+ value = value[phase.throats(physics.name)]
121
+ return value
122
+
@@ -0,0 +1,82 @@
1
+ r"""
2
+ ===============================================================================
3
+ Submodule -- diffusive_conductance
4
+ ===============================================================================
5
+
6
+ """
7
+
8
+ import scipy as _sp
9
+ import OpenPNM.Utilities.misc as misc
10
+
11
+ def bulk_diffusion(physics,
12
+ phase,
13
+ network,
14
+ pore_molar_density='pore.molar_density',
15
+ pore_diffusivity='pore.diffusivity',
16
+ pore_area='pore.area',
17
+ pore_diameter='pore.diameter',
18
+ throat_area='throat.area',
19
+ throat_length='throat.length',
20
+ throat_diameter='throat.diameter',
21
+ calc_pore_len=True,
22
+ **kwargs):
23
+ r"""
24
+ Calculate the diffusive conductance of conduits in network, where a
25
+ conduit is ( 1/2 pore - full throat - 1/2 pore ) based on the areas
26
+
27
+ Parameters
28
+ ----------
29
+ network : OpenPNM Network Object
30
+
31
+ phase : OpenPNM Phase Object
32
+ The phase of interest
33
+
34
+ Notes
35
+ -----
36
+ (1) This function requires that all the necessary phase properties already
37
+ be calculated.
38
+
39
+ (2) This function calculates the specified property for the *entire*
40
+ network then extracts the values for the appropriate throats at the end.
41
+
42
+ """
43
+ #Get Nt-by-2 list of pores connected to each throat
44
+ Ps = network['throat.conns']
45
+ #Get properties in every pore in the network
46
+ parea = network[pore_area]
47
+ pdia = network[pore_diameter]
48
+ #Get the properties of every throat
49
+ tarea = network[throat_area]
50
+ tlen = network[throat_length]
51
+ #Interpolate pore phase property values to throats
52
+ cp = phase[pore_molar_density]
53
+ ct = phase.interpolate_data(data=cp)
54
+ DABp = phase[pore_diffusivity]
55
+ DABt = phase.interpolate_data(data=DABp)
56
+ if calc_pore_len:
57
+ lengths = misc.conduit_lengths(network,mode='centroid')
58
+ plen1 = lengths[:,0]
59
+ plen2 = lengths[:,2]
60
+ else:
61
+ plen1 = (0.5*pdia[Ps[:,0]])
62
+ plen2 = (0.5*pdia[Ps[:,1]])
63
+ #remove any non-positive lengths
64
+ plen1[plen1<=0]=1e-12
65
+ plen2[plen2<=0]=1e-12
66
+ #Find g for half of pore 1
67
+ gp1 = ct*DABt*parea[Ps[:,0]]/plen1
68
+ gp1[_sp.isnan(gp1)] = _sp.inf
69
+ gp1[~(gp1>0)] = _sp.inf # Set 0 conductance pores (boundaries) to inf
70
+ #Find g for half of pore 2
71
+ gp2 = ct*DABt*parea[Ps[:,1]]/plen2
72
+ gp2[_sp.isnan(gp2)] = _sp.inf
73
+ gp2[~(gp2>0)] = _sp.inf # Set 0 conductance pores (boundaries) to inf
74
+ #Find g for full throat
75
+ #remove any non-positive lengths
76
+ tlen[tlen<=0] = 1e-12
77
+ gt = ct*DABt*tarea/tlen
78
+ value = (1/gt + 1/gp1 + 1/gp2)**(-1)
79
+ value = value[phase.throats(physics.name)]
80
+ return value
81
+
82
+
@@ -0,0 +1,59 @@
1
+ r"""
2
+ ===============================================================================
3
+ Submodule -- electrical_conductance
4
+ ===============================================================================
5
+
6
+ """
7
+
8
+ import scipy as _sp
9
+
10
+ def series_resistors(physics,
11
+ phase,
12
+ network,
13
+ pore_conductivity='pore.electrical_conductivity',
14
+ pore_area='pore.area',
15
+ pore_diameter='pore.diameter',
16
+ throat_area='throat.area',
17
+ throat_length='throat.length',
18
+ **kwargs):
19
+ r"""
20
+ Calculates the electrical conductance of throat assuming cylindrical geometry
21
+
22
+ Parameters
23
+ ----------
24
+ network : OpenPNM Network Object
25
+
26
+ phase : OpenPNM Phase Object
27
+
28
+ Notes
29
+ -----
30
+ (1) This function requires that all the necessary phase properties already
31
+ be calculated.
32
+
33
+ (2) This function calculates the specified property for the *entire*
34
+ network then extracts the values for the appropriate throats at the end.
35
+
36
+ """
37
+ #Get Nt-by-2 list of pores connected to each throat
38
+ Ps = network['throat.conns']
39
+ #Get properties in every pore in the network
40
+ sigmap = phase[pore_conductivity]
41
+ sigmat = phase.interpolate_data(sigmap)
42
+ #Find g for half of pore 1
43
+ parea = network[pore_area]
44
+ pdia = network[pore_diameter]
45
+ #remove any non-positive lengths
46
+ pdia[pdia<=0] = 0
47
+ gp1 = sigmap[Ps[:,0]]*parea[Ps[:,0]]/(0.5*pdia[Ps[:,0]])
48
+ #Find g for half of pore 2
49
+ gp2 = sigmap[Ps[:,1]]*parea[Ps[:,1]]/(0.5*pdia[Ps[:,1]])
50
+ #Find g for full throat
51
+ tarea = network[throat_area]
52
+ tlen = network[throat_length]
53
+ #remove any non-positive lengths
54
+ tlen[tlen<=0] = 0
55
+ gt = sigmat*tarea/tlen
56
+ value = (1/gt + 1/gp1 + 1/gp2)**(-1)
57
+ value = value[phase.throats(physics.name)]
58
+ return value
59
+