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,369 @@
1
+ import scipy as _sp
2
+ import matplotlib.pylab as _plt
3
+
4
+ def profiles(network,
5
+ fig=None,
6
+ values=None,
7
+ bins=[10,10,10]):
8
+ r'''
9
+ Compute the profiles for the property of interest and plots it in all
10
+ three dimensions
11
+
12
+ Parameters
13
+ ----------
14
+ network : OpenPNM Network object
15
+
16
+ values : array_like, optional
17
+ The pore property values to be plotted as a profile
18
+
19
+ bins : int or list of ints, optional
20
+ The number of bins to divide the domain into for averaging.
21
+
22
+ Notes
23
+ -----
24
+ Either propname or values can be sent, but not both
25
+
26
+ '''
27
+ if fig is None:
28
+ fig = _plt.figure()
29
+ ax1 = fig.add_subplot(131)
30
+ ax2 = fig.add_subplot(132)
31
+ ax3 = fig.add_subplot(133)
32
+ ax = [ax1,ax2,ax3]
33
+ xlab = ['x coordinate','y_coordinate','z_coordinate']
34
+ for n in [0,1,2]:
35
+ n_min, n_max = [_sp.amin(network['pore.coords'][:,n]), _sp.amax(network['pore.coords'][:,n])]
36
+ steps = _sp.linspace(n_min,n_max,bins[n]+1,endpoint=True)
37
+ vals = _sp.zeros_like(steps)
38
+ for i in range(0,len(steps)-1):
39
+ temp = (network['pore.coords'][:,n] > steps[i])*(network['pore.coords'][:,n] <= steps[i+1])
40
+ vals[i] = _sp.mean(values[temp])
41
+ yaxis = vals[:-1]
42
+ xaxis = (steps[:-1] + (steps[1]-steps[0])/2)/n_max
43
+ ax[n].plot(xaxis,yaxis,'bo-')
44
+ ax[n].set_xlabel(xlab[n])
45
+ ax[n].set_ylabel('Slice Value')
46
+ fig.show()
47
+
48
+ def porosity_profile(network,
49
+ fig=None, axis=2):
50
+
51
+ r'''
52
+ Compute and plot the porosity profile in all three dimensions
53
+
54
+ Parameters
55
+ ----------
56
+ network : OpenPNM Network object
57
+ axis : integer type 0 for x-axis, 1 for y-axis, 2 for z-axis
58
+
59
+ Notes
60
+ -----
61
+ the area of the porous medium at any position is calculated from the
62
+ maximum pore coordinates in each direction
63
+
64
+ '''
65
+ if fig is None:
66
+ fig = _plt.figure()
67
+ L_x = _sp.amax(network['pore.coords'][:,0]) + _sp.mean(((21/88.0)*network['pore.volume'])**(1/3.0))
68
+ L_y = _sp.amax(network['pore.coords'][:,1]) + _sp.mean(((21/88.0)*network['pore.volume'])**(1/3.0))
69
+ L_z = _sp.amax(network['pore.coords'][:,2]) + _sp.mean(((21/88.0)*network['pore.volume'])**(1/3.0))
70
+ if axis is 0:
71
+ xlab = 'x-direction'
72
+ area = L_y*L_z
73
+ elif axis is 1:
74
+ xlab = 'y-direction'
75
+ area = L_x*L_z
76
+ else:
77
+ axis = 2
78
+ xlab = 'z-direction'
79
+ area = L_x*L_y
80
+ n_max = _sp.amax(network['pore.coords'][:,axis]) + _sp.mean(((21/88.0)*network['pore.volume'])**(1/3.0))
81
+ steps = _sp.linspace(0,n_max,100,endpoint=True)
82
+ vals = _sp.zeros_like(steps)
83
+ p_area = _sp.zeros_like(steps)
84
+ t_area = _sp.zeros_like(steps)
85
+
86
+ rp = ((21/88.0)*network['pore.volume'])**(1/3.0)
87
+ p_upper = network['pore.coords'][:,axis] + rp
88
+ p_lower = network['pore.coords'][:,axis] - rp
89
+ TC1 = network['throat.conns'][:,0]
90
+ TC2 = network['throat.conns'][:,1]
91
+ t_upper = network['pore.coords'][:,axis][TC1]
92
+ t_lower = network['pore.coords'][:,axis][TC2]
93
+
94
+ for i in range(0,len(steps)):
95
+ p_temp = (p_upper > steps[i])*(p_lower < steps[i])
96
+ t_temp = (t_upper > steps[i])*(t_lower < steps[i])
97
+ p_area[i] = sum((22/7.0)*(rp[p_temp]**2 - (network['pore.coords'][:,axis][p_temp]-steps[i])**2))
98
+ t_area[i] = sum(network['throat.area'][t_temp])
99
+ vals[i] = (p_area[i]+t_area[i])/area
100
+ yaxis = vals
101
+ xaxis = steps/n_max
102
+ _plt.plot(xaxis,yaxis,'bo-')
103
+ _plt.xlabel(xlab)
104
+ _plt.ylabel('Porosity')
105
+ fig.show()
106
+
107
+ def saturation_profile(network, phase, fig=None, axis=2):
108
+
109
+ r'''
110
+ Compute and plot the saturation profile in all three dimensions
111
+
112
+ Parameters
113
+ ----------
114
+ network : OpenPNM Network object
115
+ phase : the invading or defending phase to plot its saturation distribution
116
+ axis : integer type 0 for x-axis, 1 for y-axis, 2 for z-axis
117
+
118
+ '''
119
+ if fig is None:
120
+ fig = _plt.figure()
121
+ if phase is None:
122
+ raise Exception('The phase for saturation profile plot is not given' )
123
+ if axis is 0:
124
+ xlab = 'x-direction'
125
+ elif axis is 1:
126
+ xlab = 'y-direction'
127
+ else:
128
+ axis = 2
129
+ xlab = 'z-direction'
130
+ n_max = _sp.amax(network['pore.coords'][:,axis]) + _sp.mean(((21/88.0)*network['pore.volume'])**(1/3.0))
131
+ steps = _sp.linspace(0,n_max,100,endpoint=True)
132
+ p_area = _sp.zeros_like(steps)
133
+ op_area = _sp.zeros_like(steps)
134
+ t_area = _sp.zeros_like(steps)
135
+ ot_area = _sp.zeros_like(steps)
136
+ vals = _sp.zeros_like(steps)
137
+ PO = phase['pore.occupancy']
138
+ TO = phase['throat.occupancy']
139
+ rp = ((21/88.0)*network['pore.volume'])**(1/3.0)
140
+ p_upper = network['pore.coords'][:,axis] + rp
141
+ p_lower = network['pore.coords'][:,axis] - rp
142
+
143
+ TC1 = network['throat.conns'][:,0]
144
+ TC2 = network['throat.conns'][:,1]
145
+ t_upper = network['pore.coords'][:,axis][TC1]
146
+ t_lower = network['pore.coords'][:,axis][TC2]
147
+
148
+ for i in range(0,len(steps)):
149
+ op_temp = (p_upper > steps[i])*(p_lower < steps[i])*PO
150
+ ot_temp = (t_upper > steps[i])*(t_lower < steps[i])*TO
151
+ op_temp = _sp.array(op_temp, dtype='bool')
152
+ ot_temp = _sp.array(op_temp, dtype='bool')
153
+ p_temp = (p_upper > steps[i])*(p_lower < steps[i])
154
+ t_temp = (t_upper > steps[i])*(t_lower < steps[i])
155
+ op_area[i] = sum((22/7.0)*(rp[op_temp]**2 - (network['pore.coords'][:,axis][op_temp]-steps[i])**2))
156
+ ot_area[i] = sum(network['throat.area'][ot_temp])
157
+ p_area[i] = sum((22/7.0)*(rp[p_temp]**2 - (network['pore.coords'][:,axis][p_temp]-steps[i])**2))
158
+ t_area[i] = sum(network['throat.area'][t_temp])
159
+ vals[i] = (op_area[i]+ot_area[i])/(p_area[i]+t_area[i])
160
+ if vals[i]>1:
161
+ vals[i]=1.
162
+ if _sp.isnan(vals[i]):
163
+ vals[i]=1.
164
+
165
+ if vals[-1]==1.:
166
+ vals = vals[::-1]
167
+
168
+ yaxis = vals
169
+ xaxis = steps/n_max
170
+ _plt.plot(xaxis,yaxis,'bo-')
171
+ _plt.xlabel(xlab)
172
+ _plt.ylabel('Saturation')
173
+ fig.show()
174
+
175
+ def distributions(net,
176
+ fig = None,
177
+ throat_diameter='throat.diameter',
178
+ pore_diameter='pore.diameter',
179
+ throat_length='throat.length',
180
+ exclude_boundaries=True,
181
+ geom_list=None):
182
+ r"""
183
+ Plot a montage of key network size distribution histograms
184
+
185
+ Parameters
186
+ ----------
187
+ net : OpenPNM Network Object
188
+ The network for which the graphs are desired
189
+
190
+ """
191
+ if fig is None:
192
+ fig = _plt.figure()
193
+
194
+ fig.subplots_adjust(hspace = 0.4)
195
+ fig.subplots_adjust(wspace = 0.4)
196
+
197
+ if geom_list is not None:
198
+ include_pores = [False]*net.num_pores()
199
+ include_throats = [False]*net.num_throats()
200
+ for geom in geom_list:
201
+ include_pores = include_pores | net["pore."+geom]
202
+ include_throats = include_throats | net["throat."+geom]
203
+ else:
204
+ include_pores = net["pore.all"]
205
+ include_throats = net["throat.all"]
206
+ pores = net.pores()[include_pores]
207
+ throats = net.throats()[include_throats]
208
+
209
+
210
+ ax1 = fig.add_subplot(221)
211
+ ax1.hist(net[pore_diameter][pores],25,facecolor='green')
212
+ ax1.set_xlabel('Pore Diameter')
213
+ ax1.set_ylabel('Frequency')
214
+ ax1.ticklabel_format(style='sci', axis='x', scilimits=(0,0))
215
+
216
+ ax2 = fig.add_subplot(222)
217
+ x = net.num_neighbors(pores,flatten=False)
218
+ ax2.hist(x,25,facecolor='yellow')
219
+ ax2.set_xlabel('Coordination Number')
220
+ ax2.set_ylabel('Frequency')
221
+
222
+ ax3 = fig.add_subplot(223)
223
+ ax3.hist(net[throat_diameter][throats],25,facecolor='blue')
224
+ ax3.set_xlabel('Throat Diameter')
225
+ ax3.set_ylabel('Frequency')
226
+ ax3.ticklabel_format(style='sci', axis='x', scilimits=(0,0))
227
+
228
+ ax4 = fig.add_subplot(224)
229
+ ax4.hist(net[throat_length][throats],25,facecolor='red')
230
+ ax4.set_xlabel('Throat Length')
231
+ ax4.set_ylabel('Frequency')
232
+ ax4.ticklabel_format(style='sci', axis='x', scilimits=(0,0))
233
+ fig.show()
234
+
235
+ def pore_size_distribution(network, fig=None,):
236
+
237
+ r'''
238
+ Plot the pore and throat size distribution which is the accumulated
239
+ volume vs. the diameter in a semilog plot
240
+
241
+ Parameters
242
+ ----------
243
+ network : OpenPNM Network object
244
+
245
+ '''
246
+ if fig is None:
247
+ fig = _plt.figure()
248
+ dp = network['pore.diameter']
249
+ Vp = network['pore.volume']
250
+ dt = network['throat.diameter']
251
+ Vt = network['throat.volume']
252
+ dmax = max(max(dp),max(dt))
253
+ steps = _sp.linspace(0,dmax,100,endpoint=True)
254
+ vals = _sp.zeros_like(steps)
255
+ for i in range(0,len(steps)-1):
256
+ temp1 = dp > steps[i]
257
+ temp2 = dt > steps[i]
258
+ vals[i] = sum(Vp[temp1]) + sum(Vt[temp2])
259
+ yaxis = vals
260
+ xaxis = steps
261
+ _plt.semilogx(xaxis,yaxis,'b.-')
262
+ _plt.xlabel('Pore & Throat Diameter (m)')
263
+ _plt.ylabel('Cumulative Volume (m^3)')
264
+ fig.show()
265
+
266
+ def drainage_curves(inv_alg,
267
+ fig=None,
268
+ Pc='inv_Pc',
269
+ sat='inv_sat',
270
+ seq='inv_seq',
271
+ timing=None):
272
+ r"""
273
+ Plot a montage of key saturation plots
274
+
275
+ Parameters
276
+ ----------
277
+ inv_alg : OpenPNM Algorithm Object
278
+ The invasion algorithm for which the graphs are desired
279
+
280
+ timing : string
281
+ if algorithm keeps track of simulated time, insert string here.
282
+
283
+ Examples
284
+ --------
285
+ >>> import OpenPNM
286
+ >>> pn = OpenPNM.Network.TestNet()
287
+ >>> geo = OpenPNM.Geometry.TestGeometry(network=pn,pores=pn.pores(),throats=pn.throats())
288
+ >>> phase1 = OpenPNM.Phases.TestPhase(network=pn)
289
+ >>> phase2 = OpenPNM.Phases.TestPhase(network=pn)
290
+ >>> phys1 = OpenPNM.Physics.TestPhysics(network=pn, phase=phase1,pores=pn.pores(),throats=pn.throats())
291
+ >>> phys2 = OpenPNM.Physics.TestPhysics(network=pn, phase=phase2,pores=pn.pores(),throats=pn.throats())
292
+ >>> IP = OpenPNM.Algorithms.InvasionPercolationTimed(network=pn)
293
+ >>> IP.run(invading_phase=phase1, defending_phase=phase2, inlets=pn.pores('top'), outlets=pn.pores('bottom'))
294
+ IP algorithm at 0 % completion at 0.0 seconds
295
+ IP algorithm at 20 % completion at 0.0 seconds
296
+ IP algorithm at 40 % completion at 0.0 seconds
297
+ IP algorithm at 60 % completion at 0.0 seconds
298
+ IP algorithm at 100% completion at 0.0 seconds
299
+ >>> OpenPNM.Postprocessing.Plots.drainage_curves(IP,timing='inv_time')
300
+ """
301
+ inv_throats = inv_alg.toindices(inv_alg['throat.'+seq]>0)
302
+ sort_seq = _sp.argsort(inv_alg['throat.'+seq][inv_throats])
303
+ inv_throats = inv_throats[sort_seq]
304
+
305
+ if fig is None:
306
+ fig = _plt.figure(num=1, figsize=(13, 10), dpi=80, facecolor='w', edgecolor='k')
307
+ ax1 = fig.add_subplot(231) #left
308
+ ax2 = fig.add_subplot(232) #middle
309
+ ax3 = fig.add_subplot(233) #right
310
+ ax4 = fig.add_subplot(234) #left
311
+ ax5 = fig.add_subplot(235) #middle
312
+ ax6 = fig.add_subplot(236) #right
313
+
314
+ ax1.plot(inv_alg['throat.'+Pc][inv_throats],inv_alg['throat.'+sat][inv_throats])
315
+ ax1.set_xlabel('Capillary Pressure (Pa)')
316
+ ax1.set_ylabel('Saturation')
317
+ ax1.set_ylim([0,1])
318
+ ax1.set_xlim([0.99*min(inv_alg['throat.'+Pc][inv_throats]),1.01*max(inv_alg['throat.'+Pc][inv_throats])])
319
+
320
+ ax2.plot(inv_alg['throat.'+seq][inv_throats],inv_alg['throat.'+sat][inv_throats])
321
+ ax2.set_xlabel('Simulation Step')
322
+ ax2.set_ylabel('Saturation')
323
+ ax2.set_ylim([0,1])
324
+ ax2.set_xlim([0,1.01*max(inv_alg['throat.'+seq][inv_throats])])
325
+
326
+ if timing==None:
327
+ ax3.plot(0,0)
328
+ ax3.set_xlabel('No Time Data Available')
329
+ else:
330
+ ax3.plot(inv_alg['throat.'+timing][inv_throats],inv_alg['throat.'+sat][inv_throats])
331
+ ax3.set_xlabel('Time (s)')
332
+ ax3.set_ylabel('Saturation')
333
+ ax3.set_ylim([0,1])
334
+ ax3.set_xlim([0,1.01*max(inv_alg['throat.'+timing][inv_throats])])
335
+
336
+ ax4.plot(inv_alg['throat.'+sat][inv_throats],inv_alg['throat.'+Pc][inv_throats])
337
+ ax4.set_ylabel('Capillary Pressure (Pa)')
338
+ ax4.set_xlabel('Saturation')
339
+ ax4.set_xlim([0,1])
340
+ ax4.set_ylim([0.99*min(inv_alg['throat.'+Pc][inv_throats]),1.01*max(inv_alg['throat.'+Pc][inv_throats])])
341
+
342
+ ax5.plot(inv_alg['throat.'+seq][inv_throats],inv_alg['throat.'+Pc][inv_throats])
343
+ ax5.set_xlabel('Simulation Step')
344
+ ax5.set_ylabel('Capillary Pressure (Pa)')
345
+ ax5.set_ylim([0.99*min(inv_alg['throat.'+Pc][inv_throats]),1.01*max(inv_alg['throat.'+Pc][inv_throats])])
346
+ ax5.set_xlim([0,1.01*max(inv_alg['throat.'+seq][inv_throats])])
347
+
348
+ if timing==None:
349
+ ax6.plot(0,0)
350
+ ax6.set_xlabel('No Time Data Available')
351
+ else:
352
+ ax6.plot(inv_alg['throat.'+timing][inv_throats],inv_alg['throat.'+Pc][inv_throats])
353
+ ax6.set_xlabel('Time (s)')
354
+ ax6.set_ylabel('Capillary Pressure (Pa)')
355
+ ax6.set_ylim([0.99*min(inv_alg['throat.'+Pc][inv_throats]),1.01*max(inv_alg['throat.'+Pc][inv_throats])])
356
+ ax6.set_xlim([0,1.01*max(inv_alg['throat.'+timing][inv_throats])])
357
+
358
+ fig.subplots_adjust(left=0.08, right=0.99, top=0.95, bottom=0.1)
359
+ ax1.grid(True)
360
+ ax2.grid(True)
361
+ ax3.grid(True)
362
+ ax4.grid(True)
363
+ ax5.grid(True)
364
+ ax6.grid(True)
365
+ fig.show()
366
+
367
+ if __name__ == '__main__':
368
+ import doctest
369
+ doctest.testmod(verbose=True)
@@ -0,0 +1,10 @@
1
+ r"""
2
+ ###############################################################################
3
+ :mod:`OpenPNM.Postprocessing` -- Analysis, Plotting and some Visualization
4
+ ###############################################################################
5
+
6
+
7
+ """
8
+
9
+ from . import Plots
10
+ from . import Graphics
@@ -0,0 +1,277 @@
1
+ from OpenPNM.Utilities import misc
2
+ import scipy as _sp
3
+ import numpy as _np
4
+ import os as _os
5
+ import pickle as _pickle
6
+ from xml.etree import ElementTree as _ET
7
+
8
+
9
+
10
+ class VTK():
11
+ r"""
12
+ Class for writing a Vtp file to be read by ParaView
13
+
14
+ """
15
+
16
+ _TEMPLATE = '''
17
+ <?xml version="1.0" ?>
18
+ <VTKFile byte_order="LittleEndian" type="PolyData" version="0.1">
19
+ <PolyData>
20
+ <Piece NumberOfLines="0" NumberOfPoints="0">
21
+ <Points>
22
+ </Points>
23
+ <Lines>
24
+ </Lines>
25
+ <PointData>
26
+ </PointData>
27
+ <CellData>
28
+ </CellData>
29
+ </Piece>
30
+ </PolyData>
31
+ </VTKFile>
32
+ '''.strip()
33
+
34
+
35
+ def __init__(self,**kwargs):
36
+ r"""
37
+ Initialize
38
+ """
39
+ super().__init__(**kwargs)
40
+
41
+ @staticmethod
42
+ def save(network,filename='',phases=[]):
43
+ r'''
44
+ Save network and phase data to a single vtp file for visualizing in
45
+ Paraview
46
+
47
+ Parameters
48
+ ----------
49
+ network : OpenPNM Network Object
50
+ The Network containing the data to be written
51
+
52
+ filename : string, optional
53
+ Filename to write data. If no name is given the file is named after
54
+ ther network
55
+
56
+ phases : list, optional
57
+ A list contain OpenPNM Phase object(s) containing data to be written
58
+
59
+ Examples
60
+ --------
61
+ >>> import OpenPNM
62
+ >>> pn = OpenPNM.Network.Cubic(shape=[3,3,3])
63
+ >>> geo = OpenPNM.Geometry.Stick_and_Ball(network=pn,pores=pn.pores(),throats=pn.throats())
64
+ >>> air = OpenPNM.Phases.Air(network=pn)
65
+ >>> phys = OpenPNM.Physics.Standard(network=pn,phase=air,pores=pn.pores(),throats=pn.throats())
66
+
67
+ >>> import OpenPNM.Utilities.IO as io
68
+ >>> io.VTK.save(pn,'test_pn.vtp',[air])
69
+
70
+ >>> # Delete the new file
71
+ >>> import os
72
+ >>> os.remove('test_pn.vtp')
73
+ '''
74
+
75
+ if filename == '':
76
+ filename = network.name
77
+ filename = filename.split('.')[0]+'.vtp'
78
+
79
+ root = _ET.fromstring(VTK._TEMPLATE)
80
+ objs = []
81
+ if type(phases) != list:
82
+ phases = [phases]
83
+ for phase in phases:
84
+ objs.append(phase)
85
+ objs.append(network)
86
+ am = misc.amalgamate_data(objs=objs)
87
+ key_list = list(sorted(am.keys()))
88
+ points = network['pore.coords']
89
+ pairs = network['throat.conns']
90
+
91
+ num_points = len(points)
92
+ num_throats = len(pairs)
93
+
94
+ piece_node = root.find('PolyData').find('Piece')
95
+ piece_node.set("NumberOfPoints", str(num_points))
96
+ piece_node.set("NumberOfLines", str(num_throats))
97
+
98
+ points_node = piece_node.find('Points')
99
+ coords = VTK._array_to_element("coords", points.T.ravel('F'), n=3)
100
+ points_node.append(coords)
101
+
102
+ lines_node = piece_node.find('Lines')
103
+ connectivity = VTK._array_to_element("connectivity", pairs)
104
+ lines_node.append(connectivity)
105
+ offsets = VTK._array_to_element("offsets", 2*_np.arange(len(pairs))+2)
106
+ lines_node.append(offsets)
107
+
108
+ point_data_node = piece_node.find('PointData')
109
+ for key in key_list:
110
+ array = am[key]
111
+ if array.dtype == _np.bool: array = array.astype(int)
112
+ if array.size != num_points: continue
113
+ element = VTK._array_to_element(key, array)
114
+ point_data_node.append(element)
115
+
116
+ cell_data_node = piece_node.find('CellData')
117
+ for key in key_list:
118
+ array = am[key]
119
+ if array.dtype == _np.bool: array = array.astype(int)
120
+ if array.size != num_throats: continue
121
+ element = VTK._array_to_element(key, array)
122
+ cell_data_node.append(element)
123
+
124
+ tree = _ET.ElementTree(root)
125
+ tree.write(filename)
126
+
127
+ #Make pretty
128
+ with open(filename, "r+") as f:
129
+ string = f.read()
130
+ string = string.replace("</DataArray>", "</DataArray>\n\t\t\t")
131
+ f.seek(0)
132
+ # consider adding header: '<?xml version="1.0"?>\n'+
133
+ f.write(string)
134
+
135
+ @staticmethod
136
+ def load(filename):
137
+ r'''
138
+ Read in pore and throat data from a saved VTK file.
139
+
140
+ Notes
141
+ -----
142
+ This will NOT reproduce original simulation, since all models and object
143
+ relationships are lost. Use IO.Save and IO.Load for that.'''
144
+ network = OpenPNM.Network.GenericNetwork()
145
+ tree = _ET.parse(filename)
146
+ piece_node = tree.find('PolyData').find('Piece')
147
+
148
+ # extract connectivity
149
+ conn_element = piece_node.find('Lines').find('DataArray')
150
+ array = VTK._element_to_array(conn_element, 2)
151
+ network['throat.conns'] = array.T
152
+
153
+ for element in piece_node.find('PointData').iter('DataArray'):
154
+ key = element.get('Name')
155
+ array = VTK._element_to_array(element)
156
+ netname = key.split('.')[0]
157
+ propname = key.strip(netname+'.')
158
+ network[propname] = array
159
+
160
+ return network
161
+
162
+ @staticmethod
163
+ def _array_to_element(name, array, n=1):
164
+ dtype_map = {
165
+ 'int8' : 'Int8',
166
+ 'int16' : 'Int16',
167
+ 'int32' : 'Int32',
168
+ 'int64' : 'Int64',
169
+ 'uint8' : 'UInt8',
170
+ 'uint16' : 'UInt16',
171
+ 'uint32' : 'UInt32',
172
+ 'uint64' : 'UInt64',
173
+ 'float32': 'Float32',
174
+ 'float64': 'Float64',
175
+ 'str' : 'String',
176
+ }
177
+ element = _ET.Element('DataArray')
178
+ element.set("Name", name)
179
+ element.set("NumberOfComponents", str(n))
180
+ element.set("type", dtype_map[str(array.dtype)])
181
+ element.text = '\t'.join(map(str,array.ravel()))
182
+ return element
183
+
184
+ @staticmethod
185
+ def _element_to_array(element, n=1):
186
+ string = element.text
187
+ dtype = element.get("type")
188
+ array = _np.fromstring(string, sep='\t')
189
+ array = array.astype(dtype)
190
+ if n is not 1:
191
+ array = array.reshape(array.size//n, n)
192
+ return array
193
+
194
+ class MAT():
195
+ r'''
196
+ Class for reading and writing OpenPNM data to a Matlab 'mat' file
197
+ '''
198
+
199
+ def __init__(self,**kwargs):
200
+ r"""
201
+ Initialize
202
+ """
203
+ super().__init__(**kwargs)
204
+
205
+ @staticmethod
206
+ def save(network, filename='', phases=[]):
207
+ r"""
208
+ Write Network to a Mat file for exporting to Matlab. This method will be
209
+ enhanced in a future update, and it's functionality may change!
210
+
211
+ Parameters
212
+ ----------
213
+
214
+ network : OpenPNM Network Object
215
+
216
+ filename : string
217
+ Desired file name, defaults to network name if not given
218
+
219
+ phases : list of phase objects ([])
220
+ Phases that have properties we want to write to file
221
+
222
+ Examples
223
+ --------
224
+ >>> import OpenPNM
225
+ >>> pn = OpenPNM.Network.TestNet()
226
+ >>> geo = OpenPNM.Geometry.TestGeometry(network=pn,pores=pn.pores(),throats=pn.throats())
227
+ >>> air = OpenPNM.Phases.TestPhase()
228
+ >>> import OpenPNM.Utilities.IO as io
229
+ >>> io.MAT.save(network=pn,filename='test_pn.mat',phases=air)
230
+
231
+ >>> #Remove newly created file
232
+ >>> import os
233
+ >>> os.remove('test_pn.mat')
234
+
235
+ """
236
+ if filename == '':
237
+ filename = network.name
238
+ filename = filename.split('.')[0]+'.mat'
239
+
240
+ pnMatlab = {}
241
+ new = []
242
+ old = []
243
+ for keys in network.keys():
244
+ old.append(keys)
245
+ new.append(keys.replace('.','_'))
246
+
247
+ for i in range(len(network)):
248
+ pnMatlab[new[i]] = network[old[i]]
249
+
250
+ if type(phases) != list:
251
+ phases = [phases]
252
+ if len(phases) != 0:
253
+ for j in range(len(phases)):
254
+ new = []
255
+ old = []
256
+
257
+ for keys in phases[j].keys():
258
+ old.append(keys)
259
+ new.append(phases[j].name+'_'+keys.replace('.','_'))
260
+
261
+ for i in range(len(phases[j])):
262
+ pnMatlab[new[i]] = phases[j][old[i]]
263
+
264
+ _sp.io.savemat(file_name=filename,mdict=pnMatlab)
265
+
266
+ @staticmethod
267
+ def load():
268
+ r'''
269
+ This method is not implemented yet.
270
+ '''
271
+ raise NotImplemented()
272
+
273
+
274
+ if __name__ == '__main__':
275
+ import doctest
276
+ doctest.testmod(verbose=True)
277
+
@@ -0,0 +1,17 @@
1
+ import string, random
2
+ import OpenPNM.Phases
3
+
4
+ def solve_linear(pn, ics):
5
+ # circumvent bug with naming by creating random names
6
+ name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
7
+ pseudo = OpenPNM.Phases.GenericPhase(network=pn, name=name)
8
+ pseudo['throat.electrical_conductance']=1
9
+
10
+ alg = OpenPNM.Algorithms.OhmicConduction(network=pn)
11
+ alg['pore.BCval']=ics
12
+ alg['pore.Dirichlet']=ics!=0
13
+ alg.run(active_phase=pseudo)
14
+ alg.return_results()
15
+
16
+ out = pseudo['pore.voltage']
17
+ return out
@@ -0,0 +1,16 @@
1
+ r"""
2
+ ###############################################################################
3
+ :mod:`OpenPNM.Utilities` -- IO, geometry tools and other functions
4
+ ###############################################################################
5
+
6
+ .. automodule:: OpenPNM.Utilities.IO
7
+ :members:
8
+ :undoc-members:
9
+ :show-inheritance:
10
+
11
+ """
12
+
13
+ from . import IO
14
+ from . import transformations
15
+ from . import misc
16
+ from . import vertexops