AI-Agency-Pro / examples /poisson_2d_vendor.py
dlynch90's picture
Create examples/poisson_2d_vendor.py
650702c verified
"""2D Poisson Equation Solver - 100% VENDOR IMPLEMENTATION
Solves: -∆u = f in Ω, u = 0 on ∂Ω
Using ONLY vendor libraries:
- skfem: FE assembly
- scipy.sparse: Linear algebra
- matplotlib: Visualization
ZERO custom FEM code.
"""
import numpy as np
from scipy.sparse.linalg import spsolve
import matplotlib.pyplot as plt
# VENDOR: scikit-fem for ALL FEM operations
import skfem
from skfem.helpers import dot, grad
def solve_poisson_vendor():
"""Solve 2D Poisson using pure vendor APIs."""
print("=" * 60)
print("2D Poisson Solver - VENDOR-ONLY Implementation")
print("="*60)
# STEP 1: Create mesh (skfem vendor)
print("\n[1/5] Generating mesh with skfem.MeshTri...")
mesh = skfem.MeshTri()
mesh = mesh.refined(4) # Refine 4 times
print(f" Nodes: {mesh.p.shape[1]}")
print(f" Elements: {mesh.t.shape[1]}")
# STEP 2: Define weak form (skfem vendor decorators)
print("\n[2/5] Defining weak forms with @skfem.BilinearForm...")
@skfem.BilinearForm
def laplacian(u, v, _):
"""Weak form of Laplacian using skfem.helpers."""
return dot(grad(u), grad(v))
@skfem.LinearForm
def load(v, w):
"""Right-hand side f=1."""
return 1.0 * v
# STEP 3: Assemble system (skfem vendor)
print("\n[3/5] Assembling system with skfem.Basis...")
basis = skfem.Basis(mesh, skfem.ElementTriP1())
K = laplacian.assemble(basis) # Returns scipy.sparse.csr_matrix
F = load.assemble(basis) # Returns numpy array
print(f" Stiffness matrix K: {K.shape}, nnz={K.nnz}")
print(f" Load vector F: {F.shape}")
# STEP 4: Apply BCs and solve (skfem + scipy vendors)
print("\n[4/5] Applying BCs and solving with scipy.sparse.linalg...")
# Get boundary DOFs (skfem vendor)
dofs = basis.get_dofs() # All boundary nodes
# Solve with BCs (skfem.condense + scipy.spsolve vendors)
u = skfem.solve(*skfem.condense(K, F, D=dofs))
print(f" Solution u: min={u.min():.6f}, max={u.max():.6f}")
# STEP 5: Visualize (matplotlib + skfem.visuals vendors)
print("\n[5/5] Visualizing with skfem.visuals.matplotlib...")
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# Plot solution using skfem vendor visualization
skfem.visuals.matplotlib.plot(
basis, u, ax=ax1, shading='gouraud', colorbar=True
)
ax1.set_title('Solution u')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# Plot mesh using skfem vendor
skfem.visuals.matplotlib.draw(mesh, ax=ax2)
ax2.set_title(f'Mesh ({mesh.t.shape[1]} elements)')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
plt.tight_layout()
plt.savefig('poisson_solution_vendor.png', dpi=150)
print(" Saved: poisson_solution_vendor.png")
print("\n" + "="*60)
print("SUCCESS: Solved using 100% vendor libraries")
print(" - skfem: Mesh, basis, assembly, BCs")
print(" - scipy.sparse: Linear solver")
print(" - matplotlib: Visualization")
print("="*60)
return mesh, u, basis
if __name__ == "__main__":
mesh, u, basis = solve_poisson_vendor()
# Additional vendor-based analysis
print("\nVendor-based Analysis:")
print(f" L2 norm of solution: {np.linalg.norm(u):.6f}")
print(f" Mesh quality (min angle): {mesh.quality().min():.3f}")
print(f" Basis dimension: {basis.N}")