From 2a4518d487dc6200f94c65b149e37aceb9e909e4 Mon Sep 17 00:00:00 2001
From: JanHab <Jan.Habscheid@web.de>
Date: Fri, 16 Aug 2024 17:31:33 +0200
Subject: [PATCH] Added ParameterAnalysis + InstructiveExample

---
 ...nsionalEquilibrium-AnInstructiveExample.py | 129 ++++++++++++++++++
 examples/ParameterAnalysis/Lambda.py          | 102 ++++++++++++++
 examples/ParameterAnalysis/ScalingPhi.py      |  72 ++++++++++
 examples/ParameterAnalysis/a.py               |  68 +++++++++
 src/Eq04.py                                   |  44 +++++-
 src/__pycache__/Eq04.cpython-312.pyc          | Bin 17910 -> 20310 bytes
 src/oneD_refined_mesh.py                      |  50 -------
 7 files changed, 412 insertions(+), 53 deletions(-)
 create mode 100644 examples/OneDimensionalEquilibrium-AnInstructiveExample.py
 create mode 100644 examples/ParameterAnalysis/Lambda.py
 create mode 100644 examples/ParameterAnalysis/ScalingPhi.py
 create mode 100644 examples/ParameterAnalysis/a.py
 delete mode 100644 src/oneD_refined_mesh.py

