Exemplo n.º 1
0
def test_laplace():

    laplace = lambda u, x, y: diff(u, x, order=2) + diff(u, y, order=2)
    bc = DirichletBVP2D(x_min=0,
                        x_min_val=lambda y: torch.sin(np.pi * y),
                        x_max=1,
                        x_max_val=lambda y: 0,
                        y_min=0,
                        y_min_val=lambda x: 0,
                        y_max=1,
                        y_max_val=lambda x: 0)

    net = FCNN(n_input_units=2, n_hidden_units=32, n_hidden_layers=1)
    solution_neural_net_laplace, _ = solve2D(
        pde=laplace,
        condition=bc,
        xy_min=(0, 0),
        xy_max=(1, 1),
        net=net,
        max_epochs=300,
        train_generator=ExampleGenerator2D((32, 32), (0, 0), (1, 1),
                                           method='equally-spaced-noisy',
                                           xy_noise_std=(0.01, 0.01)),
        batch_size=64)
    solution_analytical_laplace = lambda x, y: np.sin(np.pi * y) * np.sinh(
        np.pi * (1 - x)) / np.sinh(np.pi)

    xs, ys = np.linspace(0, 1, 101), np.linspace(0, 1, 101)
    xx, yy = np.meshgrid(xs, ys)
    sol_net = solution_neural_net_laplace(xx, yy, as_type='np')
    sol_ana = solution_analytical_laplace(xx, yy)
    assert isclose(sol_net, sol_ana, atol=0.01).all()
    print('Laplace test passed.')
Exemplo n.º 2
0
def test_monitor():

    laplace = lambda u, x, y: diff(u, x, order=2) + diff(u, y, order=2)
    bc = DirichletBVP2D(x_min=0,
                        x_min_val=lambda y: torch.sin(np.pi * y),
                        x_max=1,
                        x_max_val=lambda y: 0,
                        y_min=0,
                        y_min_val=lambda x: 0,
                        y_max=1,
                        y_max_val=lambda x: 0)

    net = FCNN(n_input_units=2, n_hidden_units=32, n_hidden_layers=1)
    solution_neural_net_laplace, _ = solve2D(
        pde=laplace,
        condition=bc,
        xy_min=(0, 0),
        xy_max=(1, 1),
        net=net,
        max_epochs=3,
        train_generator=ExampleGenerator2D((32, 32), (0, 0), (1, 1),
                                           method='equally-spaced-noisy'),
        batch_size=64,
        monitor=Monitor2D(check_every=1, xy_min=(0, 0), xy_max=(1, 1)))
    print('Monitor test passed.')
Exemplo n.º 3
0
def laplacian_spherical(u, r, theta, phi):
    """a helper function that computes the Laplacian in spherical coordinates
    """
    r_component = diff(u * r, r, order=2) / r
    theta_component = diff(torch.sin(theta) * diff(u, theta),
                           theta) / (r**2 * torch.sin(theta))
    phi_component = diff(u, phi, order=2) / (r**2 * torch.sin(theta)**2)
    return r_component + theta_component + phi_component
Exemplo n.º 4
0
def test_cylindrical_laplacian(u, x):
    out = cylindrical_laplacian(u, *x)
    rho, phi, z = x

    assert torch.allclose(
        out,
        diff(rho * diff(u, rho), rho) / rho + diff(u, phi, order=2) / rho ** 2 + diff(u, z, order=2)
    )
