Skip to content

Commit cf4310f

Browse files
committed
Implement @ operator for dot product
1 parent f264159 commit cf4310f

File tree

10 files changed

+31
-24
lines changed

10 files changed

+31
-24
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ For example, to simulate incompressible hydrodynamics in a ball, you can symboli
2727

2828
```python
2929
problem.add_equation("div(u) + tau_p = 0")
30-
problem.add_equation("dt(u) - nu*lap(u) + grad(p) + lift(tau_u) = - dot(u,grad(u))")
30+
problem.add_equation("dt(u) - nu*lap(u) + grad(p) + lift(tau_u) = - u@grad(u)")
3131
problem.add_equation("u(r=1) = 0")
3232
problem.add_equation("integ(p) = 0")
3333
```

dedalus/core/field.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ def __rmul__(self, other):
110110
from .arithmetic import Multiply
111111
return Multiply(other, self)
112112

113+
def __matmul__(self, other):
114+
# Call: self @ other
115+
from .arithmetic import DotProduct
116+
return DotProduct(self, other)
117+
118+
def __rmathmul__(self, other):
119+
# Call: other @ self
120+
from .arithmetic import DotProduct
121+
return DotProduct(other, self)
122+
113123
def __truediv__(self, other):
114124
# Call: self / other
115125
return (self * other**(-1))

docs/pages/changes_from_v2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Vector calculus operators
9696
Along with vector and tensor-valued fields, vectorial differential operators (``Gradient``, ``Divergence``, ``Curl``, and ``Laplacian``) are now available.
9797
This dramatically simplifies the symbolic specification of vector and tensor-valued equations, particularly in curvilinear coordinates.
9898
Individual partial derivative operators are now usually just used in 1D equations.
99-
Vector algebra operations (dot products, cross products, and outer products) are also available through the ``Dot``, ``Cross``, and regular multiplication operators.
99+
Vector algebra operations (dot products, cross products, and outer products) are also available through the ``Dot()`` or ``@``, ``Cross()``, and ``*`` operators.
100100

101101
For instance, an operator for computing the strain rate tensor from a velocity field can be created like:
102102

