예제 #1
0
    def test_set_parameters(self):
        # Define explicit function
        rule = lambda x, a: a * x[:, 0] - x[:, 1]
        parms = [{'a': 1}, {'a': 2}]
        f = Explicit(rule, parameters=parms, dim=2)

        x = (1, 2)
        self.assertTrue(np.allclose(f.eval(x), np.array([-1, 0])))

        # Modify parameter
        f.set_parameters({'a': 2}, pos=0)
        self.assertTrue(np.allclose(f.eval(x), np.array([0, 0])))
예제 #2
0
    def test_constructor(self):
        """
        Test initialization
        """
        f = Explicit(lambda x, a: a * x**2,
                     parameters={'a': 1},
                     dim=1,
                     n_variables=1)
        f.eval(1)
        self.assertAlmostEqual(f.eval(1), 1)

        #
        # Errors
        #
        self.assertRaises(Exception, Explicit)
예제 #3
0
    def test_add_rules(self):
        # Define explicit function
        rule = lambda x, a: a * x**2
        parameters = [{'a': 1}, {'a': 2}]
        f = Explicit(rule, parameters=parameters, dim=1)

        # Raises an error attempt to add multiple functions
        self.assertRaises(Exception, f.add_rule, *(lambda x: x, ),
                          **{'parameters': [{}, {}]})

        # Add a single rule and evaluate at a point
        f.add_rule(lambda x: x)
        x = 2
        vals = [4, 8, 2]

        for i in range(3):

            #(*(x,),**{'a':1}))
            self.assertEqual(f.eval(x)[0, i], vals[i])
예제 #4
0
    def test_subsample_deterministic(self):
        """
        When evaluating a deterministic function while specifying a subsample,
        n_subsample copies of the function output should be returned.        
        """
        #
        # Deterministic functions
        #

        # Functions
        fns = {
            1: {
                1: lambda x: x[:, 0]**2,
                2: lambda x, y: x[:, 0] + y[:, 0]
            },
            2: {
                1: lambda x: x[:, 0]**2 + x[:, 1]**2,
                2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1]
            }
        }

        # Singletons
        x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}}

        xv = {
            1: {
                1: [(2, ), (2, )],
                2: ([(3, ), (3, )], [(4, ), (4, )])
            },
            2: {
                1: [(1, 2), (1, 2)],
                2: ([(1, 2), (1, 2)], [(3, 4), (3, 4)])
            }
        }

        vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}}
        subsample = np.array([2, 3], dtype=np.int)

        for dim in [1, 2]:
            #
            # Iterate over dimension
            #

            # DofHandler
            if dim == 1:
                mesh = Mesh1D(box=[0, 5], resolution=(1, ))
            elif dim == 2:
                mesh = QuadMesh(box=[0, 5, 0, 5])
            element = QuadFE(dim, 'Q2')
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()
            basis = Basis(dofhandler)
            for n_variables in [1, 2]:
                #
                # Iterate over number of variables
                #

                #
                # Explicit
                #
                f = fns[dim][n_variables]

                # Explicit
                fe = Explicit(f, n_variables=n_variables, dim=dim, \
                             subsample=subsample)

                # Nodal
                fn = Nodal(f, n_variables=n_variables, basis=basis, dim=dim, \
                           dofhandler=dofhandler, subsample=subsample)

                # Constant
                fc = Constant(1, n_variables=n_variables, \
                              subsample=subsample)

                # Singleton input
                xn = x[dim][n_variables]

                # Explicit
                self.assertEqual(fe.eval(xn).shape[1], len(subsample))
                self.assertEqual(fe.eval(xn)[0, 0], vals[dim][n_variables])
                self.assertEqual(fe.eval(xn)[0, 1], vals[dim][n_variables])

                # Nodal
                self.assertEqual(fn.eval(xn).shape[1], len(subsample))
                self.assertAlmostEqual(
                    fn.eval(xn)[0, 0], vals[dim][n_variables])
                self.assertAlmostEqual(
                    fn.eval(xn)[0, 1], vals[dim][n_variables])

                # Constant
                self.assertEqual(fc.eval(xn).shape[1], len(subsample))
                self.assertAlmostEqual(fc.eval(xn)[0, 0], 1)
                self.assertAlmostEqual(fc.eval(xn)[0, 1], 1)

                # Vector input
                xn = xv[dim][n_variables]
                n_points = 2

                # Explicit
                self.assertEqual(fe.eval(xn).shape, (2, 2))
                for i in range(fe.n_subsample()):
                    for j in range(n_points):
                        self.assertEqual(
                            fe.eval(xn)[i][j], vals[dim][n_variables])

                # Nodal
                self.assertEqual(fn.eval(xn).shape, (2, 2))
                for i in range(fe.n_subsample()):
                    for j in range(n_points):
                        self.assertAlmostEqual(
                            fn.eval(xn)[i][j], vals[dim][n_variables])

                # Constant
                self.assertEqual(fc.eval(xn).shape, (2, 2))
                for i in range(fe.n_subsample()):
                    for j in range(n_points):
                        self.assertEqual(fc.eval(xn)[i][j], 1)
