| name | define-domains |
| description | Create and manipulate domains for PINA physics-driven problems. Covers domain types (Cartesian, Ellipsoid, Simplex), set operations, partial/update methods, and domain discretisation. |
| license | MIT |
| compatibility | opencode, codex, claude |
| metadata | {"audience":"users","workflow":"problem-creation"} |
Define Domains for a PINA Problem
[!IMPORTANT]
Read RULES.md before using this skill — it applies to all skills.
This is a sub-skill of create-problem. Load the entry-point skill first.
Use this skill to create spatial, temporal, and parameter domains, and to
discretise them for training.
Step 1 — Create domains
For each domain type, ask:
What are the variable names and their ranges?
If the user does not specify a domain, ask for:
- Variable name (e.g.
x)
- Lower bound (e.g.
0)
- Upper bound (e.g.
1)
Domain types available
from pina.domain import CartesianDomain, EllipsoidDomain, SimplexDomain
| Domain type | Description | Example |
|---|
CartesianDomain | Hyperrectangle (most common) | CartesianDomain({"x": [0, 1], "y": [0, 1]}) |
EllipsoidDomain | Hyperellipsoid | EllipsoidDomain({"x": [0, 1], "y": [0, 1]}) |
SimplexDomain | Simplex defined by vertices | SimplexDomain(vertices=[...]) |
CartesianDomain supports sampling modes: random, grid, chebyshev,
latin/lh.
Set operations on domains
from pina.domain import Union, Intersection, Difference, Exclusion
combined = Union(domain_a, domain_b)
overlap = Intersection(domain_a, domain_b)
subtracted = Difference(domain_a, domain_b)
excluded = Exclusion(domain_a, domain_b)
Step 2 — Domain methods for problem setup
partial() — extract boundary
Creates a sub-domain representing the boundary of the parent domain:
spatial_domain = CartesianDomain({"x": [0, 1], "y": [0, 1]})
boundary = spatial_domain.partial()
update() — combine domains (space + time)
Creates the Cartesian product of two domains. Essential for space-time problems:
spatial_domain = CartesianDomain({"x": [-1, 1]})
temporal_domain = CartesianDomain({"t": [0, 1]})
interior = spatial_domain.update(temporal_domain)
Common patterns:
domains = {
"D": spatial_domain.update(temporal_domain),
"ic": spatial_domain.update(CartesianDomain({"t": 0})),
"boundary": spatial_domain.partial().update(temporal_domain),
}
Step 3 — Discretise domains (sampling)
After the problem class is fully defined, sample points from each domain:
problem.discretise_domain(n=5000, mode="random", domains=["D"])
problem.discretise_domain(n=500, mode="random", domains=["boundary"])
| Mode | Description |
|---|
"random" | Uniform random sampling (default) |
"latin"/"lh" | Latin hypercube sampling |
"grid" | Regular grid points |
"chebyshev" | Chebyshev nodes (good for polynomials) |
After all domains are discretised:
problem.move_discretisation_into_conditions()
assert problem.are_all_domains_discretised
Checklist