diff --git a/examples/OneDimensionalEquilibrium-AnInstructiveExample.py b/examples/OneDimensionalEquilibrium-AnInstructiveExample.py
new file mode 100644
index 0000000..aebf81f
--- /dev/null
+++ b/examples/OneDimensionalEquilibrium-AnInstructiveExample.py
@@ -0,0 +1,129 @@
+'''
+Jan Habscheid
+Jan.Habscheid@rwth-aachen.de
+'''
+
+import numpy as np
+from scipy.integrate import odeint
+import matplotlib.pyplot as plt
+
+# Define the parameters and boundary conditions
+Lambda2 = 8.553e-6
+z_A = -1
+z_C = 1
+y_L = 1/3
+
+# Define the equilibrium concentrations
+def y_C(phi, phi_prime):
+    return y_L * np.exp(-z_C * phi - 1/2 * Lambda2 * phi_prime**2)
+
+def y_A(phi, phi_prime):
+    return y_L * np.exp(-z_A * phi - 1/2 * Lambda2 * phi_prime**2)
+
+# Define the ODEs as a system of first-order ODEs
+def func(PHI, x):
+    phi, phi_prime = PHI
+    f = -1/Lambda2 * (z_C * y_C(phi, phi_prime) + z_A * y_A(phi, phi_prime))
+    return [phi_prime, f]
+
+# Initial conditions
+Y0 = [0, 1e-9]
+x_end = np.array([-0.95, -1.0, -1.05, -1.1])*1e-1
+
+# Storage for the results
+y_C_end, y_A_end, y_S_end = [], [], []
+phi_end, x_vec = [], []
+
+# Solve the ODEs for different values of x_end
+for x_ in x_end:
+    x = np.linspace(x_, 0, 1024)
+
+    Y = odeint(func, Y0, x)
+
+    Y_mirror = np.flip(Y, axis=0)
+    phi_end.append(Y_mirror[:, 0])
+    y_C_end.append(y_C(Y_mirror[:, 0], Y_mirror[:, 1]))
+    y_A_end.append(y_A(Y_mirror[:, 0], Y_mirror[:, 1]))
+    y_S_end.append(1-y_C_end[-1]-y_A_end[-1])
+    x_vec.append(x)
+
+# Visualize the results
+# create 2x1 subplots
+fig, axs = plt.subplots(nrows=4, ncols=1, sharex=True, figsize=(14-14/3, 12), constrained_layout=True)
+
+# clear subplots
+for ax in axs:
+    ax.remove()
+
+# add subfigure per subplot
+gridspec = axs[0].get_subplotspec().get_gridspec()
+subfigs = [fig.add_subfigure(gs) for gs in gridspec]
+
+for row, subfig in enumerate(subfigs):
+    subfig.suptitle(f'$L_x = $ {abs(round(x_end[row], 4))}', fontsize=22)
+
+    # create 1x2 subplots per subfig
+    axs = subfig.subplots(nrows=1, ncols=2)
+
+    for col, ax in enumerate(axs):
+        labelsize = 20
+        ax.set_ylim(-0.05, 1.05)
+        match col:
+            case 0: 
+                ax.plot(x_vec[row], phi_end[row])
+                ax.set_ylim(-0.5, phi_end[-1][0]+0.5)
+                ax.set_ylabel('$\\varphi$', fontsize=labelsize)
+            case 1: 
+                ax.plot(x_vec[row], y_C_end[row], label='$y_C$')
+                ax.plot(x_vec[row], y_A_end[row], label='$y_A$')
+                ax.plot(x_vec[row], y_S_end[row], label='$y_S$')
+                ax.legend()
+                ax.set_ylabel('$y_\\alpha$', fontsize=labelsize)
+        ax.set_xlim(min(x_end), 0)
+        ax.set_xlabel('x [-]', fontsize=labelsize)
+        ax.grid(True)
+        ax.tick_params(axis='x', labelrotation=45)
+fig.show()
+
+
+
+
+# Streamplot
+phi_range = np.arange(-0.1, 0.1, 0.01)  # Range for x-axis
+dphi_range = np.linspace(-5e-3, 5e-3, 10)  # Range for y-axis
+
+# Create a meshgrid with different sizes for x and y axes
+phi_values, dphi_values = np.meshgrid(phi_range, dphi_range)
+initial_conditions = np.array([phi_values.ravel(), dphi_values.ravel()]).T
+
+# Points at which the solution is requested
+x_domain = np.linspace(0, 1.0e-1, 1024)
+
+# Prepare storage for the results
+results = np.zeros((len(initial_conditions), len(x_domain), 2))
+
+# Numerical integration for each initial condition
+for i, Y0 in enumerate(initial_conditions):
+    Y = odeint(func, Y0, x_domain)
+    results[i, :, :] = Y
+
+# Reshape results for plotting
+Y_reshaped = results[:, :, 0].reshape(len(dphi_range), len(phi_range), len(x_domain))
+
+# Select a specific slice for plotting, e.g., the last time point -> last point of phi
+Y_slice = Y_reshaped[:, :, -1]
+
+# Compute derivatives for the streamplot
+U, V = np.gradient(Y_slice, dphi_range, phi_range)
+
+# Plotting
+plt.subplots(tight_layout=True)
+# lw = 5*Y_slice/Y_slice.max()
+strm = plt.streamplot(phi_values, dphi_values, U, V, color=U, linewidth=2, cmap='autumn', density=10)
+plt.colorbar(strm.lines)
+plt.xlim(-0.01, 0.01)
+plt.ylim(dphi_values.min(), dphi_values.max())
+plt.xlabel('$\\varphi$')
+plt.xticks(rotation='vertical')
+plt.ylabel("$\phi$")
+plt.show()
\ No newline at end of file
diff --git a/examples/ParameterAnalysis/Lambda.py b/examples/ParameterAnalysis/Lambda.py
new file mode 100644
index 0000000..b5fc5f3
--- /dev/null
+++ b/examples/ParameterAnalysis/Lambda.py
@@ -0,0 +1,102 @@
+'''
+Jan Habscheid
+Jan.Habscheid@rwth-aachen.de
+'''
+# import the src file needed to solve the system of equations
+import sys
+import os
+
+
+# Add the src directory to the sys.path
+src_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../..', 'src')
+sys.path.insert(0, src_path)
+
+from Eq04 import solve_System_4eq
+
+# Remove the src directory from sys.path after import
+del sys.path[0]
+
+# Import plotting library
+import matplotlib.pyplot as plt
+
+# Define Parameter and buondary conditions
+phi_right = 0.0
+p_right = 0.0
+y_A_R, y_C_R = 1/3, 1/3
+z_A, z_C = -1.0, 1.0
+K = 'incompressible'
+a2 = 7.5412e-4
+number_cells = 1024*4
+refinement_style = 'hard_log'
+rtol = 1e-8
+max_iter = 10_000
+
+# Define left values of electric potential and values for lambda^2
+phi_left_vec = [-1.0, 1.0, 4.0, 8.0]
+Lambda2_vec = [8.553e-5, 8.553e-6, 8.553e-7]
+y_A, y_C, y_S, phi, p, x = [], [], [], [], [], []
+
+# Solve the system for different values of phi_left
+for phi_left_ in phi_left_vec:
+    y_A_bcs, y_C_bcs, y_S_bcs, phi_bcs, p_bcs, x_bcs = [], [], [], [], [], []
+    for l2 in Lambda2_vec:
+        y_A_, y_C_, phi_, p_, x_ = solve_System_4eq(phi_left_, phi_right, p_right, z_A, z_C, y_A_R, y_C_R, K, l2, a2, number_cells, relax_param=0.05, x0=0, x1=1, refinement_style=refinement_style, return_type='Vector', max_iter=max_iter, rtol=rtol)
+        y_A_bcs.append(y_A_)
+        y_C_bcs.append(y_C_)
+        y_S_bcs.append(1 - y_A_ - y_C_)
+        phi_bcs.append(phi_)
+        p_bcs.append(p_)
+        x_bcs.append(x_)
+    y_A.append(y_A_bcs)
+    y_C.append(y_C_bcs)
+    y_S.append(y_S_bcs)
+    phi.append(phi_bcs)
+    p.append(p_bcs)
+    x.append(x_bcs)
+    
+# Visualize the results
+fig, axs = plt.subplots(2, 2)
+xlim = 0.08
+markers = ['--', '-', ':']
+colors = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple']
+for i in range(len(phi_left_vec)):
+    # Plot phi
+
+    match i:
+        case 0: 
+            i_ = 0
+            j_ = 0
+        case 1: 
+            i_ = 0
+            j_ = 1
+        case 2: 
+            i_ = 1
+            j_ = 0
+        case 3: 
+            i_ = 1
+            j_ = 1
+    axs[i_,j_].set_title(f'$\delta \\varphi$ = {phi_left_vec[i]}')#, fontsize=labelsize)
+    for j in range(len(Lambda2_vec)):
+        clr = colors[j]
+        axs[i_,j_].plot(x[i][j], y_A[i][j], markers[0], color=clr)#, lw=lw)
+        axs[i_,j_].plot(x[i][j], y_C[i][j], markers[1], color=clr)#, lw=lw)
+        axs[i_,j_].plot(x[i][j], y_S[i][j], markers[2], color=clr)#, lw=lw)
+    axs[i_,j_].grid()
+    axs[i_,j_].set_xlim(0,xlim)
+    axs[i_,j_].set_xlabel('$x$ [-]')#, fontsize=labelsize)
+    axs[i_,j_].set_ylabel('$y_\\alpha$ [-]')#, fontsize=labelsize)
+    axs[i_,j_].tick_params(axis='both')#, labelsize=labelsize)
+
+dummy, = axs[i_,j_].plot(2, y_A_R, color='grey', linestyle='--', label='$y_A$')
+dummy, = axs[i_,j_].plot(2, y_A_R, color='grey', linestyle='-', label='$y_C$')
+dummy, = axs[i_,j_].plot(2, y_A_R, color='grey', linestyle=':', label='$y_S$')
+for index, Lambda2_cur in enumerate(Lambda2_vec):
+    dummy, = axs[i_,j_].plot(10, y_A_R, color=colors[index], linestyle='-', label=f'$\lambda^2$ = {Lambda2_cur}')
+
+lines_labels = [ax.get_legend_handles_labels() for ax in fig.axes]
+lines, labels = [sum(lol, []) for lol in zip(*lines_labels)]
+
+# Finally, the legend (that maybe you'll customize differently)
+lgnd = fig.legend(lines, labels, bbox_to_anchor=(0.88,1.15), ncol=3)
+fig.tight_layout()
+fig.show()
\ No newline at end of file
diff --git a/examples/ParameterAnalysis/ScalingPhi.py b/examples/ParameterAnalysis/ScalingPhi.py
new file mode 100644
index 0000000..95da151
--- /dev/null
+++ b/examples/ParameterAnalysis/ScalingPhi.py
@@ -0,0 +1,72 @@
+'''
+Jan Habscheid
+Jan.Habscheid@rwth-aachen.de
+'''
+
+# import the src file needed to solve the system of equations
+import sys
+import os
+
+# Add the src directory to the sys.path
+src_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../..', 'src')
+sys.path.insert(0, src_path)
+
+from Eq04 import solve_System_4eq
+
+# Remove the src directory from sys.path after import
+del sys.path[0]
+
+# Import plotting library
+import matplotlib.pyplot as plt
+
+# Define Parameter and buondary conditions
+phi_right = 0.0
+p_right = 0.0
+y_A_R, y_C_R = 1/3, 1/3
+z_A, z_C = -1.0, 1.0
+K = 'incompressible'
+Lambda2 = 8.553e-6
+a2 = 7.5412e-4
+number_cells = 1024*4
+refinement_style = 'hard_log'
+rtol = 1e-8
+max_iter = 10_000
+
+phi_left_vector = [1,2,4,8]
+
+phi, x = [], []
+# Solve the system for different values of phi_left
+for phi_L in phi_left_vector:
+    y_A_, y_C_, phi_, p_, x_ = solve_System_4eq(phi_L, phi_right, p_right, z_A, z_C, y_A_R, y_C_R, K, Lambda2, a2, number_cells, relax_param=0.05, x0=0, x1=1, refinement_style=refinement_style, return_type='Vector', rtol=rtol, max_iter=max_iter)
+    phi.append(phi_)
+    x.append(x_)
+    
+# Normalize the electric potentials
+phi_scaled = []
+for i, phi_L in enumerate(phi_left_vector):
+    phi_scaled.append(phi[i]/phi_L)
+    
+# Visualize the results
+# Non-normalized electric potential
+for i, phi_L in enumerate(phi_left_vector):
+    plt.plot(x[i], phi[i], label='$\delta \\varphi$ = ' + str(phi_L))
+plt.legend()
+plt.xlabel('$x$ [-]')
+plt.ylabel('$\\varphi$ [-]')
+plt.ylim(0, max(phi_left_vector) + 0.1)
+plt.xlim(0,0.05)
+plt.grid()
+plt.tight_layout()
+plt.show()
+
+# Normalized electric potential
+for i, phi_L in enumerate(phi_left_vector):
+    plt.plot(x[i], phi_scaled[i], label='$\delta \\varphi$ = ' + str(phi_L))
+plt.legend()
+plt.xlabel('$x$ [-]')
+plt.ylabel('$\\varphi/\delta \\varphi$ [-]')
+plt.ylim(0, 1.05)
+plt.xlim(0,0.05)
+plt.grid()
+plt.tight_layout()
+plt.show()
\ No newline at end of file
diff --git a/examples/ParameterAnalysis/a.py b/examples/ParameterAnalysis/a.py
new file mode 100644
index 0000000..042e3b4
--- /dev/null
+++ b/examples/ParameterAnalysis/a.py
@@ -0,0 +1,68 @@
+'''
+Jan Habscheid
+Jan.Habscheid@rwth-aachen.de
+'''
+# import the src file needed to solve the system of equations
+import sys
+import os
+
+
+# Add the src directory to the sys.path
+src_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../..', 'src')
+sys.path.insert(0, src_path)
+
+from Eq04 import solve_System_4eq
+
+# Remove the src directory from sys.path after import
+del sys.path[0]
+
+# Import plotting library
+import matplotlib.pyplot as plt
+import numpy as np
+
+# Define Parameter and buondary conditions
+phi_right = 0.0
+p_right = 0.0
+y_A_R, y_C_R = 1/3, 1/3
+z_A, z_C = -1.0, 1.0
+K = 'incompressible'
+Lambda2 = 8.553e-6
+number_cells = 1024*4
+refinement_style = 'hard_log'
+rtol = 1e-8
+max_iter = 10_000
+
+phi_left_vec = [0.1, 1.0, 4.0, 8.0]
+a2_vec = [7.5412e-3, 7.5412e-4, 7.5412e-5]
+y_A, y_C, y_S, phi, p, x = [], [], [], [], [], []
+for phi_left_ in phi_left_vec:
+    y_A_bcs, y_C_bcs, y_S_bcs, phi_bcs, p_bcs, x_bcs = [], [], [], [], [], []
+    for a2 in a2_vec:
+        y_A_, y_C_, phi_, p_, x_ = solve_System_4eq(phi_left_, phi_right, p_right, z_A, z_C, y_A_R, y_C_R, K, Lambda2, a2, number_cells, relax_param=0.05, x0=0, x1=1, refinement_style=refinement_style, return_type='Vector', max_iter=max_iter, rtol=rtol)
+        y_A_bcs.append(y_A_)
+        y_C_bcs.append(y_C_)
+        y_S_bcs.append(1 - y_A_ - y_C_)
+        phi_bcs.append(phi_)
+        p_bcs.append(p_)
+        x_bcs.append(x_)
+    y_A.append(y_A_bcs)
+    y_C.append(y_C_bcs)
+    y_S.append(y_S_bcs)
+    phi.append(phi_bcs)
+    p.append(p_bcs)
+    x.append(x_bcs)
+
+p = np.array(p)
+
+plt.figure()
+for j in range(len(a2_vec)):
+    plt.plot(x[-1][j], p[-1][j], label='$a^2$ = {}'.format(a2_vec[j]))
+plt.grid()
+plt.ylim(0.0, np.max(p[-1][0]))
+plt.xlim(0,0.08)
+plt.xlabel('$x$ [-]')
+plt.ylabel('$p$ [-]')
+plt.tick_params(axis='both')
+plt.legend(loc='best')
+plt.tight_layout()
+plt.show()
\ No newline at end of file
diff --git a/src/Eq04.py b/src/Eq04.py
index bed5462..37c292f 100644
--- a/src/Eq04.py
+++ b/src/Eq04.py
@@ -8,12 +8,48 @@ from mpi4py import MPI
 from dolfinx import mesh, fem, log
 from dolfinx.fem.petsc import NonlinearProblem
 from dolfinx.nls.petsc import NewtonSolver