예제 #5
0
    def test_eval(self):

        #
        # Evaluate single univariate/bivariate functions in 1 or 2 dimensions
        #
        fns = {
            1: {
                1: lambda x: x**2,
                2: lambda x, y: x + y
            },
            2: {
                1: lambda x: x[:, 0]**2 + x[:, 1]**2,
                2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1]
            }
        }

        # Singletons
        x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}}

        vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}}

        for dim in [1, 2]:
            #
            # Iterate over dimension
            #
            for n_variables in [1, 2]:
                #
                # Iterate over number of variables
                #
                fn = fns[dim][n_variables]
                f = Explicit(fn, n_variables=n_variables, dim=dim)

                xn = x[dim][n_variables]
                self.assertEqual(f.eval(xn), vals[dim][n_variables])

        #
        # Evaluate sampled functions
        #
        fns = {
            1: {
                1: lambda x, a: a * x**2,
                2: lambda x, y, a: a * (x + y)
            },
            2: {
                1: lambda x, a: a * (x[:, 0]**2 + x[:, 1]**2),
                2: lambda x, y, a: a * (x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1])
            }
        }

        pars = [{'a': 1}, {'a': 2}]

        #
        # Singletons
        #
        x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}}

        vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}}

        for dim in [1, 2]:
            #
            # Iterate over dimension
            #
            for n_variables in [1, 2]:
                #
                # Iterate over number of variables
                #
                fn = fns[dim][n_variables]
                f = Explicit(fn,
                             parameters=pars,
                             n_variables=n_variables,
                             dim=dim)

                xn = x[dim][n_variables]
                self.assertEqual(f.eval(xn)[0][0], vals[dim][n_variables])
                self.assertEqual(f.eval(xn)[0][1], 2 * vals[dim][n_variables])

        #
        # 2 points
        #
        n_points = 2
        x = {
            1: {
                1: [(2, ), (2, )],
                2: ([(3, ), (3, )], [(4, ), (4, )])
            },
            2: {
                1: [(1, 2), (1, 2)],
                2: ([(1, 2), (1, 2)], [(3, 4), (3, 4)])
            }
        }
        for dim in [1, 2]:
            #
            # Iterate over dimension
            #
            for n_variables in [1, 2]:
                #
                # Iterate over number of variables
                #
                fn = fns[dim][n_variables]
                f = Explicit(fn,
                             parameters=pars,
                             n_variables=n_variables,
                             dim=dim)

                xn = x[dim][n_variables]
                self.assertEqual(f.eval(xn).shape[0], n_points)
                self.assertEqual(f.eval(xn).shape[1], f.n_samples())

                for i in range(f.n_samples()):
                    for j in range(2):
                        val = pars[i]['a'] * vals[dim][n_variables]
                        self.assertEqual(f.eval(xn)[j, i], val)