Exemplo n.º 5
0
def test_robin_2d(ones):
    x0, x1 = 0, 1
    y0, y1 = 0, 1

    fd_x = FCNNSplitInput(2, 1)
    fd_y = FCNNSplitInput(2, 1)
    fr_x = FCNNSplitInput(2, 1)
    a_x, b_x = 1.0, 2.0
    fr_y = FCNNSplitInput(2, 1)
    a_y, b_y = 3.0, 4.0

    comp_x1 = ConditionComponent(x1,
                                 f_dirichlet=fd_x,
                                 f_neumann=None,
                                 coord_index=0)
    comp_y0 = ConditionComponent(y0,
                                 f_dirichlet=fd_y,
                                 f_neumann=None,
                                 coord_index=1)
    comp_x0 = RobinConditionComponent(x0, a_x, b_x, fr_x, coord_index=0)
    comp_y1 = RobinConditionComponent(y1, a_y, b_y, fr_y, coord_index=1)

    condition = ComposedCondition([comp_x0, comp_x1, comp_y0, comp_y1])
    net = FCNN(2, 1)

    x = (x1 - EPS) * ones
    y = linspace_without_endpoints(y0, y1, N,
                                   requires_grad=True).reshape(-1, 1)
    u = condition.enforce(net, x, y)
    assert all_close(u, fd_x(x, y), rtol=1e-4)

    x = linspace_without_endpoints(x0, x1, N,
                                   requires_grad=True).reshape(-1, 1)
    y = (y0 + EPS) * ones
    u = condition.enforce(net, x, y)
    assert all_close(u, fd_y(x, y), rtol=1e-4)

    x = (x0 + EPS) * ones
    y = linspace_without_endpoints(y0, y1, N,
                                   requires_grad=True).reshape(-1, 1)
    u = condition.enforce(net, x, y)
    pred = a_x * u + b_x * diff(u, x)
    true = fr_x(x, y)
    assert all_close(pred, true, rtol=1e-3)

    x = linspace_without_endpoints(x0, x1, N,
                                   requires_grad=True).reshape(-1, 1)
    y = (y1 - EPS) * ones
    u = condition.enforce(net, x, y)
    pred = a_y * u + b_y * diff(u, y)
    true = fr_y(x, y)
    assert all_close(pred, true, rtol=1e-3)
Exemplo n.º 6
0
def solver():
    return Solver1D(
        ode_system=lambda u, t: [u + diff(u, t)],
        conditions=[NoCondition()],
        t_min=0.0,
        t_max=1.0,
    )
Exemplo n.º 7
0
def test_set_criterion_callback_reset(solver):
    coords = torch.rand(10, 1, requires_grad=True)
    funcs = torch.exp(coords * 1.01)
    residuals = diff(funcs, coords) - funcs

    # w/o resetting
    callback = SetCriterion(criterion='l1', reset=False)
    callback(solver)
    assert torch.allclose(solver.criterion(residuals, funcs, coords),
                          torch.abs(residuals).mean())

    solver._set_criterion('l2')
    callback(solver)
    assert torch.allclose(solver.criterion(residuals, funcs, coords),
                          (residuals**2).mean())

    # w/ resetting
    callback = SetCriterion(criterion='l1', reset=True)
    callback(solver)
    assert torch.allclose(solver.criterion(residuals, funcs, coords),
                          torch.abs(residuals).mean())

    solver._set_criterion('l2')
    callback(solver)
    assert torch.allclose(solver.criterion(residuals, funcs, coords),
                          torch.abs(residuals).mean())
def test_laplacian(n_dim):
    xs = [torch.rand(N_SAMPLES, 1, requires_grad=True) for _ in range(n_dim)]
    net = FCNN(n_dim, 1)
    u = net(torch.cat(xs, dim=1))
    ans = torch.cat([diff(u, x, order=2) for x in xs], dim=1).sum(dim=1,
                                                                  keepdim=True)
    output = laplacian(u, *xs)
    assert (ans == output).all()
Exemplo n.º 9
0
def test_set_criterion_callback_polymorphism(solver, criterion):
    coords = torch.rand(10, 1, requires_grad=True)
    funcs = torch.exp(coords * 1.01)
    residuals = diff(funcs, coords) - funcs

    callback = SetCriterion(criterion=criterion)
    callback(solver)
    assert torch.allclose(solver.criterion(residuals, funcs, coords),
                          torch.abs(residuals).mean())
Exemplo n.º 10
0
    def get_dn(self, net, *x):
        projection = self._get_projection(*x)
        p_tensor = torch.cat(projection, dim=1)

        output_val = net(p_tensor)
        normal_der = diff(output_val, projection[self.idx])
        R = (self.f(*projection) - self.a * output_val -
             self.b * normal_der) / 2

        return R / self.a, R / self.b