-from ufl import TestFunctions, split, dot, grad, dx, inner, ln, Cell
+from ufl import TestFunctions, split, dot, grad, dx, inner, ln, Mesh
 from basix.ufl import element, mixed_element
-from petsc4py import PETSc
 import matplotlib.pyplot as plt
 
-from oneD_refined_mesh import create_refined_mesh
+# Define mesh
+def create_refined_mesh(refinement_style:str, number_cells:int) -> Mesh:
+    '''
+    Creates a one-dimensional mesh with a refined region at the left boundary
+
+    Parameters
+    ----------
+    refinement_style : str
+        How the mesh should be refined. Options are 'log', 'hard_log', 'hard_hard_log'
+    number_cells : int
+        Number of cells in the mesh
+
+    Returns
+    -------
+    Mesh
+        One-dimensional mesh, ready for use in FEniCSx
+    '''
+    if refinement_style == 'log':
+        coordinates_np = (np.logspace(0, 1, number_cells+1) - 1) / 9
+    elif refinement_style == 'hard_log':
+        coordinates_np1 = (np.logspace(0,1,int(number_cells*0.9)+1,endpoint=False)-1)/9 * 0.1
+        coordinates_np2 = 0.1 + (np.logspace(0,1,int(number_cells*0.1)+1)-1)/9 * 0.9
+        coordinates_np = np.concatenate((coordinates_np1, coordinates_np2), axis=0)
+    elif refinement_style == 'hard_hard_log':
+        coordinates_np1 = (np.logspace(0,1,int(number_cells*0.9)+1,endpoint=False)-1)/9 * 0.004
+        coordinates_np2 = 0.004 + (np.logspace(0,1,int(number_cells*0.1)+1)-1)/9 * 0.996
+        coordinates_np = np.concatenate((coordinates_np1, coordinates_np2), axis=0)
+    num_vertices = len(coordinates_np)
+    num_cells = num_vertices - 1
+    cells_np = np.column_stack((np.arange(num_cells), np.arange(1, num_cells+1)))
+    gdim = 1
+    shape = 'interval' # 'interval', 'triangle', 'quadrilateral', 'tetrahedron', 'hexahedron'
+    degree = 1
+    domain = Mesh(element("Lagrange", shape, 1, shape=(1,)))
+    coordinates_np_ = []
+    [coordinates_np_.append([coord]) for coord in coordinates_np]
+    msh = mesh.create_mesh(MPI.COMM_WORLD, cells_np, coordinates_np_, domain)
+    return msh
 
 def solve_System_4eq(phi_left:float, phi_right:float, p_right:float, z_A:float, z_C:float, y_A_R:float, y_C_R:float, K:float|str, Lambda2:float, a2:float, number_cells:int, solvation:float = 0, PoissonBoltzmann:bool=False, relax_param:float=None, x0:float=0, x1:float=1, refinement_style:str='uniform', return_type:str='Scalar', rtol:float=1e-8, max_iter:float=500):
     '''
@@ -26,6 +62,8 @@ def solve_System_4eq(phi_left:float, phi_right:float, p_right:float, z_A:float,
 
     with φ the electric potential, p the pressure, n^F the total free charge density, J_α the diffusion fluxes of species α, λ² a dimensionless parameter, L²=1, a² a dimensionless parameter, N the number of species, and α the species index.
 
+    ! If the Newton solver diverges, you may try to reduce the relaxation parameter.
+
     Parameters
     ----------
     phi_left : float
diff --git a/src/__pycache__/Eq04.cpython-312.pyc b/src/__pycache__/Eq04.cpython-312.pyc
index d115d2ed6ed42485613169199be3432cb7a86dc5..e94b79d647eeb82bdf59ecca6b780f96647b96e5 100644
GIT binary patch
delta 4847
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

delta 2696
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
QsAe<M`?vir+VNlTH!RPK`2YX_

diff --git a/src/oneD_refined_mesh.py b/src/oneD_refined_mesh.py
deleted file mode 100644
index d34bca8..0000000
--- a/src/oneD_refined_mesh.py
+++ /dev/null
@@ -1,50 +0,0 @@
-'''
-Jan Habscheid
-Jan.Habscheid@rwth-aachen.de
-'''
-
-import numpy as np
-from mpi4py import MPI
-from dolfinx import mesh
-from basix.ufl import element
-from ufl import Mesh
-
-
-# Define mesh
-def create_refined_mesh(refinement_style:str, number_cells:int) -> Mesh:
-    '''
-    Creates a one-dimensional mesh with a refined region at the left boundary
-
-    Parameters
-    ----------
-    refinement_style : str
-        How the mesh should be refined. Options are 'log', 'hard_log', 'hard_hard_log'
-    number_cells : int
-        Number of cells in the mesh
-
-    Returns
-    -------
-    Mesh
-        One-dimensional mesh, ready for use in FEniCSx
-    '''
-    if refinement_style == 'log':
-        coordinates_np = (np.logspace(0, 1, number_cells+1) - 1) / 9
-    elif refinement_style == 'hard_log':
-        coordinates_np1 = (np.logspace(0,1,int(number_cells*0.9)+1,endpoint=False)-1)/9 * 0.1
-        coordinates_np2 = 0.1 + (np.logspace(0,1,int(number_cells*0.1)+1)-1)/9 * 0.9
-        coordinates_np = np.concatenate((coordinates_np1, coordinates_np2), axis=0)
-    elif refinement_style == 'hard_hard_log':
-        coordinates_np1 = (np.logspace(0,1,int(number_cells*0.9)+1,endpoint=False)-1)/9 * 0.004
-        coordinates_np2 = 0.004 + (np.logspace(0,1,int(number_cells*0.1)+1)-1)/9 * 0.996
-        coordinates_np = np.concatenate((coordinates_np1, coordinates_np2), axis=0)
-    num_vertices = len(coordinates_np)
-    num_cells = num_vertices - 1
-    cells_np = np.column_stack((np.arange(num_cells), np.arange(1, num_cells+1)))
-    gdim = 1
-    shape = 'interval' # 'interval', 'triangle', 'quadrilateral', 'tetrahedron', 'hexahedron'
-    degree = 1
-    domain = Mesh(element("Lagrange", shape, 1, shape=(1,)))
-    coordinates_np_ = []
-    [coordinates_np_.append([coord]) for coord in coordinates_np]
-    msh = mesh.create_mesh(MPI.COMM_WORLD, cells_np, coordinates_np_, domain)
-    return msh
\ No newline at end of file
-- 
GitLab