예제 #6
0
    def test_constructor(self):
        # =====================================================================
        # Test 1D 
        # ===================================================================== 
        
        #
        # Kernel consists of a single explicit Function: 
        # 
        f1 = lambda x: x+2
        f = Explicit(f1, dim=1)
        k = Kernel(f)
        x = np.linspace(0,1,100)
        n_points = len(x)
        
        # Check that it evaluates correctly.
        self.assertTrue(np.allclose(f1(x), k.eval(x).ravel()))
        
        # Check shape of kernel
        self.assertEqual(k.eval(x).shape, (n_points,1))
        
        #
        # Kernel consists of a combination of two explicit functions
        # 
        f1 = Explicit(lambda x: x+2, dim=1)
        f2 = Explicit(lambda x: x**2 + 1, dim=1)
        F = lambda f1, f2: f1**2 + f2
        f_t = lambda x: (x+2)**2 + x**2 + 1
        k = Kernel([f1,f2], F=F)
        
        # Check evaluation
        self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel()))
        
        # Check shape 
        self.assertEqual(k.eval(x).shape, (n_points,1))
        

        #
        # Same thing as above, but with nodal functions
        # 
        mesh = Mesh1D(resolution=(1,))
        Q1 = QuadFE(1,'Q1')
        Q2 = QuadFE(1,'Q2')
        
        dQ1 = DofHandler(mesh,Q1)
        dQ2 = DofHandler(mesh,Q2)
        
        # Distribute dofs
        [dQ.distribute_dofs() for dQ in [dQ1,dQ2]]
        
        # Basis functions
        phi1 = Basis(dQ1,'u')
        phi2 = Basis(dQ2,'u')
        
        f1 = Nodal(lambda x: x+2, basis=phi1)
        f2 = Nodal(lambda x: x**2 + 1, basis=phi2)
        k = Kernel([f1,f2], F=F)
        
        # Check evaluation
        self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel()))
        
        #
        # Replace f2 above with its derivative
        # 
        k = Kernel([f1,f2], derivatives=['f', 'fx'], F=F)
        f_t = lambda x: (x+2)**2 + 2*x
                
        # Check derivative evaluation F = F(f1, df2_dx)
        self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel()))
        
        
        # 
        # Sampling 
        #
        one = Constant(1)
        f1 = Explicit(lambda x: x**2 + 1, dim=1)
        
        # Sampled function
        a = np.linspace(0,1,11)
        n_samples = len(a)
        
        # Define Dofhandler
        dh = DofHandler(mesh, Q2)
        dh.distribute_dofs()
        dh.set_dof_vertices()
        xv = dh.get_dof_vertices()
        n_dofs = dh.n_dofs()
        
        phi = Basis(dh, 'u')
        
        # Evaluate parameterized function at mesh dof vertices
        f2_m  = np.empty((n_dofs, n_samples))
        for i in range(n_samples):
            f2_m[:,i] = xv.ravel() + a[i]*xv.ravel()**2
        f2 = Nodal(data=f2_m, basis=phi)
        
        # Define kernel
        F = lambda f1, f2, one: f1 + f2 + one
        k = Kernel([f1,f2,one], F=F)
        
        # Evaluate on a fine mesh
        x = np.linspace(0,1,100)
        n_points = len(x)
        self.assertEqual(k.eval(x).shape, (n_points, n_samples))    
        for i in range(n_samples):
            # Check evaluation            
            self.assertTrue(np.allclose(k.eval(x)[:,i], f1.eval(x)[:,i] + x + a[i]*x**2+ 1))
            
        
        #
        # Sample multiple constant functions
        # 
        f1 = Constant(data=a)
        f2 = Explicit(lambda x: 1 + x**2, dim=1)
        f3 = Nodal(data=f2_m[:,-1], basis=phi)
        
        F = lambda f1, f2, f3: f1 + f2 + f3
        k = Kernel([f1,f2,f3], F=F)
        
        x = np.linspace(0,1,100)
        for i in range(n_samples):
            self.assertTrue(np.allclose(k.eval(x)[:,i], \
                                        a[i] + f2.eval(x)[:,i] + f3.eval(x)[:,i]))
        
        #
        # Submeshes
        # 
        mesh = Mesh1D(resolution=(1,))
        mesh_labels = Tree(regular=False)
        
        mesh = Mesh1D(resolution=(1,))
        Q1 = QuadFE(1,'Q1')
        Q2 = QuadFE(1,'Q2')
        
        dQ1 = DofHandler(mesh,Q1)
        dQ2 = DofHandler(mesh,Q2)
        
        # Distribute dofs
        [dQ.distribute_dofs() for dQ in [dQ1,dQ2]]
        
        # Basis
        p1 = Basis(dQ1)
        p2 = Basis(dQ2) 
        
        
        f1 = Nodal(lambda x: x, basis=p1)
        f2 = Nodal(lambda x: -2+2*x**2, basis=p2)
        one = Constant(np.array([1,2]))
    
        F = lambda f1, f2, one: 2*f1**2 + f2 + one
        
        I = mesh.cells.get_child(0)
        
        kernel = Kernel([f1,f2, one], F=F)
        
        rule1D = GaussRule(5,shape='interval')
        x = I.reference_map(rule1D.nodes())
