Source code for matrix_toolkit.pde.equations.convection_diffusion

"""
Convection-Diffusion equation: -ε∇²u + v·∇u = f
"""

import numpy as np
from scipy import sparse
from typing import Dict, Any, Tuple

from matrix_toolkit.pde.base import BasePDEEquation


[docs] class ConvectionDiffusionEquation(BasePDEEquation): """ The convection-diffusion equation: .. math:: -\varepsilon \nabla^2 u + \mathbf{v} \cdot \nabla u = f Examples: >>> config = PDEConfig( ... dimension=2, ... mesh_size=64, ... coefficients={'velocity': (1.0, 0.5), 'diffusion': 0.01} ... ) >>> eq = ConvectionDiffusionEquation(config) >>> A = eq.generate_matrix() """
[docs] def get_operator_name(self) -> str: return "ConvectionDiffusion"
[docs] def get_default_coefficients(self) -> Dict[str, Any]: return { 'diffusion': 1.0, 'velocity': None, # Will be set based on dimension }
[docs] def randomize_coefficients(self, seed=None) -> Dict[str, Any]: """Randomize coefficients with dimension-aware defaults""" coeffs = super().randomize_coefficients(seed) # Set velocity if not specified if coeffs['velocity'] is None: if self.config.dimension == 1: coeffs['velocity'] = 1.0 elif self.config.dimension == 2: coeffs['velocity'] = (1.0, 1.0) elif self.config.dimension == 3: coeffs['velocity'] = (1.0, 1.0, 1.0) # Randomize velocity components if ranges specified if 'velocity_x' in self.config.param_ranges: vx_min, vx_max = self.config.param_ranges['velocity_x'] vx = np.random.uniform(vx_min, vx_max) if self.config.dimension == 1: coeffs['velocity'] = vx else: v = list(coeffs['velocity']) if isinstance(coeffs['velocity'], tuple) else [1.0] * self.config.dimension v[0] = vx coeffs['velocity'] = tuple(v) if 'velocity_y' in self.config.param_ranges and self.config.dimension >= 2: vy_min, vy_max = self.config.param_ranges['velocity_y'] vy = np.random.uniform(vy_min, vy_max) v = list(coeffs['velocity']) v[1] = vy coeffs['velocity'] = tuple(v) return coeffs
[docs] def generate_matrix(self) -> sparse.spmatrix: """Generate convection-diffusion matrix""" coeffs = self.config.coefficients or self.get_default_coefficients() if self.config.random_params: coeffs = self.randomize_coefficients(self.config.random_seed) diffusion = coeffs.get('diffusion', 1.0) velocity = coeffs.get('velocity') if velocity is None: if self.config.dimension == 1: velocity = 1.0 elif self.config.dimension == 2: velocity = (1.0, 1.0) elif self.config.dimension == 3: velocity = (1.0, 1.0, 1.0) if self.config.dimension == 1: return self._generate_1d(velocity, diffusion) elif self.config.dimension == 2: return self._generate_2d(velocity, diffusion) elif self.config.dimension == 3: return self._generate_3d(velocity, diffusion)
def _generate_1d(self, velocity: float, diffusion: float) -> sparse.spmatrix: """Generate 1D convection-diffusion matrix""" from matrix_toolkit.pde.dim1d.generators import generate_1d_convection_diffusion n = self.config.mesh_size[0] h = self.config.get_mesh_spacing()[0] return generate_1d_convection_diffusion( n, velocity, diffusion, h, boundary=self.config.boundary_condition ) def _generate_2d(self, velocity: Tuple[float, float], diffusion: float) -> sparse.spmatrix: """Generate 2D convection-diffusion matrix""" from matrix_toolkit.pde.dim2d.generators import generate_2d_convection_diffusion nx, ny = self.config.mesh_size hx, hy = self.config.get_mesh_spacing() return generate_2d_convection_diffusion( nx, ny, velocity, diffusion, hx, hy, boundary=self.config.boundary_condition ) def _generate_3d(self, velocity: Tuple[float, float, float], diffusion: float) -> sparse.spmatrix: """Generate 3D convection-diffusion matrix""" from matrix_toolkit.pde.dim3d.generators import generate_3d_convection_diffusion nx, ny, nz = self.config.mesh_size hx, hy, hz = self.config.get_mesh_spacing() return generate_3d_convection_diffusion( nx, ny, nz, velocity, diffusion, hx, hy, hz )