- 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](../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:
1. Variable name (e.g. `x`)
2. Lower bound (e.g. `0`)
3. Upper bound (e.g. `1`)
### Domain types available
```python
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
```python
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:
```python
spatial_domain = CartesianDomain({"x": [0, 1], "y": [0, 1]})
boundary = spatial_domain.partial() # boundary of the square
```
### `update()` — combine domains (space + time)
Creates the Cartesian product of two domains. Essential for space-time problems:
```python
spatial_domain = CartesianDomain({"x": [-1, 1]})
temporal_domain = CartesianDomain({"t": [0, 1]})
interior = spatial_domain.update(temporal_domain)
# Equivalent to CartesianDomain({"x": [-1, 1], "t": [0, 1]})
```
Common patterns:
```python
domains = {
"D": spatial_domain.update(temporal_domain), # space-time interior
"ic": spatial_domain.update(CartesianDomain({"t": 0})), # initial condition
"boundary": spatial_domain.partial().update(temporal_domain), # moving boundary
}
```
## Step 3 — Discretise domains (sampling)
After the problem class is fully defined, sample points from each domain:
```python
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:
```python
problem.move_discretisation_into_conditions()
assert problem.are_all_domains_discretised
```
## Checklist
- [ ] All required domains are defined (`spatial_domain`, `temporal_domain`,
`parameter_domain`, or `unknown_parameter_domain` as appropriate)
- [ ] `domains` dict contains a key for every domain referenced in conditions
- [ ] For space-time problems: `spatial_domain.update(temporal_domain)` used
to build the interior domain
- [ ] For boundary conditions: `spatial_domain.partial()` used correctly
- [ ] `problem.discretise_domain(n=..., mode=..., domains=...)` called for
each physics domain
- [ ] `problem.move_discretisation_into_conditions()` called before training
- [ ] `problem.are_all_domains_discretised` is `True` after discretisation
Voir sur GitHub