예제 #7
0
def reference_solution():
    """
    Use sparse grid method to compute a benchmark solution
    """
    
    mesh = QuadMesh(resolution=(10,10))
    mesh.mark_region('boundary', lambda x,y:True, 
                     entity_type='half_edge', on_boundary=True)
    element = QuadFE(mesh.dim(), 'Q1')
    dofhandler = DofHandler(mesh, element)
    dofhandler.distribute_dofs()
    n = dofhandler.n_dofs()
    phi = Basis(dofhandler, 'u')
    phi_x = Basis(dofhandler, 'ux')
    phi_y = Basis(dofhandler, 'uy')
    yd_fn = Explicit(lambda x: np.sin(2*np.pi*x[:,0])*np.sin(2*np.pi*x[:,1]),dim=2)
    g = np.ones((n,1))
    
    #
    # Random diffusion coefficient
    # 
    
    # Sparse grid
    tasmanian_library="/home/hans-werner/bin/TASMANIAN-6.0/libtasmaniansparsegrid.so"
    grid = TasmanianSG.TasmanianSparseGrid(tasmanian_library=tasmanian_library)
    dimensions = 4
    outputs = 1
    depth = 4
    type = 'tensor'
    rule = 'gauss-legendre'
    grid.makeGlobalGrid(dimensions, outputs, depth, type, rule)
    Y = grid.getPoints()
    w = grid.getQuadratureWeights()
    n_samples = grid.getNumPoints()
    
    
    x = dofhandler.get_dof_vertices()
    a_nodal = 1 + 0.1*(np.outer(np.cos(np.pi*x[:,1]),Y[:,0])+\
                       np.outer(np.cos(np.pi*x[:,0]),Y[:,1])+\
                       np.outer(np.sin(2*np.pi*x[:,1]),Y[:,2])+\
                       np.outer(np.sin(2*np.pi*x[:,0]),Y[:,3]))
    a = Nodal(data=a_nodal, dofhandler=dofhandler)
    yd_vec = yd_fn.eval(x)
    
    problems = [[Form(a, test=phi_x, trial=phi_x), 
                Form(a, test=phi_y, trial=phi_y)],
                [Form(1, test=phi, trial=phi)]]
    
    assembler = Assembler(problems, mesh)
    assembler.assemble()
    
    A = assembler.af[0]['bilinear'].get_matrix()
    M = assembler.af[1]['bilinear'].get_matrix()
    
    state = LS(phi)
    state.add_dirichlet_constraint('boundary')
    
    adjoint = LS(phi)
    adjoint.add_dirichlet_constraint('boundary')
    
    tau = 10
    k_max = 20
    alpha = 0.1
    u = np.zeros((n,1))
    norm_dJ_iter = []
    J_iter = []
    u_iter = []
    for k in range(k_max):
        print('iteration', k)
        # 
        # Compute average cost and gradient
        # 
        dJ = np.zeros((n,1))
        J = 0
        print('sampling')
        for n in range(n_samples):
            print(n)
            yn, pn, Jn, dJn = cost_gradient(state,adjoint,A[n],M,
                                            g,u,yd_vec,alpha)
            
            J += w[n]*Jn
            dJ += w[n]*dJn
        print('')
        norm_dJ = np.sqrt(dJ.T.dot(M.dot(dJ)))
        
        #
        # Store current iterates
        # 
        norm_dJ_iter.append(norm_dJ)
        J_iter.append(J)
        u_iter.append(u)
        
        #
        # Check for convergence
        # 
        if norm_dJ<1e-8:
            break
        #
        # Update iterate
        # 
        u -= tau*dJ
예제 #8
0
# -----------------------------------------------------------------------------
# Observations
# ----------------------------------------------------------------------------- 
# Determine vertices corresponding to production wells
n_prod = 4
h = (x_max-x_min)/(n_prod+2)
x_prod = np.array([(i+1)*h for i in range(n_prod)])
v = dh_y.get_dof_vertices()
dofs_prod = []
for x in x_prod:
    dofs_prod.append(np.argmin(abs(v-x)))
#   
# Target pressure at production wells
#
z_fn = Explicit(f=lambda x: 3-4*(x[:,0]-1)**2, dim=1, mesh=mesh)
z_data = z_fn.eval(v[dofs_prod])

# -----------------------------------------------------------------------------
# Control
# -----------------------------------------------------------------------------
# Determine the vertices corresponding to the injection wells
n_inj = 6
h = (x_max-x_min)/(n_inj+2)
x_inj = np.array([(i+1)*h for i in range(n_inj)])
dofs_inj = []
for x in x_inj:
    dofs_inj.append(np.argmin(abs(v-x)))
 
u_data = np.zeros((ny,1))
u_data[dofs_inj] = 1
u = Nodal(dofhandler=dh_y, data=u_data, dim=1)
예제 #9
0
# Mark vertices
for cell, dummy in cells_production:
    cell.get_vertex(2).mark('production')

# Extract degrees of freedom
production_dofs = dh_Q1.get_region_dofs(entity_type='vertex',
                                        entity_flag='production')

v_production = dh_Q1.get_dof_vertices(dofs=production_dofs)

# Target pressure at production wells
z_fn = Explicit(f=lambda x: 3 - 4 * (x[:, 0] - 1)**2 - 8 * (x[:, 1] - 0.5)**2,
                dim=2,
                mesh=mesh)
y_target = z_fn.eval(v_production)

#
# Locations of injection wells
#
n_injection = (5, 4)  # resolution
x_injection = np.linspace(0.5, 1.5, n_injection[0])
y_injection = np.linspace(0.25, 0.75, n_injection[1])
X, Y = np.meshgrid(x_injection, y_injection)
xy = np.array([X.ravel(), Y.ravel()]).T
cells_injection = mesh.bin_points(xy)

# Mark vertices
for cell, dummy in cells_injection:
    cell.get_vertex(0).mark('injection')