Source code for sft_wick.fields

"""Field declarations and field operators.

A Field is a declaration (phi, psi) with metadata.
A FieldOperator is a specific instance with bound component index and spatial argument.
"""

from __future__ import annotations

import itertools
from dataclasses import dataclass
from enum import Enum
from typing import Optional


[docs] class FieldType(Enum): PHYSICAL = "physical" # phi RESPONSE = "response" # psi
# Global counter for unique FieldOperator IDs _uid_counter = itertools.count()
[docs] def reset_uid_counter() -> None: """Reset the UID counter. Useful for reproducible tests.""" global _uid_counter _uid_counter = itertools.count()
[docs] @dataclass(frozen=True) class Field: """Declaration of a field species. Examples: phi = Field('phi', FieldType.PHYSICAL, n_components=3) psi = Field('psi', FieldType.RESPONSE) # scalar (n_components=1) """ name: str field_type: FieldType n_components: int = 1 def __init__(self, name: str, field_type: str | FieldType, n_components: int = 1): object.__setattr__(self, "name", name) if isinstance(field_type, str): field_type = FieldType(field_type) object.__setattr__(self, "field_type", field_type) object.__setattr__(self, "n_components", n_components) def __call__(self, *args: str) -> FieldOperator: """Create a field operator with bound indices. For multi-component (n_components > 1): phi('a', 'x') -> phi_a(x) For scalar (n_components == 1): phi('x') -> phi(x) """ if self.is_scalar: if len(args) != 1: raise ValueError( f"Scalar field '{self.name}' expects 1 argument (spatial), " f"got {len(args)}" ) return FieldOperator( field=self, component_index=None, spatial_arg=args[0], uid=next(_uid_counter), ) else: if len(args) != 2: raise ValueError( f"Multi-component field '{self.name}' expects 2 arguments " f"(component, spatial), got {len(args)}" ) return FieldOperator( field=self, component_index=args[0], spatial_arg=args[1], uid=next(_uid_counter), ) @property def is_scalar(self) -> bool: return self.n_components == 1 @property def is_physical(self) -> bool: return self.field_type == FieldType.PHYSICAL @property def is_response(self) -> bool: return self.field_type == FieldType.RESPONSE
[docs] @dataclass(frozen=True) class FieldOperator: """A field at a specific point with a specific component index. Each instance has a unique uid to distinguish identical-looking operators (e.g., two phi_a(x) in the same product). """ field: Field component_index: Optional[str] spatial_arg: str uid: int @property def field_type(self) -> FieldType: return self.field.field_type @property def is_physical(self) -> bool: return self.field.is_physical @property def is_response(self) -> bool: return self.field.is_response def __repr__(self) -> str: if self.component_index is not None: return f"{self.field.name}_{self.component_index}({self.spatial_arg})" return f"{self.field.name}({self.spatial_arg})"