Exemplo n.º 11
0
def test_ode_system():

    parametric_circle = lambda x1, x2, t: [diff(x1, t) - x2, diff(x2, t) + x1]
    init_vals_pc = [IVP(t_0=0.0, x_0=0.0), IVP(t_0=0.0, x_0=1.0)]

    solution_pc, _ = solve_system(
        ode_system=parametric_circle,
        conditions=init_vals_pc,
        t_min=0.0,
        t_max=2 * np.pi,
        max_epochs=5000,
    )

    ts = np.linspace(0, 2 * np.pi, 100)
    x1_net, x2_net = solution_pc(ts, as_type='np')
    x1_ana, x2_ana = np.sin(ts), np.cos(ts)
    assert isclose(x1_net, x1_ana, atol=0.1).all()
    assert isclose(x2_net, x2_ana, atol=0.1).all()
    print('solve_system basic test passed.')
def test_div(n_dim):
    xs = [torch.rand(N_SAMPLES, 1, requires_grad=True) for _ in range(n_dim)]
    nets = [FCNN(n_dim, 1) for _ in range(n_dim)]
    us = [net(torch.cat(xs, dim=1)) for net in nets]

    grads = [diff(u, x) for u, x in zip(us, xs)]
    ans = torch.cat(grads, dim=1).sum(dim=1, keepdim=True)

    output = div(*us, *xs)
    assert (output == ans).all()
Exemplo n.º 13
0
def test_monitor():
    exponential = lambda x, t: diff(x, t) - x
    init_val_ex = IVP(t_0=0.0, x_0=1.0)
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           max_epochs=3,
                           monitor=Monitor(t_min=0.0, t_max=2.0,
                                           check_every=1))
    print('Monitor test passed.')
Exemplo n.º 14
0
def get_rfx(n_input, n_output, n_equation):
    coords = [torch.rand((N, 1), requires_grad=True) for _ in range(n_input)]
    coords_tensor = torch.cat(coords, dim=1)
    funcs = [
        torch.sigmoid(torch.sum(coords_tensor, dim=1, keepdim=True))
        for _ in range(n_output)
    ]
    residual = [
        diff(funcs[0], coords[0]) + funcs[0] for _ in range(n_equation)
    ]
    residual = torch.cat(residual, dim=1)
    return residual, funcs, coords
Exemplo n.º 15
0
def test_condition_component_3d_get_dn(w0, f, g, xyz, net_31, coord_index):
    component = ConditionComponent3D(w0, f, g, coord_index=coord_index)
    p = component._get_projection(*xyz)
    D, N = component.get_dn(net_31, *xyz)
    p_tensor = torch.cat(p, dim=1)
    assert all_close(D, f(*p) - net_31(p_tensor))
    assert all_close(N, g(*p) - diff(net_31(p_tensor), p[coord_index]))

    component = ConditionComponent3D(w0, None, g, coord_index=coord_index)
    p = component._get_projection(*xyz)
    D, N = component.get_dn(net_31, *xyz)
    p_tensor = torch.cat(p, dim=1)
    assert all_close(D, 0.0)
    assert all_close(N, g(*p) - diff(net_31(p_tensor), p[coord_index]))

    component = ConditionComponent3D(w0, f, None, coord_index=coord_index)
    p = component._get_projection(*xyz)
    D, N = component.get_dn(net_31, *xyz)
    p_tensor = torch.cat(p, dim=1)
    assert all_close(D, f(*p) - net_31(p_tensor))
    assert all_close(N, 0.0)
