Skip to content

Commit

Permalink
add figure
Browse files Browse the repository at this point in the history
  • Loading branch information
obouchaara committed Jan 11, 2024
1 parent 0b6c6d7 commit 54dd209
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 160 deletions.
135 changes: 135 additions & 0 deletions notebooks/figure.ipynb

Large diffs are not rendered by default.

68 changes: 8 additions & 60 deletions notebooks/symbolic/field.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1fea1cdfb7f64bd08da215bd57e6ea30",
"model_id": "d3a381a9bff5462ba45bb3af34c9290e",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -184,7 +184,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6a32393e60dd48b29678a0cd56fb8948",
"model_id": "7cf0c7c1a185487ca5af1d3892818097",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -293,7 +293,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7c4d90cee99c4a5e812d43aa6a2a93a5",
"model_id": "0adf0d6fec7d4ee5a20a508f1c4a0d84",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -317,6 +317,7 @@
}
],
"source": [
"scalar_field = scalar_field.to_cartesian()\n",
"scalar_field.plot()"
]
},
Expand Down Expand Up @@ -359,7 +360,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4399f504d89042e094f9ae65ab7dc8a0",
"model_id": "6d0e5225ee0e4ba89b46a7d975831c63",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -460,48 +461,10 @@
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Error occurred while plotting: Cannot plot field with unresolved parameters: n, m\n"
]
},
{
"data": {
"text/plain": [
"SymbolicScalarField(\n",
"-2*m*y + 3*x,\n",
"(x, y, z),\n",
"[m])"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Error occurred while plotting: Cannot plot field with unresolved parameters: m\n"
]
},
{
"data": {
"text/plain": [
"SymbolicScalarField(\n",
"3*x,\n",
"(x, y, z),\n",
"[])"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "74fe6d14310d42cd829d0064b9534d1b",
"model_id": "dd305afc69b74f1088183d88e9dba902",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -530,24 +493,9 @@
"data = sp.Array([1*n, -2*m, 0])\n",
"linear_scalar_field = SymbolicScalarField.create_linear(data, field_params=field_params)\n",
"display(linear_scalar_field)\n",
"try:\n",
" linear_scalar_field.plot()\n",
"except ValueError as e:\n",
" print(f\"Error occurred while plotting: {e}\")\n",
" \n",
"linear_scalar_field.subs_field_params({n: 3})\n",
"display(linear_scalar_field)\n",
"try:\n",
" linear_scalar_field.plot()\n",
"except ValueError as e:\n",
" print(f\"Error occurred while plotting: {e}\")\n",
"\n",
"linear_scalar_field.subs_field_params({m: 0})\n",
"display(linear_scalar_field)\n",
"try:\n",
" linear_scalar_field.plot()\n",
"except ValueError as e:\n",
" print(f\"Error occurred while plotting: {e}\")"
"linear_scalar_field.plot()"
]
}
],
Expand All @@ -567,7 +515,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
"version": "3.10.12"
}
},
"nbformat": 4,
Expand Down
21 changes: 3 additions & 18 deletions src/mechpy/core/symbolic/coord.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,11 @@ def __init__(self, basis_symbols=None):
def get_basis_cartesian_exprs(self, cartesian_basis_symbols=None) -> dict:
if not cartesian_basis_symbols:
cartesian_basis_symbols = sp.symbols("x y z")
if (
not isinstance(cartesian_basis_symbols, (list, tuple))
or len(cartesian_basis_symbols) != 3
):
raise ValueError("values must be a list or tuple of length 3")

r, theta, z_cyl = self.basis_symbols
x, y, z_cart = cartesian_basis_symbols

x_expr = r * sp.cos(theta)
y_expr = r * sp.sin(theta)
z_expr = z_cyl

return {x: x_expr, y: y_expr, z_cart: z_expr}
r_expr = sp.sqrt(x**2 + y**2)
theta_expr = sp.atan2(y, x)
return {r: r_expr, theta: theta_expr, z_cyl: z_cart}

def to_cartesian(self):
expr_dict = self.get_basis_cartesian_exprs()
Expand All @@ -108,12 +99,6 @@ def __init__(self, basis_symbols=None):
def get_basis_cartesian_exprs(self, cartesian_basis_symbols=None) -> dict:
if not cartesian_basis_symbols:
cartesian_basis_symbols = sp.symbols("x y z")
if (
not isinstance(cartesian_basis_symbols, (list, tuple))
or len(cartesian_basis_symbols) != 3
):
raise ValueError("values must be a list or tuple of length 3")

r, theta, phi = self.basis_symbols
x, y, z = cartesian_basis_symbols
r_expr = sp.sqrt(x**2 + y**2 + z**2)
Expand Down
103 changes: 21 additions & 82 deletions src/mechpy/core/symbolic/field.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import copy
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt

from matplotlib.widgets import Slider

