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,564 @@
1
+ r"""
2
+ ===============================================================================
3
+ Submodule -- generic_source_term
4
+ ===============================================================================
5
+
6
+ """
7
+
8
+ import scipy as _sp
9
+
10
+ def linear(physics,
11
+ phase,
12
+ A1='',
13
+ A2='',
14
+ x='',
15
+ return_rate=True,
16
+ **kwargs):
17
+ r"""
18
+ For the following source term:
19
+ .. math::
20
+ r = A_{1} x + A_{2}
21
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
22
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
23
+ .. math::
24
+ r = S_{1} x + S_{2}
25
+
26
+ Parameters
27
+ ----------
28
+ A1 , A2 : string
29
+ The property name of the coefficients in the source term model. With A2 set to zero
30
+ this equation takes on the familiar for of r=kx.
31
+ x : string or float/int or array/list
32
+ The property name or numerical value or array for the main quantity
33
+ Notes
34
+ -----
35
+ Because this source term is linear in concentration (x) is it not necessary
36
+ to iterate during the solver step. Thus, when using the
37
+ ``set_source_term`` method for an algorithm, it is recommended to set the ``maxiter``
38
+ argument to 0. This will save 1 unncessary solution of the system, since
39
+ the solution would coverge after the first pass anyway.
40
+
41
+ """
42
+ if x=='':
43
+ X = _sp.ones(physics.Np)*_sp.nan
44
+ else:
45
+ if type(x)==str:
46
+ x = 'pore.'+x.split('.')[-1]
47
+ try: X = physics[x]
48
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
49
+ else:
50
+ X = _sp.array(x)
51
+
52
+ length_X = _sp.size(X)
53
+ if length_X!=physics.Np:
54
+ if length_X==1:
55
+ X = X*_sp.ones(physics.Np)
56
+ elif length_X>=phase.Np:
57
+ X = X[physics.map_pores()]
58
+ else: raise Exception('Wrong size for the numerical array of x!')
59
+
60
+ if A1 == '': a1 = 0
61
+ else:
62
+ if type(A1)==str:
63
+ A1 = 'pore.'+A1.split('.')[-1]
64
+ try: a1 = physics[A1]
65
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
66
+ else: raise Exception('A1 can be only string!')
67
+
68
+ if A2 == '': a2 = 0
69
+ else:
70
+ if type(A2)==str:
71
+ A2 = 'pore.'+A2.split('.')[-1]
72
+ try: a2 = physics[A2]
73
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
74
+ else: raise Exception('A2 can be only string!')
75
+
76
+ if return_rate:
77
+ return(a1*X**a2)
78
+ else:
79
+ S1 = a1
80
+ S2 = a2
81
+ return(_sp.vstack((S1,S2)).T)
82
+
83
+ def power_law(physics,
84
+ phase,
85
+ A1='',
86
+ A2='',
87
+ A3='',
88
+ x='',
89
+ return_rate=True,
90
+ **kwargs):
91
+ r"""
92
+ For the following source term:
93
+ .. math::
94
+ r = A_{1} x^{A_{2}} + A_{3}
95
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
96
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
97
+ .. math::
98
+ r = S_{1} x + S_{2}
99
+
100
+ Parameters
101
+ ----------
102
+ A1 -> A3 : string
103
+ The property name of the coefficients in the source term model
104
+ x : string or float/int or array/list
105
+ The property name or numerical value or array for the main quantity
106
+ Notes
107
+ -----
108
+
109
+ """
110
+ if x=='':
111
+ X = _sp.ones(physics.Np)*_sp.nan
112
+ # length_X = _sp.size(x)
113
+ else:
114
+ if type(x)==str:
115
+ x = 'pore.'+x.split('.')[-1]
116
+ try: X = physics[x]
117
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
118
+ else:
119
+ X = _sp.array(x)
120
+
121
+ length_X = _sp.size(X)
122
+ if length_X!=physics.Np:
123
+ if length_X==1:
124
+ X = X*_sp.ones(physics.Np)
125
+ elif length_X>=phase.Np:
126
+ X = X[physics.map_pores()]
127
+ else: raise Exception('Wrong size for the numerical array of x!')
128
+
129
+ if A1 == '': a1 = 0
130
+ else:
131
+ if type(A1)==str:
132
+ A1 = 'pore.'+A1.split('.')[-1]
133
+ try: a1 = physics[A1]
134
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
135
+ else: raise Exception('A1 can be only string!')
136
+
137
+ if A2 == '': a2 = 0
138
+ else:
139
+ if type(A2)==str:
140
+ A2 = 'pore.'+A2.split('.')[-1]
141
+ try: a2 = physics[A2]
142
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
143
+ else: raise Exception('A2 can be only string!')
144
+
145
+ if A3 == '': a3 = 0
146
+ else:
147
+ if type(A3)==str:
148
+ A3 = 'pore.'+A3.split('.')[-1]
149
+ try: a3 = physics[A3]
150
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A3+'!')
151
+ else: raise Exception('A3 can be only string!')
152
+
153
+ if return_rate:
154
+ return(a1*X**a2 +a3)
155
+ else:
156
+ S1 = a1*a2*X**(a2-1)
157
+ S2 = a1*X**a2*(1-a2)+a3
158
+ return(_sp.vstack((S1,S2)).T)
159
+
160
+
161
+ def exponential(physics,
162
+ phase,
163
+ A1='',
164
+ A2='',
165
+ A3='',
166
+ A4='',
167
+ A5='',
168
+ A6='',
169
+ x='',
170
+ return_rate=True,
171
+ **kwargs):
172
+ r"""
173
+ For the following source term:
174
+ .. math::
175
+ r = A_{1} A_{2}^{( A_{3} x^{ A_{4} } + A_{5})} + A_{6}
176
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
177
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
178
+ .. math::
179
+ r = S_{1} x + S_{2}
180
+
181
+ Parameters
182
+ ----------
183
+ A1 -> A6 : string
184
+ The property name of the coefficients in the source term model
185
+ x : string or float/int or array/list
186
+ The property name or numerical value or array for the main quantity
187
+ Notes
188
+ -----
189
+
190
+ """
191
+ if x=='':
192
+ X = _sp.ones(physics.Np)*_sp.nan
193
+ # length_X = _sp.size(x)
194
+ else:
195
+ if type(x)==str:
196
+ x = 'pore.'+x.split('.')[-1]
197
+ try: X = physics[x]
198
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
199
+ else:
200
+ X = _sp.array(x)
201
+
202
+ length_X = _sp.size(X)
203
+ if length_X!=physics.Np:
204
+ if length_X==1:
205
+ X = X*_sp.ones(physics.Np)
206
+ elif length_X>=phase.Np:
207
+ X = X[physics.map_pores()]
208
+ else: raise Exception('Wrong size for the numerical array of x!')
209
+
210
+ if A1 == '': a1 = 1
211
+ else:
212
+ if type(A1)==str:
213
+ A1 = 'pore.'+A1.split('.')[-1]
214
+ try: a1 = physics[A1]
215
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
216
+ else: raise Exception('A1 can be only string!')
217
+
218
+ if A2 == '': a2 = 0
219
+ else:
220
+ if type(A2)==str:
221
+ A2 = 'pore.'+A2.split('.')[-1]
222
+ try: a2 = physics[A2]
223
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
224
+ else: raise Exception('A2 can be only string!')
225
+
226
+ if A3 == '': a3 = 0
227
+ else:
228
+ if type(A3)==str:
229
+ A3 = 'pore.'+A3.split('.')[-1]
230
+ try: a3 = physics[A3]
231
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A3+'!')
232
+ else: raise Exception('A3 can be only string!')
233
+
234
+
235
+ if A4 == '': a4 = 0
236
+ else:
237
+ if type(A4)==str:
238
+ A4 = 'pore.'+A4.split('.')[-1]
239
+ try: a4 = physics[A4]
240
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A4+'!')
241
+ else: raise Exception('A4 can be only string!')
242
+
243
+ if A5 == '': a5 = 0
244
+ else:
245
+ if type(A5)==str:
246
+ A5 = 'pore.'+A5.split('.')[-1]
247
+ try: a5 = physics[A5]
248
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A5+'!')
249
+ else: raise Exception('A5 can be only string!')
250
+
251
+ if A6 == '': a6 = 0
252
+ else:
253
+ if type(A6)==str:
254
+ A6 = 'pore.'+A6.split('.')[-1]
255
+ try: a6 = physics[A6]
256
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A6+'!')
257
+ else: raise Exception('A6 can be only string!')
258
+
259
+ if return_rate:
260
+ return(a1*a2**(a3*X**a4 +a5)+a6)
261
+ else:
262
+ S1 = a1*a3*a4*_sp.log(a2)*a2**(a3*X**a4+a5)*X**(a4-1)
263
+ S2 = a1*a2**(a3*X**a4+a5)*(1-a3*a4*_sp.log(a2)*X**a4)+a6
264
+ return(_sp.vstack((S1,S2)).T)
265
+
266
+
267
+ def natural_exponential(physics,
268
+ phase,
269
+ A1='',
270
+ A2='',
271
+ A3='',
272
+ A4='',
273
+ A5='',
274
+ x='',
275
+ return_rate=True,
276
+ **kwargs):
277
+ r"""
278
+ For the following source term:
279
+ .. math::
280
+ r = A_{1} exp( A_{2} x^{ A_{3} } + A_{4} )+ A_{5}
281
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
282
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
283
+ .. math::
284
+ r = S_{1} x + S_{2}
285
+
286
+ Parameters
287
+ ----------
288
+ A1 -> A5 : string
289
+ The property name of the coefficients in the source term model
290
+ x : string or float/int or array/list
291
+ The property name or numerical value or array for the main quantity
292
+ Notes
293
+ -----
294
+
295
+ """
296
+ if x=='':
297
+ X = _sp.ones(physics.Np)*_sp.nan
298
+ # length_X = _sp.size(x)
299
+ else:
300
+ if type(x)==str:
301
+ x = 'pore.'+x.split('.')[-1]
302
+ try: X = physics[x]
303
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
304
+ else:
305
+ X = _sp.array(x)
306
+
307
+ length_X = _sp.size(X)
308
+ if length_X!=physics.Np:
309
+ if length_X==1:
310
+ X = X*_sp.ones(physics.Np)
311
+ elif length_X>=phase.Np:
312
+ X = X[physics.map_pores()]
313
+ else: raise Exception('Wrong size for the numerical array of x!')
314
+
315
+ if A1 == '': a1 = 1
316
+ else:
317
+ if type(A1)==str:
318
+ A1 = 'pore.'+A1.split('.')[-1]
319
+ try: a1 = physics[A1]
320
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
321
+ else: raise Exception('A1 can be only string!')
322
+
323
+ if A2 == '': a2 = 0
324
+ else:
325
+ if type(A2)==str:
326
+ A2 = 'pore.'+A2.split('.')[-1]
327
+ try: a2 = physics[A2]
328
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
329
+ else: raise Exception('A2 can be only string!')
330
+
331
+ if A3 == '': a3 = 0
332
+ else:
333
+ if type(A3)==str:
334
+ A3 = 'pore.'+A3.split('.')[-1]
335
+ try: a3 = physics[A3]
336
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A3+'!')
337
+ else: raise Exception('A3 can be only string!')
338
+
339
+
340
+ if A4 == '': a4 = 0
341
+ else:
342
+ if type(A4)==str:
343
+ A4 = 'pore.'+A4.split('.')[-1]
344
+ try: a4 = physics[A4]
345
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A4+'!')
346
+ else: raise Exception('A4 can be only string!')
347
+
348
+ if A5 == '': a5 = 0
349
+ else:
350
+ if type(A5)==str:
351
+ A5 = 'pore.'+A5.split('.')[-1]
352
+ try: a5 = physics[A5]
353
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A5+'!')
354
+ else: raise Exception('A5 can be only string!')
355
+
356
+ if return_rate:
357
+ return(a1*_sp.exp(a2*X**a3+a4) +a5)
358
+ else:
359
+ S1 = a1*a2*a3*X**(a3-1)*_sp.exp(a2*X**a3+a4)
360
+ S2 = a1*_sp.exp(a2*X**a3+a4)*(1-a2*a3*X**a3)+a5
361
+ return(_sp.vstack((S1,S2)).T)
362
+
363
+ def logarithm(physics,
364
+ phase,
365
+ A1='',
366
+ A2='',
367
+ A3='',
368
+ A4='',
369
+ A5='',
370
+ A6='',
371
+ x='',
372
+ return_rate=True,
373
+ **kwargs):
374
+ r"""
375
+ For the following source term:
376
+ .. math::
377
+ r = A_{1} Log_{ A_{2} }( A_{3} x^{ A_{4} }+ A_{5})+ A_{6}
378
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
379
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
380
+ .. math::
381
+ r = S_{1} x + S_{2}
382
+
383
+ Parameters
384
+ ----------
385
+ A1 -> A6 : string
386
+ The property name of the coefficients in the source term model
387
+ x : string or float/int or array/list
388
+ The property name or numerical value or array for the main quantity
389
+ Notes
390
+ -----
391
+
392
+ """
393
+ if x=='':
394
+ X = _sp.ones(physics.Np)*_sp.nan
395
+ # length_X = _sp.size(x)
396
+ else:
397
+ if type(x)==str:
398
+ x = 'pore.'+x.split('.')[-1]
399
+ try: X = physics[x]
400
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
401
+ else:
402
+ X = _sp.array(x)
403
+
404
+ length_X = _sp.size(X)
405
+ if length_X!=physics.Np:
406
+ if length_X==1:
407
+ X = X*_sp.ones(physics.Np)
408
+ elif length_X>=phase.Np:
409
+ X = X[physics.map_pores()]
410
+ else: raise Exception('Wrong size for the numerical array of x!')
411
+
412
+ if A1 == '': a1 = 1
413
+ else:
414
+ if type(A1)==str:
415
+ A1 = 'pore.'+A1.split('.')[-1]
416
+ try: a1 = physics[A1]
417
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
418
+ else: raise Exception('A1 can be only string!')
419
+
420
+ if A2 == '': a2 = 0
421
+ else:
422
+ if type(A2)==str:
423
+ A2 = 'pore.'+A2.split('.')[-1]
424
+ try: a2 = physics[A2]
425
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
426
+ else: raise Exception('A2 can be only string!')
427
+
428
+ if A3 == '': a3 = 0
429
+ else:
430
+ if type(A3)==str:
431
+ A3 = 'pore.'+A3.split('.')[-1]
432
+ try: a3 = physics[A3]
433
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A3+'!')
434
+ else: raise Exception('A3 can be only string!')
435
+
436
+
437
+ if A4 == '': a4 = 0
438
+ else:
439
+ if type(A4)==str:
440
+ A4 = 'pore.'+A4.split('.')[-1]
441
+ try: a4 = physics[A4]
442
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A4+'!')
443
+ else: raise Exception('A4 can be only string!')
444
+
445
+ if A5 == '': a5 = 0
446
+ else:
447
+ if type(A5)==str:
448
+ A5 = 'pore.'+A5.split('.')[-1]
449
+ try: a5 = physics[A5]
450
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A5+'!')
451
+ else: raise Exception('A5 can be only string!')
452
+
453
+ if A6 == '': a6 = 0
454
+ else:
455
+ if type(A6)==str:
456
+ A6 = 'pore.'+A6.split('.')[-1]
457
+ try: a6 = physics[A6]
458
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A6+'!')
459
+ else: raise Exception('A6 can be only string!')
460
+
461
+ if return_rate:
462
+ return(a1*_sp.log(a3*X**a4 +a5)/_sp.log(a2)+a6)
463
+ else:
464
+ S1 = a1*a3*a4*X**(a4-1)/(_sp.log(a2)*(a3*X**a4+a5))
465
+ S2 = a1*_sp.log(a3*X**a4+a5)/_sp.log(a2)+a6-a1*a3*a4*X**a4/(_sp.log(a2)*(a3*X**a4+a5))
466
+ return(_sp.vstack((S1,S2)).T)
467
+
468
+
469
+ def natural_logarithm(physics,
470
+ phase,
471
+ A1='',
472
+ A2='',
473
+ A3='',
474
+ A4='',
475
+ A5='',
476
+ x='',
477
+ return_rate=True,
478
+ **kwargs):
479
+ r"""
480
+ For the following source term:
481
+ .. math::
482
+ r = A_{1} Ln( A_{2} x^{ A_{3} }+ A_{4})+ A_{5}
483
+ If return_rate is True, it returns the value of source term for the provided x in each pore.
484
+ If return_rate is False, it calculates the slope and intercept for the following linear form :
485
+ .. math::
486
+ r = S_{1} x + S_{2}
487
+
488
+ Parameters
489
+ ----------
490
+ A1 -> A5 : string
491
+ The property name of the coefficients in the source term model
492
+ x : string or float/int or array/list
493
+ The property name or numerical value or array for the main quantity
494
+ Notes
495
+ -----
496
+
497
+ """
498
+ if x=='':
499
+ X = _sp.ones(physics.Np)*_sp.nan
500
+ # length_X = _sp.size(x)
501
+ else:
502
+ if type(x)==str:
503
+ x = 'pore.'+x.split('.')[-1]
504
+ try: X = physics[x]
505
+ except: raise Exception(physics.name+' does not have the pore property :'+x+'!')
506
+ else:
507
+ X = _sp.array(x)
508
+
509
+ length_X = _sp.size(X)
510
+ if length_X!=physics.Np:
511
+ if length_X==1:
512
+ X = X*_sp.ones(physics.Np)
513
+ elif length_X>=phase.Np:
514
+ X = X[physics.map_pores()]
515
+ else: raise Exception('Wrong size for the numerical array of x!')
516
+
517
+ if A1 == '': a1 = 1
518
+ else:
519
+ if type(A1)==str:
520
+ A1 = 'pore.'+A1.split('.')[-1]
521
+ try: a1 = physics[A1]
522
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A1+'!')
523
+ else: raise Exception('A1 can be only string!')
524
+
525
+ if A2 == '': a2 = 0
526
+ else:
527
+ if type(A2)==str:
528
+ A2 = 'pore.'+A2.split('.')[-1]
529
+ try: a2 = physics[A2]
530
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A2+'!')
531
+ else: raise Exception('A2 can be only string!')
532
+
533
+ if A3 == '': a3 = 0
534
+ else:
535
+ if type(A3)==str:
536
+ A3 = 'pore.'+A3.split('.')[-1]
537
+ try: a3 = physics[A3]
538
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A3+'!')
539
+ else: raise Exception('A3 can be only string!')
540
+
541
+
542
+ if A4 == '': a4 = 0
543
+ else:
544
+ if type(A4)==str:
545
+ A4 = 'pore.'+A4.split('.')[-1]
546
+ try: a4 = physics[A4]
547
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A4+'!')
548
+ else: raise Exception('A4 can be only string!')
549
+
550
+ if A5 == '': a5 = 0
551
+ else:
552
+ if type(A5)==str:
553
+ A5 = 'pore.'+A5.split('.')[-1]
554
+ try: a5 = physics[A5]
555
+ except: raise Exception(physics.name+'/'+phase.name+' does not have the pore property :'+A5+'!')
556
+ else: raise Exception('A5 can be only string!')
557
+
558
+
559
+ if return_rate:
560
+ return(a1*_sp.log(a2*X**a3 +a4)+a5)
561
+ else:
562
+ S1 = a1*a2*a3*X**(a3-1)/(a2*X**a3+a4)
563
+ S2 = a1*_sp.log(a2*X**a3+a4)+a5-a1*a2*a3*X**a3/(a2*X**a3+a4)
564
+ return(_sp.vstack((S1,S2)).T)
@@ -0,0 +1,76 @@
1
+ r"""
2
+ ===============================================================================
3
+ Submodule -- hydraulic_conductance
4
+ ===============================================================================
5
+
6
+ """
7
+
8
+ import scipy as _sp
9
+ import OpenPNM.Utilities.misc as misc
10
+
11
+ def hagen_poiseuille(physics,
12
+ phase,
13
+ network,
14
+ pore_diameter='pore.diameter',
15
+ pore_viscosity='pore.viscosity',
16
+ throat_length='throat.length',
17
+ throat_diameter='throat.diameter',
18
+ calc_pore_len=True,
19
+ **kwargs):
20
+ r"""
21
+ Calculates the hydraulic conductivity of throat assuming cylindrical
22
+ geometry using the Hagen-Poiseuille model
23
+
24
+ Parameters
25
+ ----------
26
+ network : OpenPNM Network Object
27
+
28
+ phase : OpenPNM Phase Object
29
+
30
+ Notes
31
+ -----
32
+ (1) This function requires that all the necessary phase properties already
33
+ be calculated.
34
+
35
+ (2) This function calculates the specified property for the *entire*
36
+ network then extracts the values for the appropriate throats at the end.
37
+
38
+ """
39
+ #Get Nt-by-2 list of pores connected to each throat
40
+ Ps = network['throat.conns']
41
+ #Get properties in every pore in the network
42
+ mup = phase[pore_viscosity]
43
+ mut = phase.interpolate_data(mup)
44
+ pdia = network[pore_diameter]
45
+ if calc_pore_len:
46
+ lengths = misc.conduit_lengths(network,mode='centroid')
47
+ plen1 = lengths[:,0]
48
+ plen2 = lengths[:,2]
49
+ else:
50
+ plen1 = (0.5*pdia[Ps[:,0]])
51
+ plen2 = (0.5*pdia[Ps[:,1]])
52
+ #remove any non-positive lengths
53
+ plen1[plen1<=0]=1e-12
54
+ plen2[plen2<=0]=1e-12
55
+ #Find g for half of pore 1
56
+ gp1 = _sp.pi*(pdia[Ps[:,0]])**4/(128*plen1*mut)
57
+ gp1[_sp.isnan(gp1)] = _sp.inf
58
+ gp1[~(gp1>0)] = _sp.inf #Set 0 conductance pores (boundaries) to inf
59
+
60
+ #Find g for half of pore 2
61
+ #gp2 = 2.28*(pdia[pores[:,1]]/2)**4/(pdia[pores[:,1]]*mut)
62
+ gp2 = _sp.pi*(pdia[Ps[:,1]])**4/(128*plen2*mut)
63
+ gp2[_sp.isnan(gp2)] = _sp.inf
64
+ gp2[~(gp2>0)] = _sp.inf #Set 0 conductance pores (boundaries) to inf
65
+ #Find g for full throat
66
+ tdia = network[throat_diameter]
67
+ tlen = network[throat_length]
68
+ #remove any non-positive lengths
69
+ tlen[tlen<=0] = 1e-12
70
+ gt = _sp.pi*(tdia)**4/(128*tlen*mut)
71
+ gt[~(gt>0)] = _sp.inf #Set 0 conductance pores (boundaries) to inf
72
+ value = (1/gt + 1/gp1 + 1/gp2)**(-1)
73
+ value = value[phase.throats(physics.name)]
74
+ return value
75
+
76
+