Exemplo n.º 16
0
def test_heat():

    k, L, T = 0.3, 2, 3
    heat = lambda u, x, t: diff(u, t) - k * diff(u, x, order=2)

    ibvp = IBVP1D(x_min=0,
                  x_min_val=lambda t: 0,
                  x_max=L,
                  x_max_val=lambda t: 0,
                  t_min=0,
                  t_min_val=lambda x: torch.sin(np.pi * x / L))
    net = FCNN(n_input_units=2, n_hidden_units=32, n_hidden_layers=1)

    def mse(u, x, y):
        true_u = torch.sin(np.pi * y) * torch.sinh(np.pi *
                                                   (1 - x)) / np.sinh(np.pi)
        return torch.mean((u - true_u)**2)

    solution_neural_net_heat, _ = solve2D(pde=heat,
                                          condition=ibvp,
                                          xy_min=(0, 0),
                                          xy_max=(L, T),
                                          net=net,
                                          max_epochs=300,
                                          train_generator=ExampleGenerator2D(
                                              (32, 32), (0, 0), (L, T),
                                              method='equally-spaced-noisy'),
                                          batch_size=64,
                                          metrics={'mse': mse})
    solution_analytical_heat = lambda x, t: np.sin(np.pi * x / L) * np.exp(
        -k * np.pi**2 * t / L**2)

    xs = np.linspace(0, L, 101)
    ts = np.linspace(0, T, 101)
    xx, tt = np.meshgrid(xs, ts)
    make_animation(solution_neural_net_heat, xs, ts)  # test animation
    sol_ana = solution_analytical_heat(xx, tt)
    sol_net = solution_neural_net_heat(xx, tt, as_type='np')
    assert isclose(sol_net, sol_ana, atol=0.01).all()
    print('Heat test passed.')
Exemplo n.º 17
0
def test_ode_ivp():
    oscillator = lambda x, t: diff(x, t, order=2) + x
    init_val_ho = IVP(t_0=0.0, x_0=0.0, x_0_prime=1.0)
    solution_ho, _ = solve(ode=oscillator,
                           condition=init_val_ho,
                           max_epochs=3000,
                           t_min=0.0,
                           t_max=2 * np.pi)
    ts = np.linspace(0, 2 * np.pi, 100)
    x_net = solution_ho(ts, as_type='np')
    x_ana = np.sin(ts)
    assert isclose(x_net, x_ana, atol=0.1).all()
    print('IVP basic test passed.')
Exemplo n.º 18
0
def test_ode_bvp():
    oscillator = lambda x, t: diff(x, t, order=2) + x
    bound_val_ho = DirichletBVP(t_0=0.0, x_0=0.0, t_1=1.5 * np.pi, x_1=-1.0)
    solution_ho, _ = solve(ode=oscillator,
                           condition=bound_val_ho,
                           max_epochs=3000,
                           t_min=0.0,
                           t_max=1.5 * np.pi)
    ts = np.linspace(0, 1.5 * np.pi, 100)
    x_net = solution_ho(ts, as_type='np')
    x_ana = np.sin(ts)
    assert isclose(x_net, x_ana, atol=0.1).all()
    print('BVP basic test passed.')
Exemplo n.º 19
0
def test_composed_condition_3d_single_component(w0, f, g, xyz, net_31,
                                                coord_index, ComponentClass,
                                                ConditionClass, k, detach):
    component = ComponentClass(w0, f, g, coord_index=coord_index)
    condition = ConditionClass(components=[component], k=k, detach=detach)
    xyz = list(xyz)
    xyz[coord_index] = torch.ones_like(xyz[coord_index],
                                       requires_grad=True) * (w0 + EPS)
    xyz_tensor = torch.cat(xyz, dim=1)

    u = condition.enforce(net_31, *xyz)
    assert all_close(u, f(*xyz), atol=1e-4, rtol=1e-2)
    assert all_close(diff(u, xyz[coord_index]), g(*xyz), atol=1e-4, rtol=1e-2)
Exemplo n.º 20
0
def test_cylindrical_curl(U, x):
    out_rho, out_phi, out_z = cylindrical_curl(*U, *x)
    rho, phi, z = x
    urho, uphi, uz = U

    assert torch.allclose(out_rho, diff(uz, phi) / rho - diff(uphi, z))
    assert torch.allclose(out_phi, diff(urho, z) - diff(uz, rho))
    assert torch.allclose(out_z, (diff(rho * uphi, rho) - diff(urho, phi)) / rho)
