Skip to main content
Glama
vector_calculus.py7.75 kB
import numpy as np import sympy as sp from sympy.parsing.sympy_parser import standard_transformations, implicit_multiplication_application from sympy import parse_expr from sympy.vector import Del, CoordSys3D, directional_derivative C = CoordSys3D('C') def parse_field(f_str: str): """ Parse a vector field string into a Sympy Vector. Args: f_str (str): e.g. "[z, -y, x]". x_coord, y_coord, z_coord: optional sympy symbols (e.g., x, C.x). If None, defaults to bare symbols (x, y, z). Returns: sympy.vector.Vector: symbolic vector in CoordSys3D C. """ raw = f_str.strip().strip("[]") comps_str = [c.strip() for c in raw.split(",")] transformations = standard_transformations + (implicit_multiplication_application,) local_ns = { "x": C.x, "y": C.y, "z": C.z, "sin": sp.sin, "cos": sp.cos } comp_syms = [ parse_expr(expr, local_dict=local_ns, transformations=transformations) for expr in comps_str ] return comp_syms[0] * C.i + comp_syms[1] * C.j + comp_syms[2] * C.k def register_tools(mcp, tensor_store): # Basic vector operations @mcp.tool() def vector_project(name: str, new_vector: list[float]) -> np.ndarray: """ Projects a stored vector onto another vector. Args: name (str): Name of the stored vector to project. new_vector (list[float]): The vector to project onto. Returns: np.ndarray: The projection result vector. Raises: ValueError: If the vector name is not found or projection fails. """ if name not in tensor_store: raise ValueError("The tensor name is not found in the store.") try: new_vector = np.asarray(new_vector) result = np.dot(tensor_store[name], new_vector) / np.linalg.norm(new_vector) * new_vector except ValueError as e: raise ValueError(f"Error computing projection:{e}") return result @mcp.tool() def vector_dot_product(name_a: str, name_b: str) -> np.ndarray: """ Computes the dot product between two stored vectors. Args: name_a (str): Name of the first vector in the tensor store. name_b (str): Name of the second vector in the tensor store. Returns: np.ndarray: Scalar result of the dot product. Raises: ValueError: If either vector is not found or if the dot product computation fails. """ if name_a not in tensor_store or name_b not in tensor_store: raise ValueError("One or both tensor names not found in the store.") try: result = np.dot(tensor_store[name_a], tensor_store[name_b]) except ValueError as e: raise ValueError(f"Error computing dot product:{e}") return result @mcp.tool() def vector_cross_product(name_a: str, name_b: str) -> np.ndarray: """ Computes the cross product of two stored vectors. Args: name_a (str): Name of the first vector in the tensor store. name_b (str): Name of the second vector in the tensor store. Returns: np.ndarray: Vector result of the cross product. Raises: ValueError: If either vector is not found or if the cross product computation fails. """ if name_a not in tensor_store or name_b not in tensor_store: raise ValueError("One or both tensor names not found in the store.") try: result = np.cross(tensor_store[name_a], tensor_store[name_b]) except ValueError as e: raise ValueError(f"Error computing cross product:{e}") return result @mcp.tool() def gradient(f_str: str) -> str: """ Computes the symbolic gradient of a scalar function. Args: f_str (str): A string representing a scalar function (e.g., "x**2 + y*z"). Returns: str: A string representation of the symbolic gradient as a vector. """ f_sym = sp.sympify(f_str) variable = sorted(list(f_sym.free_symbols), key=lambda s: s.name) grad = sp.Matrix([f_sym]).jacobian(variable) return grad @mcp.tool() def curl(f_str: str, point: list[float] = None) -> dict: """ Computes the symbolic curl of a vector field, optionally evaluated at a point. Args: f_str (str): A string representing the vector field in list format (e.g., "[x+y, x, 2*z]"). point (list[float], optional): A list of coordinates [x, y, z] to evaluate the curl numerically. Returns: dict: A dictionary with the symbolic curl as a string, and optionally the evaluated vector. """ F = parse_field(f_str) curl_sym = Del().cross(F).doit() result = {"curl_sym": str(curl_sym)} if point: variables = [C.x, C.y, C.z] comps = [curl_sym.dot(dir_) for dir_ in (C.i, C.j, C.k)] lamb = sp.lambdify(variables, sp.Matrix(comps), 'numpy') result['curl_val'] = [float(v) for v in lamb(*point)] return result @mcp.tool() def divergence(f_str: str, point: list[float] = None) -> dict: """ Computes the symbolic divergence of a vector field, optionally evaluated at a point. Args: f_str (str): A string representing the vector field in list format (e.g., "[x+y, x, 2*z]"). point (list[float], optional): A list of coordinates [x, y, z] to evaluate the divergence numerically. Returns: dict: A dictionary with the symbolic divergence as a string, and optionally the evaluated scalar. """ F = parse_field(f_str) div_sym = Del().dot(F, doit=True) result = {'divergence_sym': str(div_sym)} if point: variables = [C.x, C.y, C.z] lamb = sp.lambdify(variables, div_sym, 'numpy') result['divergence_val'] = float(lamb(*point)) return result @mcp.tool() def laplacian(f_str: str, is_vector: bool = False) -> str: """ Computes the Laplacian of a scalar or vector field symbolically. Args: f_str (str): Scalar function as "x**2 + y*z" or vector "[Fx, Fy, Fz]". is_vector (bool): Set True to compute vector Laplacian. Returns: str: Symbolic result of the Laplacian—scalar or list of 3 components. """ if not is_vector: f = parse_expr(f_str, local_dict={"x": C.x, "y": C.y, "z": C.z}) lap = Del().dot(Del()(f)).doit() return str(lap) else: F = parse_field(f_str) # Extract components comps = F.to_matrix(C).tolist() lap_comps = [Del().dot(Del()(comp)).doit() for comp in comps] return str(lap_comps) # list form @mcp.tool() def directional_deriv(f_str: str, u: list[float], unit: bool = True) -> str: """ Computes symbolic directional derivative of scalar field along a vector direction. Args: f_str (str): Expression like "x*y*z". u (list[float]): Direction vector [vx, vy, vz]. unit (bool): True if u should be normalized before calculating directional derivative. Set to True by default. Returns: str: Symbolic result as string. """ f = parse_expr(f_str, local_dict={"x": C.x, "y": C.y, "z": C.z}) v = u[0] * C.i + u[1] * C.j + u[2] * C.k if unit: v = v.normalize() expr = directional_derivative(f, v).doit() return str(expr)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Aman-Amith-Shastry/scientific_computation_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server