DeepONet
popinn.DeepONet
¤
Deep Operator Network consisting of a single trunk network and a branch network for each auxiliary input.
The trunk and branch networks are all equinox.nn.MLP.
The final model output is constructed by taking the sum over an element-wise product between the trunk \(tr(\vec{x})\) and branch \(br_j(\vec{\mu_j})\) outputs, plus a learnable bias \(b\). For example, for two branches, the output is:
The trunk and branch outputs must therefore all be the same dimension, which is specified
by branch_trunk_output_dim on initialization.
The auxiliary inputs are functions evaluated at a fixed set of sensor points, e.g. the forcing term \(F(t)\) in the PDE:
and the initial condition \(u_0(x)\) that may depend on \(\beta\), \(\nu\), and \(\rho\).
Example usage:
import jax.numpy as jnp
import popinn
beta = jnp.array(1.)
nu = jnp.array(2.)
rho = jnp.array(3.)
ts = jnp.linspace(0,1,10)
F_t = # some function that depends t
F_t_vals = F_t(ts)
xs = jnp.linspace(0,1,10)
u_0 = # some function that depends on x and may depend on beta, nu, and/or rho
u_0_vals = u_0(xs)
x = jnp.array(1.)
t = jnp.array(1.)
# initialize
model = popinn.DeepONet(
branch_input_dim = (xs.shape[0], ts.shape[0]),
trunk_input_dim = 2,
branch_depth = (5, 5)
)
# evaluate
u = model(x, t, (u_0_vals, F_t_vals))
See Lu et al. (2020) for more details on DeepONets.
Source code in src/popinn/models.py
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | |
__init__(key, branch_input_dim, trunk_input_dim, branch_trunk_output_dim=100, branch_depth=(5,), trunk_depth=3, branch_kwargs={'activation': jnp.tanh, 'final_activation': jnp.tanh}, trunk_kwargs={'activation': jnp.tanh, 'final_activation': jnp.tanh}, bias_min=-1.0, bias_max=1.0)
¤
Build the branch networks, trunk, and bias.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
jax.random.PRNGKey
|
PRNG key. |
required |
branch_input_dim
|
tuple[int]
|
Tuple containing the sensor count for each branch. |
required |
trunk_input_dim
|
int
|
Number of coordinate inputs to the trunk. |
required |
branch_trunk_output_dim
|
int
|
The shared hidden and output width of the trunk and branch networks. |
100
|
branch_depth
|
tuple
|
Number of hidden layers per branch; one entry per branch (indexed alongside branch_input_dim). |
(5,)
|
trunk_depth
|
int
|
Number of hidden layers in the trunk. |
3
|
branch_kwargs
|
dict
|
Extra kwargs forwarded to every branch MLP. |
{'activation': jax.numpy.tanh, 'final_activation': jax.numpy.tanh}
|
trunk_kwargs
|
dict
|
Extra kwargs forwarded to the trunk MLP. |
{'activation': jax.numpy.tanh, 'final_activation': jax.numpy.tanh}
|
Source code in src/popinn/models.py
__call__(*args)
¤
Evaluate the model at one point.
Coordinates are passed as individual scalars; auxiliary inputs are passed as a single trailing tuple:
model(x, t, (a, b)) # x & t are the coordinates; a & b are the auxiliary inputs.
For models with no auxiliary inputs, e.g. popinn.PINN, the auxiliary tuple
can be empty, or omitted completely:
model(x, t, ()) # explicit empty aux -- equivalent to:
model(x, t) # no aux
Note the auxiliary inputs must be a tuple specifically, not a list or array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
The coordinate scalars, optionally followed by the aux tuple. |
()
|
Returns:
| Type | Description |
|---|---|
jaxtyping.Float[jax.Array, '']
|
The model output as a scalar JAX array. |
Source code in src/popinn/models.py
D(*argnums)
¤
Build the derivative of the model with respect to one or more coordinates.
Returns a function with the same call signature as the model whose output is the requested derivative.
Derivative syntax
Each entry of argnums indexes a coordinate argument (0 -> first coordinate, 1 -> second, ...);
chaining differentiates repeatedly. For example, for a model with two coordinates x & t,
derivatives are taken & evaluated like:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*argnums
|
int
|
Coordinate indices to differentiate with respect to, applied left to right. |
()
|
Returns:
| Type | Description |
|---|---|
collections.abc.Callable
|
A function with the same signature as the model that returns the requested scalar derivative. |