from .coord import (
SymbolicCoordSystem,
Expand All @@ -16,7 +17,7 @@ def __init__(self, data, coord_system, field_params=None):
if isinstance(coord_system, SymbolicCoordSystem):
self.data = data
self.coord_system = coord_system
self.field_params = list(field_params or [])
self.field_params = field_params or {}
self.validate_field()
else:
raise ValueError("coord system must be a SymbolicCoordSystem")
Expand Down Expand Up @@ -52,21 +53,21 @@ def validate_basis_symbols(self):
"""
# extract basis symbols function arg
# extract data function arg

basis_symbols = set(self.coord_system.basis_symbols)
field_param_symbols = set(self.field_params)
# to remove
# Extracting the arguments of each function
function_args = set()
for element in self.data:
for arg in element.args:
if arg.is_Function:
function_args.update(arg.args)
valid_symbols = basis_symbols.union(field_param_symbols).union(function_args)
# to remove
# valid_symbols = basis_symbols.union(field_param_symbols)

# # to remove
# # Extracting the arguments of each function
# function_args = set()
# for element in self.data:
# for arg in element.args:
# if arg.is_Function:
# function_args.update(arg.args)
# valid_symbols = basis_symbols.union(field_param_symbols).union(function_args)
# # to remove

valid_symbols = basis_symbols.union(field_param_symbols)

free_symbols = (
self.data.free_symbols
Expand All @@ -77,7 +78,6 @@ def validate_basis_symbols(self):
# Exclude numerical symbols from the free symbols set
free_symbols = {sym for sym in free_symbols if not isinstance(sym, sp.Number)}


invalid_symbols = free_symbols - valid_symbols
if invalid_symbols:
raise ValueError(
Expand Down Expand Up @@ -232,43 +232,8 @@ def create_linear(cls, data, coord_system=None, field_params=None):
scalar_field = sum(var * coeff for coeff, var in zip(data, basis_symbols))
return cls(scalar_field, coord_system, field_params)

def plot(self, x_limits=[-100, 100], y_limits=[-100, 100], z_limits=[-100, 100]):
if self.field_params:
raise ValueError(
"Cannot plot field with unresolved parameters: "
+ ", ".join(str(p) for p in self.field_params)
)

x_vals = np.linspace(*x_limits, 100)
y_vals = np.linspace(*y_limits, 100)
X, Y = np.meshgrid(x_vals, y_vals)

f = self.lambdify()

fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")

# Number of z slices
num_slices = 10
z_slices = np.linspace(z_limits[0], z_limits[1], num_slices)

# Plot 2D contour plots at different z slices
for z_val in z_slices:
Z = f(X, Y, z_val)
contour = ax.contourf(
X, Y, Z, zdir="z", offset=z_val, levels=20, cmap="viridis", alpha=0.5
)

fig.colorbar(contour, ax=ax, shrink=0.5, aspect=5)

ax.set_xlim(np.array(x_limits) * 1.2)
ax.set_ylim(np.array(y_limits) * 1.2)
ax.set_zlim(np.array(z_limits) * 1.2)
ax.set_xlabel("X axis")
ax.set_ylabel("Y axis")
ax.set_zlabel("Z axis")

plt.show()
def plot(self):
pass


class SymbolicVectorField(SymbolicSpatialField):
Expand All @@ -294,7 +259,7 @@ def create(cls, data=None, coord_system=None, field_params=None):
raise ValueError("data type error")
except:
raise ValueError("Conversion error")

data = sp.ImmutableDenseNDimArray(data)

return cls(data, coord_system, field_params)
Expand All @@ -318,34 +283,8 @@ def create_linear(cls, data, coord_system=None, field_params=None):
vector_field = sp.ImmutableDenseNDimArray(vector_field_components)
return cls(vector_field, coord_system, field_params)

def plot(self, x_limits=[-100, 100], y_limits=[-100, 100], z_limits=[-100, 100]):
# Create a grid of points within the specified limits
x_vals = np.linspace(*x_limits, 10)
y_vals = np.linspace(*y_limits, 10)
z_vals = np.linspace(*z_limits, 10)
X, Y, Z = np.meshgrid(x_vals, y_vals, z_vals)

f = self.lambdify()

# Evaluate the function at each point in the grid
U, V, W = f(X, Y, Z)

# Create a 3D plot
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")

# Plot the vector field using a quiver plot
ax.quiver(X, Y, Z, U, V, W, length=0.01)

# Set the limits and labels
ax.set_xlim(np.array(x_limits) * 1.2)
ax.set_ylim(np.array(y_limits) * 1.2)
ax.set_zlim(np.array(z_limits) * 1.2)
ax.set_xlabel("X axis")
ax.set_ylabel("Y axis")
ax.set_zlabel("Z axis")

plt.show()
def plot(self):
pass


class SymbolicTensorField(SymbolicSpatialField):
Expand Down
Loading

0 comments on commit 54dd209

Please sign in to comment.