docs/pages/gauge_conditions.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ At first glance, we might think to build the problem variables and specify the e
1818
# Problem
1919
problem = d3.IVP([p, u], namespace=locals())
2020
problem.add_equation("div(u) = 0")
21-
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - dot(u,grad(u))")
21+
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - u@grad(u)")
2222
2323
This formulation produces square matrices (same number of modes in the equations as the variables), but they are not all nonsingular.
2424
The problem is that the pressure gauge is undetermined -- any constant can be added to the pressure without affecting any of the equations.
@@ -42,7 +42,7 @@ Another option is to expand the system by adding a spatially-constant variable (
4242
# Problem
4343
problem = d3.IVP([p, u, tau_p], namespace=locals())
4444
problem.add_equation("div(u) + tau_p = 0")
45-
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - dot(u,grad(u))")
45+
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - u@grad(u)")
4646
problem.add_equation("integ(p) = 0")
4747
4848
We've added a single additional degree of freedom to the variables and a single additional constraint, so this system is still square.

examples/ivp_2d_rayleigh_benard/rayleigh_benard.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
# First-order form: "lap(f)" becomes "div(grad_f)"
7272
problem = d3.IVP([p, b, u, tau_p, tau_b1, tau_b2, tau_u1, tau_u2], namespace=locals())
7373
problem.add_equation("trace(grad_u) + tau_p = 0")
74-
problem.add_equation("dt(b) - kappa*div(grad_b) + lift(tau_b2) = - dot(u,grad(b))")
75-
problem.add_equation("dt(u) - nu*div(grad_u) + grad(p) - b*ez + lift(tau_u2) = - dot(u,grad(u))")
74+
problem.add_equation("dt(b) - kappa*div(grad_b) + lift(tau_b2) = - u@grad(b)")
75+
problem.add_equation("dt(u) - nu*div(grad_u) + grad(p) - b*ez + lift(tau_u2) = - u@grad(u)")
7676
problem.add_equation("b(z=0) = Lz")
7777
problem.add_equation("u(z=0) = 0")
7878
problem.add_equation("b(z=Lz) = 0")
@@ -100,7 +100,7 @@
100100

101101
# Flow properties
102102
flow = d3.GlobalFlowProperty(solver, cadence=10)
103-
flow.add_property(np.sqrt(d3.dot(u,u))/nu, name='Re')
103+
flow.add_property(np.sqrt(u@u)/nu, name='Re')
104104

105105
# Main loop
106106
startup_iter = 10

examples/ivp_2d_shear_flow/shear_flow.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@
5656

5757
# Problem
5858
problem = d3.IVP([u, s, p, tau_p], namespace=locals())
59-
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - dot(u,grad(u))")
60-
problem.add_equation("dt(s) - D*lap(s) = - dot(u,grad(s))")
59+
problem.add_equation("dt(u) + grad(p) - nu*lap(u) = - u@grad(u)")
60+
problem.add_equation("dt(s) - D*lap(s) = - u@grad(s)")
6161
problem.add_equation("div(u) + tau_p = 0")
6262
problem.add_equation("integ(p) = 0") # Pressure gauge
6363

@@ -87,7 +87,7 @@
8787

8888
# Flow properties
8989
flow = d3.GlobalFlowProperty(solver, cadence=10)
90-
flow.add_property(d3.dot(u,ez)**2, name='w2')
90+
flow.add_property((u@ez)**2, name='w2')
9191

9292
# Main loop
9393
try:

examples/ivp_ball_internally_heated_convection/internally_heated_convection.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
problem = d3.IVP([p, u, T, tau_p, tau_u, tau_T], namespace=locals())
8181
problem.add_equation("div(u) + tau_p = 0")
8282
problem.add_equation("dt(u) - nu*lap(u) + grad(p) - r_vec*T + lift(tau_u) = - cross(curl(u),u)")
83-
problem.add_equation("dt(T) - kappa*lap(T) + lift(tau_T) = - dot(u,grad(T)) + kappa*T_source")
83+
problem.add_equation("dt(T) - kappa*lap(T) + lift(tau_T) = - u@grad(T) + kappa*T_source")
8484
problem.add_equation("shear_stress = 0") # Stress free
8585
problem.add_equation("radial(u(r=1)) = 0") # No penetration
8686
problem.add_equation("radial(grad(T)(r=1)) = -2")
@@ -117,7 +117,7 @@
117117

118118
# Flow properties
119119
flow = d3.GlobalFlowProperty(solver, cadence=10)
120-
flow.add_property(d3.dot(u,u), name='u2')
120+
flow.add_property(u@u, name='u2')
121121

122122
# Main loop
123123
try:

examples/ivp_disk_libration/libration.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
# Problem
6767
problem = d3.IVP([p, u, tau_u, tau_p], time=t, namespace=locals())
6868
problem.add_equation("div(u) + tau_p = 0")
69-
problem.add_equation("dt(u) - nu*lap(u) + grad(p) + lift(tau_u) = - dot(u, grad(u0)) - dot(u0, grad(u))")
69+
problem.add_equation("dt(u) - nu*lap(u) + grad(p) + lift(tau_u) = - u@grad(u0) - u0@grad(u)")
7070
problem.add_equation("u(r=1) = 0")
7171
problem.add_equation("integ(p) = 0")
7272

@@ -82,11 +82,11 @@
8282
snapshots = solver.evaluator.add_file_handler('snapshots', sim_dt=0.1, max_writes=20)
8383
snapshots.add_task(-d3.div(d3.skew(u)), scales=(4, 1), name='vorticity')
8484
scalars = solver.evaluator.add_file_handler('scalars', sim_dt=0.01)
85-
scalars.add_task(d3.integ(0.5*d3.dot(u,u)), name='KE')
85+
scalars.add_task(d3.integ(0.5*u@u), name='KE')
8686

8787
# Flow properties
8888
flow = d3.GlobalFlowProperty(solver, cadence=100)
89-
flow.add_property(d3.dot(u,u), name='u2')
89+
flow.add_property(u@u, name='u2')
9090

9191
# Main loop
9292
try:

examples/ivp_shell_convection/shell_convection.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@
7373
# Problem
7474
problem = d3.IVP([p, b, u, tau_p, tau_b1, tau_b2, tau_u1, tau_u2], namespace=locals())
7575
problem.add_equation("trace(grad_u) + tau_p = 0")
76-
problem.add_equation("dt(b) - kappa*div(grad_b) + lift(tau_b2) = - dot(u,grad(b))")
77-
problem.add_equation("dt(u) - nu*div(grad_u) + grad(p) - b*er + lift(tau_u2) = - dot(u,grad(u))")
76+
problem.add_equation("dt(b) - kappa*div(grad_b) + lift(tau_b2) = - u@grad(b)")
77+
problem.add_equation("dt(u) - nu*div(grad_u) + grad(p) - b*er + lift(tau_u2) = - u@grad(u)")
7878
problem.add_equation("b(r=Ri) = 1")
7979
problem.add_equation("u(r=Ri) = 0")
8080
problem.add_equation("b(r=Ro) = 0")
@@ -91,10 +91,7 @@
9191
b['g'] += (Ri - Ri*Ro/r) / (Ri - Ro) # Add linear background
9292

9393
# Analysis
94-
db = b# - d3.Average(b, coords.S2coordsys)
95-
flux = d3.dot(er, -kappa*d3.grad(db) + db*u)
96-
#db.store_last = True
97-
flux.store_last = True
94+
flux = er @ (-kappa*d3.grad(b) + u*b)
9895
snapshots = solver.evaluator.add_file_handler('snapshots', sim_dt=10, max_writes=10)
9996
snapshots.add_task(b(r=(Ri+Ro)/2), scales=dealias, name='bmid')
10097
snapshots.add_task(flux(r=Ro), scales=dealias, name='flux_r_outer')
@@ -109,7 +106,7 @@
109106

110107
# Flow properties
111108
flow = d3.GlobalFlowProperty(solver, cadence=10)
112-
flow.add_property(np.sqrt(d3.dot(u,u))/nu, name='Re')
109+
flow.add_property(np.sqrt(u@u)/nu, name='Re')
113110

114111
# Main loop
115112
try:

examples/ivp_sphere_shallow_water/shallow_water.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
# Initial conditions: balanced height
6666
c = dist.Field(name='c')
6767
problem = d3.LBVP([h, c], namespace=locals())
68-
problem.add_equation("g*lap(h) + c = - div(dot(u, grad(u)) + 2*Omega*zcross(u))")
68+
problem.add_equation("g*lap(h) + c = - div(u@grad(u) + 2*Omega*zcross(u))")
6969
problem.add_equation("ave(h) = 0")
7070
solver = problem.build_solver()
7171
solver.solve()
@@ -79,7 +79,7 @@
7979

8080
# Problem
8181
problem = d3.IVP([u, h], namespace=locals())
82-
problem.add_equation("dt(u) + nu*lap(lap(u)) + g*grad(h) + 2*Omega*zcross(u) = - dot(u, grad(u))")
82+
problem.add_equation("dt(u) + nu*lap(lap(u)) + g*grad(h) + 2*Omega*zcross(u) = - u@grad(u)")
8383
problem.add_equation("dt(h) + nu*lap(lap(h)) + H*div(u) = - div(h*u)")
8484

8585
# Solver

0 commit comments

Comments
 (0)