Exemplo n.º 21
0
def test_neumann_boundaries_2():

    k, L, T = 0.3, 2, 3
    heat = lambda u, x, t: diff(u, t) - k * diff(u, x, order=2)
    solution_analytical_heat = lambda x, t: np.sin(np.pi * x / L) * np.exp(
        -k * np.pi**2 * t / L**2)

    # Neumann on the left Dirichlet on the right
    ibvp = IBVP1D(
        x_min=0,
        x_min_prime=lambda t: np.pi / L * torch.exp(-k * np.pi**2 * t / L**2),
        x_max=L,
        x_max_val=lambda t: 0,
        t_min=0,
        t_min_val=lambda x: torch.sin(np.pi * x / L))

    net = FCNN(n_input_units=2, n_hidden_units=32, n_hidden_layers=1)

    solution_neural_net_heat, _ = solve2D(pde=heat,
                                          condition=ibvp,
                                          xy_min=(0, 0),
                                          xy_max=(L, T),
                                          net=net,
                                          max_epochs=300,
                                          train_generator=ExampleGenerator2D(
                                              (32, 32), (0, 0), (L, T),
                                              method='equally-spaced-noisy'),
                                          batch_size=64)

    xs = np.linspace(0, L, 101)
    ts = np.linspace(0, T, 101)
    xx, tt = np.meshgrid(xs, ts)
    make_animation(solution_neural_net_heat, xs, ts)  # test animation
    sol_ana = solution_analytical_heat(xx, tt)
    sol_net = solution_neural_net_heat(xx, tt, as_type='np')
    assert isclose(sol_net, sol_ana, atol=0.1).all()
    print('Neumann on the left Dirichlet on the right test passed.')
Exemplo n.º 22
0
def test_lotka_volterra():
    alpha, beta, delta, gamma = 1, 1, 1, 1
    lotka_volterra = lambda x, y, t: [
        diff(x, t) - (alpha * x - beta * x * y),
        diff(y, t) - (delta * x * y - gamma * y)
    ]
    init_vals_lv = [IVP(t_0=0.0, x_0=1.5), IVP(t_0=0.0, x_0=1.0)]
    nets_lv = [
        FCNN(n_hidden_units=32, n_hidden_layers=1, actv=SinActv),
        FCNN(n_hidden_units=32, n_hidden_layers=1, actv=SinActv)
    ]
    solution_lv, _ = solve_system(ode_system=lotka_volterra,
                                  conditions=init_vals_lv,
                                  t_min=0.0,
                                  t_max=12,
                                  nets=nets_lv,
                                  max_epochs=12000,
                                  monitor=Monitor(t_min=0.0,
                                                  t_max=12,
                                                  check_every=100))
    ts = np.linspace(0, 12, 100)
    prey_net, pred_net = solution_lv(ts, as_type='np')

    def dPdt(P, t):
        return [
            P[0] * alpha - beta * P[0] * P[1],
            delta * P[0] * P[1] - gamma * P[1]
        ]

    P0 = [1.5, 1.0]
    Ps = odeint(dPdt, P0, ts)
    prey_num = Ps[:, 0]
    pred_num = Ps[:, 1]
    assert isclose(prey_net, prey_num, atol=0.1).all()
    assert isclose(pred_net, pred_num, atol=0.1).all()
    print('Lotka Volterra test passed.')
Exemplo n.º 23
0
    def get_dn(self, net, *x):
        projection = self._get_projection(*x)
        p_tensor = torch.cat(projection, dim=1)

        if self.f_d is None:
            D = self.bias(net)
        else:
            D = self.f_d(*projection) - net(p_tensor)

        if self.f_n is None:
            N = 0.0
        else:
            N = self.f_n(*projection) - diff(net(p_tensor),
                                             projection[self.idx])

        return D, N
