photosurfactant 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,288 @@
1
+ #! /usr/bin/env python
2
+ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
3
+
4
+ import numpy as np
5
+ from matplotlib import colors
6
+
7
+ from photosurfactant.parameters import Parameters, PlottingParameters
8
+ from photosurfactant.semi_analytic.leading_order import LeadingOrder
9
+ from photosurfactant.semi_analytic.limits import HighIntensity, LowIntensity
10
+ from photosurfactant.utils.arg_parser import (
11
+ leading_order_parser,
12
+ parameter_parser,
13
+ plot_parser,
14
+ )
15
+
16
+ # TODO: Reduced figures at 3 magnitudes?
17
+
18
+
19
+ def plot_bulk_concentration(
20
+ intensities, default_params, plot_params, root_index, log=False
21
+ ):
22
+ """Plot the bulk concentrations for varying intensity."""
23
+
24
+ default_intensity = default_params.Da_tr
25
+
26
+ # Figure setup
27
+ plt = plot_params.plt
28
+ fig, axs = plt.subplots(2, 1, figsize=(9, 6), constrained_layout=True)
29
+
30
+ cmap = plt.cm.get_cmap("coolwarm")
31
+
32
+ if log:
33
+ norm = colors.LogNorm(
34
+ vmin=intensities[0] / np.sqrt(10), vmax=intensities[-1] * np.sqrt(10)
35
+ )
36
+ else:
37
+ norm = plt.Normalize(vmin=intensities[0], vmax=intensities[-1])
38
+
39
+ yy = np.linspace(0, 1, plot_params.grid_size)
40
+
41
+ # Plot concentrations for varying intensity
42
+ for intensity in intensities:
43
+ params = default_params.update(
44
+ Da_tr=default_params.Da_tr * intensity / default_intensity,
45
+ Da_ci=default_params.Da_ci * intensity / default_intensity,
46
+ )
47
+
48
+ # Solve leading order problem
49
+ leading = LeadingOrder(params, root_index)
50
+
51
+ # Plot bulk concentrations
52
+ axs[0].plot(yy, leading.c_tr(yy), color=cmap(norm(intensity)))
53
+ axs[1].plot(yy, leading.c_ci(yy), color=cmap(norm(intensity)))
54
+
55
+ # Highlight curves for unit intensity
56
+ params = default_params.copy()
57
+ leading = LeadingOrder(params, root_index)
58
+ axs[0].plot(yy, leading.c_tr(yy), color="k", linestyle=(0, (5, 10)))
59
+ axs[1].plot(yy, leading.c_ci(yy), color="k", linestyle=(0, (5, 10)))
60
+
61
+ # Tidy up figure
62
+ axs[0].set_xticklabels([])
63
+ axs[0].set_ylabel(r"$c_{\mathrm{tr}, 0}$")
64
+ axs[0].ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
65
+
66
+ axs[1].set_xlabel(r"$z$")
67
+ axs[1].set_ylabel(r"$c_{\mathrm{ci}, 0}$")
68
+ axs[1].ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
69
+
70
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
71
+ cbar = fig.colorbar(
72
+ sm, ax=axs.ravel().tolist(), label=r"Intensity ($Da_\mathrm{tr}$)"
73
+ )
74
+
75
+ # Annotate colorbar
76
+ cbar.ax.scatter(
77
+ np.mean(cbar.ax.set_xlim()) * np.ones_like(intensities),
78
+ intensities,
79
+ s=50,
80
+ facecolors="none",
81
+ edgecolors="k",
82
+ )
83
+
84
+ cbar.ax.scatter(
85
+ [np.mean(cbar.ax.set_xlim())],
86
+ [default_intensity],
87
+ s=60,
88
+ facecolors="k",
89
+ edgecolors="k",
90
+ marker="D",
91
+ )
92
+
93
+ if plot_params.save:
94
+ plt.savefig(
95
+ plot_params.path
96
+ + f"bulk_concentration{plot_params.label}.{plot_params.format}",
97
+ bbox_inches="tight",
98
+ )
99
+ else:
100
+ plt.show()
101
+
102
+
103
+ def plot_interfacial_concentration(
104
+ intensities, default_params, plot_params, root_index, log=False, limits=False
105
+ ):
106
+ """Plot surface excess for varying intensity."""
107
+ # Collect interfacial values for varying intensity
108
+ gamma_tr, gamma_ci = [], []
109
+ tension = []
110
+ default_intensity = default_params.Da_tr
111
+
112
+ for intensity in intensities:
113
+ params = default_params.update(
114
+ Da_tr=default_params.Da_tr * intensity / default_intensity,
115
+ Da_ci=default_params.Da_ci * intensity / default_intensity,
116
+ )
117
+
118
+ # Solve leading order problem
119
+ leading = LeadingOrder(params, root_index)
120
+
121
+ # Store values
122
+ gamma_tr.append(leading.Gamma_tr)
123
+ gamma_ci.append(leading.Gamma_ci)
124
+
125
+ tension.append(leading.gamma)
126
+
127
+ gamma_tr, gamma_ci = np.array(gamma_tr), np.array(gamma_ci)
128
+ tension = np.array(tension)
129
+
130
+ plt = plot_params.plt
131
+ fig, ax1 = plt.subplots(figsize=(8, 6))
132
+
133
+ # Plot surface excess
134
+ gamma_tr_plt = ax1.plot(
135
+ intensities, gamma_tr, "r--", label=r"$\Gamma_{\mathrm{tr}, 0}$"
136
+ )
137
+ gamma_ci_plt = ax1.plot(
138
+ intensities, gamma_ci, "b-.", label=r"$\Gamma_{\mathrm{ci}, 0}$"
139
+ )
140
+
141
+ # Plot limiting cases
142
+ if limits:
143
+ tan_length = int((3 / 8) * len(intensities))
144
+
145
+ small_dam = LowIntensity(params)
146
+ ax1.plot(
147
+ intensities[:tan_length],
148
+ small_dam.gamma_tr * np.ones_like(intensities[:tan_length]),
149
+ "r:",
150
+ )
151
+ ax1.plot(
152
+ intensities[:tan_length],
153
+ small_dam.gamma_ci * np.ones_like(intensities[:tan_length]),
154
+ "b:",
155
+ )
156
+
157
+ large_dam = HighIntensity(params)
158
+ ax1.plot(
159
+ intensities[-tan_length:],
160
+ large_dam.gamma_tr * np.ones_like(intensities[-tan_length:]),
161
+ "r:",
162
+ )
163
+ ax1.plot(
164
+ intensities[-tan_length:],
165
+ large_dam.gamma_ci * np.ones_like(intensities[-tan_length:]),
166
+ "b:",
167
+ )
168
+
169
+ # Set xscale
170
+ if log:
171
+ ax1.set_xscale("log")
172
+
173
+ ax1.set_xlabel(r"Intensity ($Da_\mathrm{tr}$)")
174
+ ax1.set_ylabel(
175
+ r"Surface Excess ($\Gamma_{\mathrm{tr}, 0}, \Gamma_{\mathrm{ci}, 0}$)"
176
+ )
177
+ ax1.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
178
+ ax1.grid()
179
+
180
+ ax2 = ax1.twinx()
181
+
182
+ # Plot surface tension
183
+ tension_plt = ax2.plot(
184
+ intensities,
185
+ tension,
186
+ "k-",
187
+ label=r"$\gamma_0$",
188
+ )
189
+ ax2.set_ylabel(r"$\gamma_0$")
190
+ ax2.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
191
+
192
+ # Annotate points at unit intensity
193
+ leading = LeadingOrder(default_params, root_index)
194
+ ax1.plot([default_intensity], [leading.Gamma_tr], color="r", marker="D")
195
+ ax1.plot([default_intensity], [leading.Gamma_ci], color="b", marker="D")
196
+ ax2.plot([default_intensity], [leading.gamma], color="k", marker="D")
197
+
198
+ # Merge legends
199
+ plots = tension_plt + gamma_tr_plt + gamma_ci_plt
200
+ labels = [plot.get_label() for plot in plots]
201
+ ax2.legend(plots, labels, loc="upper right")
202
+
203
+ if plot_params.save:
204
+ plt.savefig(
205
+ plot_params.path
206
+ + f"interfacial_concentration{plot_params.label}.{plot_params.format}",
207
+ bbox_inches="tight",
208
+ )
209
+ else:
210
+ plt.show()
211
+
212
+
213
+ def plot_leading_order(): # noqa: D103
214
+ parser = ArgumentParser(
215
+ description="Plot the leading order surfactant concentrations.",
216
+ formatter_class=ArgumentDefaultsHelpFormatter,
217
+ )
218
+ parameter_parser(parser)
219
+ plot_parser(parser)
220
+ leading_order_parser(parser)
221
+ parser.add_argument(
222
+ "--intensities",
223
+ type=float,
224
+ nargs="*",
225
+ default=[1.0],
226
+ help="Intensity factors to plot the concentration for. If count is greater "
227
+ "than one, plots for a range instead.",
228
+ )
229
+ parser.add_argument(
230
+ "--count",
231
+ type=int,
232
+ default=1,
233
+ help="The number of values to plot if using an intensity range.",
234
+ )
235
+ parser.add_argument(
236
+ "--interface",
237
+ action="store_true",
238
+ help="Plot the interfacial values.",
239
+ )
240
+ parser.add_argument(
241
+ "--limits",
242
+ action="store_true",
243
+ help="Plot the equilibrium states for small and large intensity.",
244
+ )
245
+ parser.add_argument(
246
+ "--log",
247
+ action="store_true",
248
+ help="Use a log scale.",
249
+ )
250
+ parser.add_argument(
251
+ "--gamma",
252
+ type=float,
253
+ default=1.0,
254
+ help="The stretching rate when using a range.",
255
+ )
256
+ args = parser.parse_args()
257
+
258
+ params = Parameters.from_dict(vars(args))
259
+ plot_params = PlottingParameters.from_dict(vars(args))
260
+ root_index = args.root_index
261
+ intensities = args.intensities
262
+
263
+ if args.count > 1:
264
+ if len(intensities) != 2:
265
+ raise ValueError("intensities must be of length 2 to plot a range.")
266
+
267
+ grid = abs(np.linspace(-1.0, 1.0, args.count)) ** args.gamma
268
+ grid[: args.count // 2] *= -1
269
+ intensities = grid * (intensities[1] - intensities[0]) / 2 + np.mean(
270
+ intensities
271
+ )
272
+
273
+ if args.log:
274
+ intensities = 10.0 ** np.array(intensities)
275
+
276
+ if args.interface:
277
+ plot_interfacial_concentration(
278
+ intensities,
279
+ params,
280
+ plot_params,
281
+ root_index,
282
+ log=args.log,
283
+ limits=args.limits,
284
+ )
285
+ else:
286
+ plot_bulk_concentration(
287
+ intensities, params, plot_params, root_index, log=args.log
288
+ )
@@ -0,0 +1,146 @@
1
+ #! /usr/bin/env python
2
+ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
3
+
4
+ import numpy as np
5
+
6
+ from photosurfactant.fourier import convolution_coeff, fourier_series_coeff
7
+ from photosurfactant.intensity_functions import mollifier, square_wave
8
+ from photosurfactant.parameters import Parameters, PlottingParameters
9
+ from photosurfactant.semi_analytic.first_order import FirstOrder, Variables
10
+ from photosurfactant.semi_analytic.leading_order import LeadingOrder
11
+ from photosurfactant.utils.arg_parser import (
12
+ first_order_parser,
13
+ leading_order_parser,
14
+ parameter_parser,
15
+ plot_parser,
16
+ )
17
+
18
+
19
+ def plot_spectrum(): # noqa: D103
20
+ parser = ArgumentParser(
21
+ description="Plot the first order surfactant concentrations.",
22
+ formatter_class=ArgumentDefaultsHelpFormatter,
23
+ )
24
+ parameter_parser(parser)
25
+ plot_parser(parser)
26
+ leading_order_parser(parser)
27
+ first_order_parser(parser)
28
+ args = parser.parse_args()
29
+
30
+ root_index = args.root_index
31
+
32
+ params = Parameters.from_dict(vars(args))
33
+ plot_params = PlottingParameters.from_dict(vars(args))
34
+
35
+ wavenumbers, _ = fourier_series_coeff(
36
+ lambda x: 0.0, params.L, plot_params.wave_count
37
+ )
38
+
39
+ _, square_wave_coeffs = fourier_series_coeff(
40
+ lambda x: square_wave(x), params.L, plot_params.wave_count
41
+ )
42
+
43
+ _, mol_wave_coeffs = convolution_coeff(
44
+ lambda x: square_wave(x),
45
+ mollifier(plot_params.delta),
46
+ params.L,
47
+ plot_params.wave_count,
48
+ )
49
+
50
+ # Solve leading order problem
51
+ leading = LeadingOrder(params, root_index)
52
+
53
+ # Solve first order problem
54
+ first = FirstOrder(wavenumbers, params, leading)
55
+ first.solve(lambda n: (Variables.f, 1.0))
56
+
57
+ S_n = abs(first.solution @ Variables.S)
58
+
59
+ # Calculate the slope of the spectrum on a log plot
60
+ index = S_n > 1e-20
61
+ slope = np.polyfit(wavenumbers[index], np.log(S_n[index]), 1)
62
+
63
+ # Figure setup
64
+ plt = plot_params.plt
65
+
66
+ # Plot the spectrum
67
+ plt.figure()
68
+ plt.plot(wavenumbers[1:], S_n[1:], "k-")
69
+ plt.plot(
70
+ wavenumbers,
71
+ np.exp(slope[1] + slope[0] * wavenumbers),
72
+ "k--",
73
+ label=r"$e^{" f"{slope[0] * np.pi / params.L:.2f}" r"n}$",
74
+ )
75
+ plt.yscale("log")
76
+ plt.xlabel(r"$k_n$")
77
+ plt.ylabel(r"$|\tilde{S}^{(n)}|$")
78
+ plt.legend()
79
+ plt.tight_layout()
80
+
81
+ if plot_params.save:
82
+ plt.savefig(
83
+ plot_params.path
84
+ + f"interface_spectrum{plot_params.label}.{plot_params.format}",
85
+ bbox_inches="tight",
86
+ )
87
+ else:
88
+ plt.show()
89
+
90
+ # Plot the square wave spectrum
91
+ plt.figure()
92
+ plt.plot(
93
+ wavenumbers,
94
+ square_wave_coeffs.real,
95
+ "k-",
96
+ label="Square wave",
97
+ )
98
+ plt.plot(
99
+ wavenumbers,
100
+ mol_wave_coeffs.real,
101
+ "r--",
102
+ label="Mollified square wave",
103
+ )
104
+ plt.xlabel(r"$k_n$")
105
+ plt.ylabel(r"$S^{(n)}$")
106
+ plt.legend()
107
+ plt.tight_layout()
108
+
109
+ if plot_params.save:
110
+ plt.savefig(
111
+ plot_params.path
112
+ + f"square_wave_spectrum{plot_params.label}.{plot_params.format}",
113
+ bbox_inches="tight",
114
+ )
115
+ else:
116
+ plt.show()
117
+
118
+ # Plot the square wave
119
+ def invert(fourier_coeffs, x):
120
+ return (
121
+ fourier_coeffs[0].real
122
+ + 2
123
+ * np.sum(
124
+ fourier_coeffs[1:, np.newaxis]
125
+ * np.exp(1j * wavenumbers[1:, np.newaxis] * x[np.newaxis, :]),
126
+ axis=0,
127
+ ).real
128
+ )
129
+
130
+ x = np.linspace(-params.L, params.L, plot_params.grid_size)
131
+
132
+ plt.figure()
133
+ plt.plot(x, invert(square_wave_coeffs, x), "k-", label="Square wave")
134
+ plt.plot(x, invert(mol_wave_coeffs, x), "r--", label="Mollified square wave")
135
+ plt.xlabel(r"$x$")
136
+ plt.ylabel(r"$f_1(x)$")
137
+ plt.legend()
138
+ plt.tight_layout()
139
+
140
+ if plot_params.save:
141
+ plt.savefig(
142
+ plot_params.path + f"square_wave{plot_params.label}.{plot_params.format}",
143
+ bbox_inches="tight",
144
+ )
145
+ else:
146
+ plt.show()
@@ -0,0 +1,234 @@
1
+ #! /usr/bin/env python
2
+ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
3
+ from typing import Callable
4
+
5
+ import numpy as np
6
+ from alive_progress import alive_it
7
+ from matplotlib import colors
8
+ from scipy.optimize import minimize_scalar
9
+
10
+ from photosurfactant.fourier import fourier_series_coeff
11
+ from photosurfactant.parameters import Parameters, PlottingParameters
12
+ from photosurfactant.semi_analytic.first_order import FirstOrder, Variables
13
+ from photosurfactant.semi_analytic.leading_order import LeadingOrder
14
+ from photosurfactant.utils.arg_parser import (
15
+ first_order_parser,
16
+ parameter_parser,
17
+ plot_parser,
18
+ )
19
+ from photosurfactant.utils.func_parser import parse_func
20
+
21
+
22
+ def find_max(func: Callable[[float], float], bounds: list[float]) -> float:
23
+ """Find the maximum of a functional over a given range."""
24
+ res = minimize_scalar(lambda x: -func(x), bounds=bounds)
25
+ assert res.success, "maximum velocity not found"
26
+
27
+ return -res.fun
28
+
29
+
30
+ def plot_multi_sweep(
31
+ intensity: Callable[[float], float],
32
+ x_func: Callable[[Parameters], float],
33
+ k_tr_vals: list[float],
34
+ params_list: list[Parameters],
35
+ plot_params: PlottingParameters,
36
+ xlabel: str,
37
+ tol: float = 1e-3,
38
+ label: str = "",
39
+ ):
40
+ """Sweep maximum velocity for set of k_tr values."""
41
+
42
+ if label:
43
+ label += "_"
44
+
45
+ # Figure setup
46
+ plt = plot_params.plt
47
+ fig, ax = plt.subplots(figsize=(6, 5), constrained_layout=True) # (9, 6)
48
+
49
+ cmap = plt.get_cmap("viridis")
50
+
51
+ norm = colors.LogNorm(
52
+ vmin=min(k_tr_vals) / np.sqrt(10), vmax=max(k_tr_vals) * np.sqrt(10)
53
+ )
54
+
55
+ # Plot profiles over multile values of k_tr
56
+ for k_tr in k_tr_vals:
57
+ data = []
58
+ for params in alive_it(params_list, title=f"Sweeping at k_tr = {k_tr}"):
59
+ # Preserve the ratio in k parameters
60
+ params = params.update(k_tr=k_tr, k_ci=params.k_ci * (k_tr / params.k_tr))
61
+
62
+ # Find Fourier coeffients of the intensity function
63
+ wavenumbers, func_coeffs = fourier_series_coeff(
64
+ lambda x: intensity(x, params), params.L, plot_params.wave_count
65
+ )
66
+
67
+ # Solve leading order problem
68
+ leading = LeadingOrder(params)
69
+
70
+ if leading.gamma < tol:
71
+ # TODO: Temp fix for Marangoni sweep
72
+ if label == "ma_":
73
+ data.pop()
74
+
75
+ break
76
+
77
+ # Solve first order problem
78
+ first = FirstOrder(wavenumbers, params, leading)
79
+ first.solve(lambda n: (Variables.f, func_coeffs[n]))
80
+
81
+ # Reduce using the functionals
82
+ data.append(
83
+ (
84
+ x_func(params),
85
+ find_max(lambda x: abs(first.u(x, y=1.0)), [-params.L, params.L]),
86
+ )
87
+ )
88
+
89
+ if data:
90
+ x_data, y_data = zip(*data)
91
+ ax.plot(x_data, y_data, color=cmap(norm(k_tr)))
92
+
93
+ # Tidy up figure
94
+ ax.set_xlabel(xlabel)
95
+ ax.set_ylabel(r"$\max_{x}\lvert{u_1}\rvert_{y=1}$")
96
+ ax.set_xscale("log")
97
+ # ax.set_yscale("log")
98
+ ax.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
99
+
100
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
101
+ cbar = plt.colorbar(sm, ax=ax, label=r"$k_\mathrm{tr}$")
102
+
103
+ # Annotate colorbar
104
+ cbar.ax.scatter(
105
+ np.mean(cbar.ax.set_xlim()) * np.ones_like(k_tr_vals),
106
+ k_tr_vals,
107
+ s=50,
108
+ facecolors="none",
109
+ edgecolors="k",
110
+ )
111
+
112
+ if plot_params.save:
113
+ plt.savefig(
114
+ plot_params.path + f"{label}sweep.{plot_params.format}",
115
+ bbox_inches="tight",
116
+ )
117
+ else:
118
+ plt.show()
119
+
120
+
121
+ def bi_sweep(
122
+ intensity,
123
+ start: float,
124
+ stop: float,
125
+ k_tr_vals: list[float],
126
+ default_params: Parameters,
127
+ plot_params: PlottingParameters,
128
+ ):
129
+ """Sweep Biot number."""
130
+ biot_tr_vals = 10 ** np.linspace(start, stop, plot_params.grid_size)
131
+ params_list = [
132
+ default_params.update(
133
+ Bi_tr=Bi_tr,
134
+ Bi_ci=default_params.Bi_ci * (Bi_tr / default_params.Bi_tr),
135
+ )
136
+ for Bi_tr in biot_tr_vals
137
+ ]
138
+
139
+ print("Sweeping Biot number...")
140
+ plot_multi_sweep(
141
+ intensity,
142
+ lambda p: p.Bi_tr,
143
+ k_tr_vals,
144
+ params_list,
145
+ plot_params,
146
+ xlabel=r"$Bi_{\mathrm{tr}}$",
147
+ label="bi",
148
+ )
149
+
150
+
151
+ def da_sweep(
152
+ intensity,
153
+ start: float,
154
+ stop: float,
155
+ k_tr_vals: list[float],
156
+ default_params: Parameters,
157
+ plot_params: PlottingParameters,
158
+ ):
159
+ """Sweep Damkohler number."""
160
+ damkohler_tr_vals = 10 ** np.linspace(start, stop, plot_params.grid_size)
161
+ params_list = [
162
+ default_params.update(
163
+ Da_tr=Da_tr,
164
+ Da_ci=default_params.Da_ci * (Da_tr / default_params.Da_tr),
165
+ )
166
+ for Da_tr in damkohler_tr_vals
167
+ ]
168
+
169
+ print("Sweeping Damkohler number...")
170
+ plot_multi_sweep(
171
+ intensity,
172
+ lambda p: p.Da_tr,
173
+ k_tr_vals,
174
+ params_list,
175
+ plot_params,
176
+ xlabel=r"$Da_{\mathrm{tr}}$",
177
+ label="da",
178
+ )
179
+
180
+
181
+ def ma_sweep(
182
+ intensity,
183
+ start: float,
184
+ stop: float,
185
+ k_tr_vals: list[float],
186
+ default_params: Parameters,
187
+ plot_params: PlottingParameters,
188
+ ):
189
+ """Sweep Marangoni number."""
190
+ marangoni_vals = 10 ** np.linspace(start, stop, plot_params.grid_size)
191
+ params_list = [default_params.update(Ma=Ma) for Ma in marangoni_vals]
192
+
193
+ print("Sweeping Marangoni number...")
194
+ plot_multi_sweep(
195
+ intensity,
196
+ lambda p: p.Ma,
197
+ k_tr_vals,
198
+ params_list,
199
+ plot_params,
200
+ xlabel="$Ma$",
201
+ label="ma",
202
+ )
203
+
204
+
205
+ def main():
206
+ # Parse parameters
207
+ parser = ArgumentParser(
208
+ description="Plot the maximum interfacial velocity.",
209
+ formatter_class=ArgumentDefaultsHelpFormatter,
210
+ )
211
+ parameter_parser(parser)
212
+ plot_parser(parser)
213
+ first_order_parser(parser)
214
+ args = parser.parse_args()
215
+
216
+ default_params = Parameters.from_dict(vars(args))
217
+ plot_params = PlottingParameters.from_dict(vars(args))
218
+ intensity = parse_func(args.func)
219
+
220
+ # Set k values
221
+ k_tr_vals = 10.0 ** np.arange(-4, 1)
222
+
223
+ # Sweep Biot number
224
+ bi_sweep(intensity, -4, 4, k_tr_vals, default_params, plot_params)
225
+
226
+ # Sweep Damkohler number
227
+ da_sweep(intensity, -6, 2, k_tr_vals, default_params, plot_params)
228
+
229
+ # Sweep Marangoni number
230
+ ma_sweep(intensity, -4, 6, k_tr_vals, default_params, plot_params)
231
+
232
+
233
+ if __name__ == "__main__":
234
+ main()
@@ -0,0 +1,3 @@
1
+ from .first_order import FirstOrder as FirstOrder
2
+ from .first_order import Variables as Variables
3
+ from .leading_order import LeadingOrder as LeadingOrder