Source code for buffalo_panel.formulations.lumped_vortex

"""Public lumped-vortex formulation entry points."""

from __future__ import annotations

from dataclasses import dataclass

import numpy as np

from buffalo_panel.assembly import Freestream2D
from buffalo_panel.assembly.internal.system import build_lumped_vortex_system
from buffalo_panel.basis.descriptors import LINE_POINT
from buffalo_panel.families.dof_maps import PerElementDofMap
from buffalo_panel.families.element_family import ElementFamily
from buffalo_panel.geometry.line2d import ThinBodyLineGeometry2D
from buffalo_panel.geometry.supports import LINE_2D
from buffalo_panel.kernels.registry import KernelRegistry
from buffalo_panel.post import BodyReference2D, PanelSolution2D
from buffalo_panel.post.internal.lumped_vortex import (
    recover_lumped_vortex_solution,
)
from buffalo_panel.prescribed.internal.point_element_particle_2d import (
    PointElementParticle2D,
)
from buffalo_panel.singularities.descriptors import VORTEX
from buffalo_panel.solvers.dense import solve_dense
from buffalo_panel.type_aliases import FloatArray


[docs] @dataclass(slots=True) class LumpedVortexFormulation: """Solve a thin-body lumped-vortex formulation.""" geometry: ThinBodyLineGeometry2D """Thin-body geometry used in the lumped-vortex solver.""" registry: KernelRegistry """Registry of computational kernels to use in the solver.""" backend: str = "python" """Specific computational kernel backend to use.""" body_reference: BodyReference2D | None = None """Reference quantities for integrated coefficient recovery."""
[docs] def build_body_vortex_family(self) -> ElementFamily: """ Build the point-vortex family for the body panels. Returns ------- ElementFamily Body point-vortex assembly for this formulation. """ n_body_panels = self.geometry.n_body_panels body_vortex_indices = np.arange(n_body_panels, dtype=np.int32) return ElementFamily( name="body_vortices", support=LINE_2D, singularity=VORTEX, basis=LINE_POINT, n_elements=n_body_panels, panel_indices=self.geometry.body_panel_indices, dof_map=PerElementDofMap(global_indices=body_vortex_indices), metadata={"role": "body", "lumped": True}, )
[docs] def solve( self, freestream: Freestream2D, point_particles: tuple[PointElementParticle2D, ...] = (), ) -> tuple[FloatArray, PanelSolution2D]: """ Assemble, solve, and recover surface results for one freestream. Parameters ---------- freestream : Freestream2D Freestream conditions for this solution. point_particles : tuple[PointElementParticle2D, ...], optional Prescribed point particles whose induced fields contribute known forcing to the body boundary condition and to recovered flow fields. Returns ------- FloatArray Raw solution from the system of equations. PanelSolution2D Processed results information from solution. """ vortex_family = self.build_body_vortex_family() matrix, rhs = build_lumped_vortex_system( vortex_family, self.geometry, freestream, self.registry, self.backend, point_particles, ) x = solve_dense(matrix, rhs) results = recover_lumped_vortex_solution( x, (vortex_family,), self.geometry, freestream, self.registry, self.backend, self.body_reference, point_particles, ) return x, results