def test_curl(x3):
    nets = [FCNN(3, 1) for _ in range(3)]
    x, y, z = x3
    u, v, w = [net(torch.cat(x3, dim=1)) for net in nets]

    ans = [
        diff(w, y) - diff(v, z),
        diff(u, z) - diff(w, x),
        diff(v, x) - diff(u, y),
    ]
    output = curl(u, v, w, x, y, z)

    for a, o in zip(ans, output):
        assert (a == o).all()
Exemplo n.º 25
0
def test_ode():
    def mse(x, t):
        true_x = torch.sin(t)
        return torch.mean((x - true_x)**2)

    exponential = lambda x, t: diff(x, t) - x
    init_val_ex = IVP(t_0=0.0, x_0=1.0)
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           shuffle=False,
                           max_epochs=2000,
                           return_best=True,
                           metrics={'mse': mse})
    ts = np.linspace(0, 2.0, 100)
    x_net = solution_ex(ts, as_type='np')
    x_ana = np.exp(ts)
    assert isclose(x_net, x_ana, atol=0.1).all()
    print('solve basic test passed.')
Exemplo n.º 26
0
def test_train_generator():
    exponential = lambda x, t: diff(x, t) - x
    init_val_ex = IVP(t_0=0.0, x_0=1.0)

    train_gen = Generator1D(size=32, t_min=0.0, t_max=2.0, method='uniform')
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=0.0,
                            t_max=2.0,
                            method='equally-spaced')
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=0.0,
                            t_max=2.0,
                            method='equally-spaced-noisy')
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=0.0,
                            t_max=2.0,
                            method='equally-spaced-noisy',
                            noise_std=0.01)
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.0,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=np.log10(0.1),
                            t_max=np.log10(2.0),
                            method='log-spaced')
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.1,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=np.log10(0.1),
                            t_max=np.log10(2.0),
                            method='log-spaced-noisy')
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.1,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)
    train_gen = Generator1D(size=32,
                            t_min=np.log10(0.1),
                            t_max=np.log10(2.0),
                            method='log-spaced-noisy',
                            noise_std=0.01)
    solution_ex, _ = solve(ode=exponential,
                           condition=init_val_ex,
                           t_min=0.1,
                           t_max=2.0,
                           train_generator=train_gen,
                           max_epochs=3)

    with raises(ValueError):
        train_gen = Generator1D(size=32, t_min=0.0, t_max=2.0, method='magic')
    print('ExampleGenerator test passed.')
Exemplo n.º 27
0
 def particle_squarewell(y1, y2, t):
     return [(-1 / 2) * diff(y1, t, order=2) - 3 - (y2) * (y1), diff(y2, t)]
Exemplo n.º 28
0
def test_cylindrical_grad(u, x):
    out_rho, out_phi, out_z = cylindrical_grad(u, *x)
    rho, phi, z = x
    assert torch.allclose(out_rho, diff(u, rho))
    assert torch.allclose(out_phi, diff(u, phi) / rho)
    assert torch.allclose(out_z, diff(u, z))
Exemplo n.º 29
0
def test_cylindrical_div(U, x):
    out = cylindrical_div(*U, *x)
    rho, phi, z = x
    urho, uphi, uz = U

    assert torch.allclose(out, diff(rho * urho, rho) / rho + diff(uphi, phi) / rho + diff(uz, z))
Exemplo n.º 30
0
def test_cylindrical_vector_laplacian(U, x):
    out_rho, out_phi, out_z = cylindrical_vector_laplacian(*U, *x)
    rho, phi, z = x
    urho, uphi, uz = U

    def scalar_lap(u):
        return diff(rho * diff(u, rho), rho) / rho + diff(u, phi, order=2) / rho ** 2 + diff(u, z, order=2)

    assert torch.allclose(out_rho, scalar_lap(urho) - urho / rho ** 2 - 2 / rho ** 2 * diff(uphi, phi))
    assert torch.allclose(out_phi, scalar_lap(uphi) - uphi / rho ** 2 + 2 / rho ** 2 * diff(urho, phi))
    assert torch.allclose(out_z, scalar_lap(uz))