poisson.py

In this script we solve Poisson’s equation Δu = 1 subject to boundary constraints, using the fact that the solution to the strong form minimizes the functional ∫ .5 ‖∇u‖² - u. The domain is a unit square, and the solution is constrained to zero along the entire boundary.

 8from nutils import mesh, function, solver, export, cli, testing
 9
10
11def main(nelems: int):
12    '''
13    Poisson's equation on a unit square.
14
15    .. arguments::
16
17       nelems [10]
18         Number of elements along edge.
19    '''
20
21    domain, x = mesh.unitsquare(nelems, etype='square')
22    u = function.dotarg('udofs', domain.basis('std', degree=1))
23    g = u.grad(x)
24    J = function.J(x)
25    cons = solver.optimize('udofs,',
26                           domain.boundary.integral(u**2 * J, degree=2), droptol=1e-12)
27    args = solver.optimize('udofs,',
28                            domain.integral((g @ g / 2 - u) * J, degree=1), constrain=cons)
29    bezier = domain.sample('bezier', 3)
30    x, u = bezier.eval([x, u], **args)
31    export.triplot('u.png', x, u, tri=bezier.tri, hull=bezier.hull)
32
33    return args['udofs']

If the script is executed (as opposed to imported), nutils.cli.run() calls the main function with arguments provided from the command line. To keep with the default arguments simply run python3 poisson.py (view log).

40if __name__ == '__main__':
41    cli.run(main)

Once a simulation is developed and tested, it is good practice to save a few strategic return values for regression testing. The nutils.testing module, which builds on the standard unittest framework, facilitates this by providing nutils.testing.TestCase.assertAlmostEqual64() for the embedding of desired results as compressed base64 data.

50class test(testing.TestCase):
51
52    def test_default(self):
53        udofs = main(nelems=10)
54        self.assertAlmostEqual64(udofs, '''
55            eNp9zrENwCAMBEBGYQJ444o2ozAAYgFmYhLEFqxAmye1FUtf+PSy7Jw9J6yoKGiMYsUTrq44kaVKZ7JM
56            +lWlDdlymEFXXC2o3H1C8mmzXz5t6OwhPfTDO+2na9+1f7D/teYFdsk5vQ==''')