def __init__(self, mesh, permittivity_dict, k0L, **kvargs):
        super().__init__(mesh, k0L, **kvargs)
        self.II = fd.as_matrix(((1, 0), (0, 1)))
        self.permittivity = fd.Function(
            fd.TensorFunctionSpace(self.mesh, "DG", 0))

        for (subd_id, epsilon_tensor) in permittivity_dict.items():
            epsilon = fd.as_matrix(epsilon_tensor)
            self.permittivity.interpolate(
                epsilon, self.mesh.measure_set("cell", subd_id))
Example #2
0
def test_n_min_pre_ufl():
    """Tests that the sharp cutoff function does what it should when n_pre is given by a UFL expression."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)
    
    n_pre = 1.0 + fd.sin(30*x[0])
    
    prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    n_min_val = 2.0
    
    prob.n_min(n_min_val,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)
    
    assert (n_fn.dat.data_ro >= n_min_val).all()
def test_coeff_definition_error():
    """Test that a coeff with too many pieces is caught."""
    k = 20.0
    mesh = fd.UnitSquareMesh(100, 100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 13
    noise_level = 0.1
    num_repeats = 10

    A_pre = fd.as_matrix(np.array([[1.0, 0.0], [0.0, 1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              A_pre, [2, 2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              n_pre, [1])

    f = 1.0
    g = 1.0

    GMRES_its = nbex.nearby_preconditioning_experiment(V, k, A_pre, A_stoch,
                                                       n_pre, n_stoch, f, g,
                                                       num_repeats)

    # The code should catch the error and print a warning message, and
    # exit, not recording any GMRES iterations.

    assert GMRES_its.shape == (0, )
def test_coeff_definition_no_error():
    """Test that a coeff with just too few many pieces is not caught."""
    k = 20.0
    mesh = fd.UnitSquareMesh(100, 100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 12
    noise_level = 0.1
    num_repeats = 10

    A_pre = fd.as_matrix(np.array([[1.0, 0.0], [0.0, 1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              A_pre, [2, 2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh, num_pieces, noise_level,
                                              n_pre, [1])

    f = 1.0
    g = 1.0

    GMRES_its = nbex.nearby_preconditioning_experiment(V, k, A_pre, A_stoch,
                                                       n_pre, n_stoch, f, g,
                                                       num_repeats)

    # The code should not error.

    assert GMRES_its.shape != (0, )
def test_coeff_size():
    """Tests that the p/w/ const coeffs are the correct size."""

    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 1
    noise_level = 0.1
    num_repeats = 100
    
    A_pre = fd.as_matrix(np.array([[1.0,0.0],[0.0,1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,A_pre,[2,2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,n_pre,[1])
    for ii in range(num_repeats):
        A_stoch.sample()
        n_stoch.sample()
        fl = A_stoch._constant_array.flat
        for jj in fl:
            coords = hh_utils.flatiter_hack(A_stoch._constant_array,fl.coords)
            assert A_stoch._constant_array[coords].evaluate(None,None,(),None).shape\
                == (2,2)
            assert n_stoch._constant_array[coords].evaluate(None,None,(),None).shape\
                == ()
Example #6
0
def test_sharp_cutoff_pre_ufl():
    """Tests that the sharp cutoff function does what it should when the
    preconditioning coefficient is given by ufl."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)

    x = fd.SpatialCoordinate(mesh)

    n_pre = 1.0 + fd.sin(30*x[0])

    prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    prob.sharp_cutoff(np.array([0.5,0.5]),0.5,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)

    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)

    # As above
    assert n_fn.dat.data_ro[97] == 1.0
def test_coeff_being_updated():
    """Test that the p/w/ const random coefficients are updated."""

    k = 20.0
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 12
    noise_level = 0.1
    num_repeats = 10
    
    A_pre = fd.as_matrix(np.array([[1.0,0.0],[0.0,1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,A_pre,[2,2])

    n_pre = 1.0
    n_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,n_pre,[1])

    A_copy = copy.deepcopy(A_stoch._constant_array[0,0].values())

    n_copy = copy.deepcopy(n_stoch._constant_array[0,0].values())

    A_stoch.sample()

    n_stoch.sample()

    A_diff = A_copy - A_stoch._constant_array[0,0].values()

    assert all(A_copy != 0.0)

    assert n_copy != n_stoch._constant_array[0,0].values()    
    def _coeff_initialise(self,mesh,coeff_pre):
        """Initialises self.coeff equal to coeff_pre, but sets up
        Firedrake Constant structure to allow for sampling.

        Parameters:

        mesh - a Firedrake mesh.

        coeff_pre - see init.
        """

        if self._coeff_dims == [2,2]\
                and coeff_pre != fd.as_matrix([[1.0,0.0],[0.0,1.0]]):

            warnings.warn("coeff_pre is not the identity. There is no\
            guarantee that the randomly-generated matrices are\
            positive-definite, or have the correct amount of noise.")

        d = mesh.geometric_dimension()
            
        # Bit of a hack, set up num_pieces
        num_pieces_list = []
        [num_pieces_list.append(self._num_pieces) for ii in range(d)]
            
        # Set up all the Firedrake Constants:
        self._constant_array = np.empty(num_pieces_list,dtype=object)

        with np.nditer(self._constant_array,flags=['refs_ok'],op_flags=['writeonly']) as array_it:
            
            for const in array_it:

                if self._coeff_dims == [2,2]:
                    const[...] = fd.Constant(np.array([[0.0,0.0],[0.0,0.0]]),domain=mesh)
                elif self._coeff_dims == [1]:
                    const[...] = fd.Constant(0.0,domain=mesh)
                
        # Form coeff by looping over all the subdomains
        x = fd.SpatialCoordinate(mesh)

        self.coeff = coeff_pre

        array_it = np.nditer(self._constant_array,flags=['refs_ok','multi_index'])

        while not array_it.finished:
        
            const =  array_it[0]
            
            loc_array = np.array((array_it.multi_index,1+np.array(array_it.multi_index))
                                 ,dtype='float').T/float(self._num_pieces)
            
            self.coeff += utils.nd_indicator(x,const,loc_array)

            array_it.iternext()
Example #9
0
        def sigma_next(timestep, zeta, ep_dot, sigma, P):
            A = 1 + 0.25 * (timestep * params.e ** 2) / params.T
            B = timestep * 0.125 * (1 - params.e ** 2) / params.T
            rhs = (1 - (timestep * params.e ** 2) / (4 * params.T)) * sigma - timestep / params.T * (
                    0.125 * (1 - params.e ** 2) * tr(sigma) * Identity(2) - 0.25 * P * Identity(2) + zeta * ep_dot)
            C = (rhs[0, 0] - rhs[1, 1]) / A
            D = (rhs[0, 0] + rhs[1, 1]) / (A + 2 * B)
            sigma00 = 0.5 * (C + D)
            sigma11 = 0.5 * (D - C)
            sigma01 = rhs[0, 1]
            sigma = as_matrix([[sigma00, sigma01], [sigma01, sigma11]])

            return sigma
Example #10
0
        def __init__(self,type):
            """Initialises testing class."""
            self._counter = 1

            self._changes = fd.Constant(1.0)

            self._type = type

            if type == "matrix":
                self.coeff = fd.as_matrix([[1.0,0.0],[0.0,1.0/self._changes]])

            if type == "scalar":
                self.coeff = 1 + 1.0/self._changes
Example #11
0
def test_HelmholtzProblem_set_A():
    """Test that set_A assigns and re-initialises."""
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)
    k = 20.0
    
    prob = hh.HelmholtzProblem(k,V)

    A = fd.as_matrix([[0.9,0.2],[0.2,0.8]])
    
    prob.set_A(A)

    assert prob._A == A
Example #12
0
def test_n_stoch_none():
    """Test that not setting n_stoch doesn't misbehave."""

    k = 10.0

    mesh = fd.UnitSquareMesh(100,100)

    V = fd.FunctionSpace(mesh, "CG", 1)

    A_stoch = PiecewiseConstantCoeffGenerator(
        mesh,2,0.1,fd.as_matrix([[1.0,0.0],[0.0,1.0]]),[2,2])

    prob = hh.StochasticHelmholtzProblem(k,V,A_stoch=A_stoch)
Example #13
0
def nearby_preconditioning_experiment_exponential(k_range,scale,num_repeats):
    """Tests the effectiveness of nearby preconditioning for a
    homogeneous but exponential-like  random refractive index.

    The preconditioner is given by n=1.

    The preconditioned problem is given by 1 + exp(scale)
    """

    GMRES_all = []
    
    for k in k_range:

        num_points = hh_utils.h_to_num_cells(k**(-1.5),2)
        
        mesh = fd.UnitSquareMesh(num_points,num_points)

        V = fd.FunctionSpace(mesh, "CG", 1)

        n_stoch = coeff.ExponentialConstantCoeffGenerator(scale)

        n_pre = 1.0
        f = 1.0
        g = 0.0

        GMRES_its = nearby_preconditioning_experiment(
            V,k,A_pre=fd.as_matrix([[1.0,0.0],[0.0,1.0]]),
            A_stoch=None,n_pre=n_pre,n_stoch=n_stoch,
            f=f,g=g,num_repeats=num_repeats)

        save_location = './'

        info = {"function" : "nearby_preconditioning_experiment_exponential",
                "k" : k,
                "h" : "k**(-1.5)",
                "scale" : scale,
                "f" : f,
                "g" : g,
                "n_pre" : n_pre,
                "num_repeats" : num_repeats
                }

        if fd.COMM_WORLD.rank == 0:
            hh_utils.write_GMRES_its(GMRES_its,save_location,info)

        GMRES_all.append(GMRES_its)

    # Mainly for easy testing
    return GMRES_all
Example #14
0
def test_HelmholtzProblem_set_pre():
    """Test that set_A_pre and set_n_pre assign and re-initialise."""
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)
    k = 20.0
    
    prob = hh.HelmholtzProblem(k,V)

    A_pre = fd.as_matrix([[0.9,0.2],[0.2,0.8]])

    n_pre = 1.1
    
    prob.set_A_pre(A_pre)

    prob.set_n_pre(n_pre)

    assert prob._A_pre == A_pre
Example #15
0
    def sharp_cutoff(self, centre, width, apply_to_preconditioner=False):
        """Applies a sharp cutoff function to A&n.

        Applying this function means A=I and n=1 on the boundary

        The cutoff function is 1 on a square/cube, and zero outside
        the square/cube.

        Inputs:

        centre - numpy array containing the coordinates of the centre
        of the cutoff zone.

        width - the width of the zone on which the original values of
        A & n hold.

        apply_to_preconditioner - boolean - if true, does this only to
        the preconditioner, rather than the problem itself. Used mainly
        when setting an already-existing problem as the preconditioner.
        """
        x = fd.SpatialCoordinate(self.V.mesh())

        dim = self.V.mesh().geometric_dimension()

        indicator_region = np.array(centre)\
                           + np.repeat(0.5*np.array([-width,width],ndmin=2),
                                       dim,axis=0)

        ind = nd_indicator(x, 1.0, indicator_region)

        identity = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]])

        if apply_to_preconditioner:

            self.set_n_pre(1.0 + ind * (self._n_pre - 1.0))

            self.set_A_pre(identity + ind * (self._A_pre - identity))

        else:

            self.set_n(1.0 + ind * (self._n - 1.0))

            self.set_A(identity + ind * (self._A - identity))
def test_matrices_noise_level():
    """Tests p/w const coeff matrices have correct noise_level.

    Only works for the case coeff_pre = I."""

    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 12
    noise_level = 0.1
    num_repeats = 100
    
    A_pre = fd.as_matrix(np.array([[1.0,0.0],[0.0,1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,A_pre,[2,2])

    A_func = fd.Function(V)
    
    for ii in range(num_repeats):
        A_stoch.sample()

    for ii_x in range(2):
        for ii_y in range(2):
            A_func.interpolate(A_stoch.coeff[ii_x,ii_y]-float(A_pre[ii_x,ii_y]))

            assert (np.abs(A_func.dat.data_ro) <= noise_level).all()

        fl = A_stoch._constant_array.flat
        for jj in fl:
            coords = hh_utils.flatiter_hack(A_stoch._constant_array,fl.coords)

            assert abs(A_stoch._constant_array[coords]\
                       .evaluate(None,None,(),None)[0,0]) <= noise_level

            assert abs(A_stoch._constant_array[coords]\
                       .evaluate(None,None,(),None)[1,1]) <= noise_level

            assert abs(A_stoch._constant_array[coords]\
                       .evaluate(None,None,(),None)[0,1]) <= noise_level

            assert abs(A_stoch._constant_array[coords]\
                       .evaluate(None,None,(),None)[1,0]) <= noise_level
Example #17
0
def test_n_min_pre():
    """Tests that the sharp cutoff function does what it should."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)
    
    prob = hh.HelmholtzProblem(k,V,n_pre=2.0,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    n_min_val = 2.0
    
    prob.n_min(n_min_val,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)
    
    assert np.isclose(n_min_val,n_fn.dat.data_ro).all()
def test_matrices_spd():
    """Tests that p/w const coeffmatrices are spd.

    Uses Sylvester's criterion.

    Only works for the case coeff_pre = I."""

    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    num_pieces = 12
    noise_level = 0.1
    num_repeats = 100
    
    A_pre = fd.as_matrix(np.array([[1.0,0.0],[0.0,1.0]]))
    A_stoch = PiecewiseConstantCoeffGenerator(mesh,num_pieces,
                                                   noise_level,A_pre,[2,2])

    for ii in range(num_repeats):
        A_stoch.sample()

        fl = A_stoch._constant_array.flat
        for jj in fl:
            coords = hh_utils.flatiter_hack(A_stoch._constant_array,fl.coords)

            assert A_stoch._constant_array[coords].evaluate(
                None,None,(),None)[1,0]\
                == A_stoch._constant_array[coords].evaluate(
                    None,None,(),None)[0,1]
            
            assert 1.0 +\
                A_stoch._constant_array[coords].evaluate(
                    None,None,(),None)[0,0] > 0.0
            
            assert np.linalg.det(np.array([[1.0,0.0],[0.0,1.0]])\
                                 + A_stoch._constant_array[coords].\
                                 evaluate(None,None,(),None))\
                                 > 0.0
Example #19
0
    def f_g_scattered_plane_wave(self, d):
        """Sets f and g to correspond to the scattering of a plane wave
        by a compactly-supported heterogeneous region.

        Parameters - d - list of the length of the spatial dimension;
        the direction in which the plane wave propagates.
        """

        d = fd.as_vector(d)

        x = fd.SpatialCoordinate(self.V.mesh())

        # Incident wave
        u_I = fd.exp(1j * self._k * fd.dot(x, d))

        identity = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]])

        f = fd.div(fd.dot((identity-self._A),fd.grad(u_I)))\
            + self._k**2.0 * fd.inner((1.0-self._n), u_I)

        self.set_f(f)

        self.set_g(0.0)
Example #20
0
def test_sharp_cutoff_pre():
    """Tests that the sharp cutoff function does what it should."""

    k = 10.0

    mesh = fd.UnitSquareMesh(10,10)

    V = fd.FunctionSpace(mesh,"CG",1)
    
    prob = hh.HelmholtzProblem(k,V,n_pre=2.0,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]]))

    prob.sharp_cutoff(np.array([0.5,0.5]),0.5,True)

    V_DG = fd.FunctionSpace(mesh,"DG",0)
    
    n_fn = fd.Function(V_DG)

    n_fn.interpolate(prob._n_pre)

    # As above
    assert n_fn.dat.data_ro[97] == 1.0

    assert n_fn.dat.data_ro[95] == 2.0
Example #21
0
def test_HelmholtzProblem_init_f_g_zero():
    """Test a simple setup with f = g = 0."""
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)
    k = 20.0
    A = fd.as_matrix([[0.9,0.2],[0.2,0.8]])
    n = 1.1
    A_pre = A
    n_pre = n
    f = 0.0
    g = 0.0
    prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g)

    assert prob._k == k
    assert prob.V == V
    assert prob._A == A
    assert prob._n == n
    assert prob._A_pre == A_pre
    assert prob._n_pre == n_pre
    # Currently not testing f and g, as the code sets f = g = x[0]-x[0],
    # as that doesn't crash Firedrake
    assert prob.GMRES_its == -1
    assert prob.u_h.vector().sum() == 0.0
Example #22
0
def test_HelmholtzProblem_init_simple():
    """Test a simple setup."""
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)
    k = 20.0
    A = fd.as_matrix([[0.9,0.2],[0.2,0.8]])
    n = 1.1
    A_pre = A
    n_pre = n
    f = 2.0
    g = 1.1
    prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g)

    assert prob._k == k
    assert prob.V == V
    assert prob._A == A
    assert prob._n == n
    assert prob._A_pre == A_pre
    assert prob._n_pre == n_pre
    assert prob._f == f
    assert prob._g == g
    assert prob.GMRES_its == -1
    assert prob.u_h.vector().sum() == 0.0
Example #23
0
def test_HelmholtzProblem_init_one_pc_none():
    """Test a simple setup with one preconditioning coeff as None."""
    mesh = fd.UnitSquareMesh(100,100)
    V = fd.FunctionSpace(mesh, "CG", 1)
    k = 20.0
    A = fd.as_matrix([[0.9,0.2],[0.2,0.8]])
    n = 1.1
    A_pre = None
    n_pre = 1.0
    f = 1.0
    g = 1.0
    prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g)

    prob._initialise_problem()

    assert prob._k == k
    assert prob.V == V
    assert prob._A == A
    assert prob._n == n
    assert prob._a_pre == None
    assert prob._f == f
    assert prob._g == g
    assert prob.GMRES_its == -1
    assert prob.u_h.vector().sum() == 0.0
Example #24
0
def qmc_nbpc_experiment(h_spec,dim,J,M,k,delta,lambda_mult,j_scaling,mean_type,
                        use_nbpc,points_generation_method,seed,GMRES_threshold):
    """Performs QMC for the Helmholtz Eqn with nearby preconditioning.

    Mention: expansion, n only, unit square, the idea of the algorithm.

    Parameters:

    h_spec - like one entry of h_list in piecewise_experiment_set.

    dim - 2 or 3 - the spatial dimension.

    J - positive int - the length of the KL-like expansion in the
    definition of n.

    M - positive int - 2**M is the number of QMC points to use.

    k - positive float - the wavenumber.

    delta - see the definition of delta in
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff.__init__.

    lambda_mult - see the definition of lambda_mult in
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff.__init__.

    j_scaling - see the definition of j_scaling in
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff.__init__.

    mean_type - one of 'constant', INSERT MORE IN HERE - n_0 in the
    expansion for n.

    use_nbpc - Boolean - whether to use nearby preconditioning to speed
    up the qmc method, or to perform an LU decomposition for each QMC
    point, and use this to precondition GMRES (which will converge in
    one step).

    point_generation_method - either 'qmc' or 'mc'. 'qmc' means a QMC
    lattice rule is used to generate the points, whereas 'mc' means the
    points are randomly generated according to a uniform distribution on
    the cube.

    seed - seed with which to start the randomness.

    GMRES_threshold - positive int - the number of GMRES iteration we
    will tolerate before we 'redo' the preconditioning.

    Outputs:

    time - a 2-tuple of non-negative floats. time[0] is the amount of
    time taken to calculate the LU decompositions, and time[1] is the
    amount of time taken performing GMRES solves. NOT YET IMPLEMTENTED.

    points_info - a pandas DataFrame of length M, where each row
    corresponds to a QMC point. The columns of this dataframe are 'sto_loc'
    - a numpy array giving the location of the point in stochastic
    space; 'LU' - a boolean stating whether the system matric
    corresponding to that point was factorised into its LU
    factorisation; and 'GMRES' - a non-negative int giving the number of
    GMRES iterations it took to achieve convergence at this QMC
    point. The points are ordered (from top to bottom) in the order they
    were tackled by the algorithm.

    """
    scaling = lambda_mult * np.array(list(range(1,J+1)),
                                     dtype=float)**(-1.0-delta)

    if points_generation_method is 'qmc':
        # Generate QMC points on [-1/2,1/2]^J using Dirk Nuyens' code
        qmc_generator = latticeseq_b2.latticeseq_b2(s=J)

        points = []

        # The following range will have M as its last term
        for m in range((M+1)):
            points.append(qmc_generator.calc_block(m))

        qmc_points = points[0]

        for ii in range(1,len(points)):
            qmc_points = np.vstack((qmc_points,points[ii]))
        

    elif points_generation_method is 'mc':
        qmc_points = np.random.rand(2**M,J)

    qmc_points -= 0.5
        
    # Create the coefficient
    if mean_type is 'constant':
        n_0 = 1.0

    mesh_points = hh_utils.h_to_num_cells(h_spec[0]*k**h_spec[1],dim)
    mesh = fd.UnitSquareMesh(mesh_points,mesh_points)
    
    kl_like = coeff.UniformKLLikeCoeff(mesh,J,delta,lambda_mult,j_scaling,n_0,qmc_points)
    
    # Create the problem
    V = fd.FunctionSpace(mesh,"CG",1)
    # The Following lines are a hack because deepcopy isn't implemented
    # for ufl expressions (in general at least), and creating an
    # instance of the coefficient with particular 'stochastic
    # coordinates' is the easiest way to get the preconditioning
    # coefficient.

    prob = hh.StochasticHelmholtzProblem(k,V,None,kl_like,
                                         **{'A_pre' :
                                            fd.as_matrix([[1.0,0.0],[0.0,1.0]])
                                         })
    
    points_info_columns = ['sto_loc','LU','GMRES']
    points_info = pd.DataFrame(None,columns=points_info_columns)
    
    centre = np.zeros((1,J))

    # Order points relative to the origin
    order_points(prob.n_stoch,centre,scaling)

    update_pc(prob,mesh,J,delta,lambda_mult,j_scaling,n_0)
    LU = True
    num_solves = 0
    
    continue_in_loop = True
    while continue_in_loop:
        if fd.COMM_WORLD.rank == 0:
            print('Going round loop',flush=True)
        prob.solve()
        num_solves += 1
        
        if use_nbpc is True:
            # If GMRES iterations were too big, or we're not using nbpc,
            # recalculate preconditioner.
            if (prob.GMRES_its > GMRES_threshold):
                new_centre(prob,mesh,J,delta,lambda_mult,j_scaling,n_0,scaling)
                LU = True

            else:
                # Copy details of last solve into output dataframe
                temp_df = pd.DataFrame(
                    [[prob.n_stoch.current_point(),LU,prob.GMRES_its]],columns=points_info_columns)
                points_info = points_info.append(temp_df,ignore_index=True)
                LU = False
                try:
                    prob.sample()
                except coeff.SamplingError:
                    continue_in_loop = False

        else: # Not using NBPC
            temp_df = pd.DataFrame(
                [[prob.n_stoch.current_point(),LU,prob.GMRES_its]],columns=points_info_columns)
            points_info = points_info.append(temp_df,ignore_index=True)

            try:
                prob.sample()
                new_centre(prob,mesh,J,delta,lambda_mult,j_scaling,n_0,scaling)
            except coeff.SamplingError:
                continue_in_loop = False

        
    # Now trying to see if I can do stuff with timings
    # Try uing the re regular expression package
    
    
    try:
        open('tmp.txt','r')
        print('SUCCESS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
        print(num_solves)
    except:
        pass
    
    return points_info
Example #25
0
        shift = np.array([[eps, 0.0], [0.0, 0.0]])

        num_cells = h_to_num_cells(k**(-1.5), 2)

        mesh = fd.UnitSquareMesh(num_cells, num_cells)

        V = fd.FunctionSpace(mesh, "CG", 1)

        x = fd.SpatialCoordinate(mesh)

        n = 0.5 + nd_indicator(x, 1.0, discon + eps)

        n_pre = 0.5 + nd_indicator(x, 1.0, discon)

        A = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]])

        prob = HelmholtzProblem(k, V, A=A, n=n, A_pre=A, n_pre=n_pre)

        prob.f_g_plane_wave([np.cos(angle), np.sin(angle)])

        prob.solve()

        storage = np.append(storage,
                            np.array((k, prob.GMRES_its), ndmin=2),
                            axis=0)

    storage = storage[1:, :]

    if fd.COMM_WORLD.rank == 0:
Example #26
0
def nearby_preconditioning_piecewise_experiment_set(
        A_pre_type,n_pre_type,dim,num_pieces,seed,num_repeats,
        k_list,h_list,p_list,noise_master_level_list,noise_modifier_list,
        save_location):
    """Test nearby preconditioning for a range of parameter values.

    Performs nearby preconditioning tests for a range of values of k,
    the mesh size h, and the size of the random noise (which can be
    specified in terms of k and h). The random noise is piecewise
    constant on a grid unrelated to the finite-element mesh.

    Parameters:

    A_pre_type - string - options are 'constant', giving A_pre =
    [[1.0,0.0],[0.0,1.0]].

    n_pre_type - string - options are 'constant', giving n_pre = 1.0;
    'jump_down' giving n_pre = 2/3 on a central square of side length
    1/3, and 1 otherwise; and 'jump_up' giving n_pre = 1.5 on a central
    square of side length 1/3, and 1 otherwise.

    dim - 2 or 3, the dimension of the problem.

    num_pieces - see
        helmholtz.coefficients.PieceWiseConstantCoeffGenerator.

    seed - see StochasticHelmholtzProblem.

    num_repeats - see nearby_preconditioning_test.

    k_list - list of positive floats - the values of k for which we will
    run experiments.

    h_list - list of 2-tuples; in each tuple (call it t) t[0] should be
    a positive float and t[1] should be a float. These specify the
    values of the mesh size h for which we will run experiments. h =
    t[0] * k**t[1].

    p_list - list of positive ints, the polynomial degrees to run
    experiments for. Degree >= 5 will be very slow because of the
    implementation in Firedrake.

    noise_master_level_list - list of 2-tuples, where each entry of the
    tuple is a positive float.  This defines the values of base_noise_A
    and base_noise_n to be used in the experiments. Call a given tuple
    t. Then base_noise_A = t[0] and base_noise_n = t[1].

    noise_modifier_list - list of 4-tuples; the entries of each tuple
    should be floats. Call a given tuple t. This modifies the base noise
    so that the L^\infty norms of A and n are less than or equal to
    (respectively) base_noise_A * h**t[0] * k**t[1] and base_noise_n *
    h**t[2] * k**t[3].

    save_location - see utils.write_repeats_to_csv.

    """

    if not(isinstance(A_pre_type,str)):
        raise TypeError("Input A_pre_type should be a string")
    elif A_pre_type is not "constant":
        raise HelmholtzNotImplementedError(
            "Currently only implemented A_pre_type = 'constant'.")

    if not(isinstance(n_pre_type,str)):
        raise TypeError("Input n_pre_type should be a string")

    if not(isinstance(k_list,list)):
        raise TypeError("Input k_list should be a list.")
    elif any(not(isinstance(k,float)) for k in k_list):
        raise TypeError("Input k_list should be a list of floats.")
    elif any(k <= 0 for k in k_list):
        raise TypeError(
            "Input k_list should be a list of positive floats.")

    if not(isinstance(h_list,list)):
        raise TypeError("Input h_list should be a list.")
    elif any(not(isinstance(h_tuple,tuple)) for h_tuple in h_list):
        raise TypeError("Input h_list should be a list of tuples.")
    elif any(len(h_tuple) is not 2 for h_tuple in h_list):
        raise TypeError("Input h_list should be a list of 2-tuples.")
    elif any(not(isinstance(h_tuple[0],float)) for h_tuple in h_list)\
             or any(h_tuple[0] <= 0 for h_tuple in h_list):
        raise TypeError(
            "The first item of every tuple in h_list\
            should be a positive float.")
    elif any(not(isinstance(h_tuple[1],float)) for h_tuple in h_list):
        raise TypeError(
            "The second item of every tuple in h_list should be a float.")

    if not(isinstance(noise_master_level_list,list)):
        raise TypeError(
            "Input noise_master_level_list should be a list.")
    elif any(not(isinstance(noise_tuple,tuple))
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list should be a list of tuples.")
    elif any(len(noise_tuple) is not 2
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list should be a list of 2-tuples.")
    elif any(any(not(isinstance(noise_tuple[i],float))
                 for i in range(len(noise_tuple)))
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list\
            should be a list of 2-tuples of floats.")

    if not(isinstance(noise_modifier_list,list)):
        raise TypeError("Input noise_modifier_list should be a list.")
    elif any(not(isinstance(mod_tuple,tuple))
             for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list should be a list of tuples.")
    elif any(len(mod_tuple) is not 4 for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list should be a list of 4-tuples.")
    elif any(any(not(isinstance(mod_tuple[i],float))
                 for i in range(len(mod_tuple)))
             for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list\
            should be a list of 4-tuples of floats.")


    
    for k in k_list:
        for h_tuple in h_list:
            for p in p_list:
                h = h_tuple[0] * k**h_tuple[1]
                mesh_points = hh_utils.h_to_num_cells(h,dim)
                mesh = fd.UnitSquareMesh(mesh_points,mesh_points)
                V = fd.FunctionSpace(mesh, "CG", p)
                f = 0.0
                d = fd.as_vector([1.0/fd.sqrt(2.0),1.0/fd.sqrt(2.0)])
                x = fd.SpatialCoordinate(mesh)
                nu = fd.FacetNormal(mesh)
                g=1j*k*fd.exp(1j*k*fd.dot(x,d))*(fd.dot(d,nu)-1)

                if A_pre_type is "constant":
                    A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])

                if n_pre_type is "constant":
                    n_pre = 1.0

                elif n_pre_type is "jump_down":
                    n_pre = (2.0/3.0)\
                            + hh_utils.nd_indicator(
                                x,1.0/3.0,
                                np.array([[1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0]]
                                )
                            )

                elif n_pre_type is "jump_up":
                    n_pre = 1.5\
                            + hh_utils.nd_indicator(
                                x,-1.0/2.0,
                                np.array([[1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0]]
                                )
                            )


                for noise_master in noise_master_level_list:
                    A_noise_master = noise_master[0]
                    n_noise_master = noise_master[1]

                    for modifier in noise_modifier_list:
                        if fd.COMM_WORLD.rank == 0:
                            print(k,h_tuple,noise_master,modifier)

                        A_modifier = h ** modifier[0] * k**modifier[1]
                        n_modifier = h ** modifier[2] * k**modifier[3]
                        A_noise_level = A_noise_master * A_modifier
                        n_noise_level = n_noise_master * n_modifier

                        A_stoch = coeff.PiecewiseConstantCoeffGenerator(
                            mesh,num_pieces,A_noise_level,A_pre,[2,2])
                        n_stoch = coeff.PiecewiseConstantCoeffGenerator(
                            mesh,num_pieces,n_noise_level,n_pre,[1])
                        np.random.seed(seed)

                        GMRES_its = nearby_preconditioning_experiment(
                            V,k,A_pre,A_stoch,n_pre,n_stoch,f,g,num_repeats)

                        if fd.COMM_WORLD.rank == 0:
                            hh_utils.write_GMRES_its(
                                GMRES_its,save_location,
                                {'k' : k,
                                 'h_tuple' : h_tuple,
                                 'p' : p,
                                 'num_pieces' : num_pieces,
                                 'A_pre_type' : A_pre_type,
                                 'n_pre_type' : n_pre_type,
                                 'noise_master' : noise_master,
                                 'modifier' : modifier,
                                 'num_repeats' : num_repeats
                                 }
                                )
Example #27
0
    def setup(self, state):

        space = state.spaces("HDiv")
        super(SawyerEliassenU, self).setup(state, space=space)

        u = state.fields("u")
        b = state.fields("b")
        v = inner(u, as_vector([0., 1., 0.]))

        # spaces
        V0 = FunctionSpace(state.mesh, "CG", 2)
        Vu = u.function_space()

        # project b to V0
        self.b_v0 = Function(V0)
        btri = TrialFunction(V0)
        btes = TestFunction(V0)
        a = inner(btes, btri) * dx
        L = inner(btes, b) * dx
        projectbproblem = LinearVariationalProblem(a, L, self.b_v0)
        self.project_b_solver = LinearVariationalSolver(
            projectbproblem, solver_parameters={'ksp_type': 'cg'})

        # project v to V0
        self.v_v0 = Function(V0)
        vtri = TrialFunction(V0)
        vtes = TestFunction(V0)
        a = inner(vtes, vtri) * dx
        L = inner(vtes, v) * dx
        projectvproblem = LinearVariationalProblem(a, L, self.v_v0)
        self.project_v_solver = LinearVariationalSolver(
            projectvproblem, solver_parameters={'ksp_type': 'cg'})

        # stm/psi is a stream function
        self.stm = Function(V0)
        psi = TrialFunction(V0)
        xsi = TestFunction(V0)

        f = state.parameters.f
        H = state.parameters.H
        L = state.parameters.L
        dbdy = state.parameters.dbdy
        x, y, z = SpatialCoordinate(state.mesh)

        bcs = [DirichletBC(V0, 0., "bottom"), DirichletBC(V0, 0., "top")]

        Mat = as_matrix([[b.dx(2), 0., -f * self.v_v0.dx(2)], [0., 0., 0.],
                         [-self.b_v0.dx(0), 0., f**2 + f * self.v_v0.dx(0)]])

        Equ = (inner(grad(xsi), dot(Mat, grad(psi))) -
               dbdy * inner(grad(xsi), as_vector([-v, 0., f *
                                                  (z - H / 2)]))) * dx

        # fourth-order terms
        if state.parameters.fourthorder:
            eps = Constant(0.0001)
            brennersigma = Constant(10.0)
            n = FacetNormal(state.mesh)
            deltax = Constant(state.parameters.deltax)
            deltaz = Constant(state.parameters.deltaz)

            nn = as_matrix([[sqrt(brennersigma / Constant(deltax)), 0., 0.],
                            [0., 0., 0.],
                            [0., 0.,
                             sqrt(brennersigma / Constant(deltaz))]])

            mu = as_matrix([[1., 0., 0.], [0., 0., 0.], [0., 0., H / L]])

            # anisotropic form
            Equ += eps * (
                div(dot(mu, grad(psi))) * div(dot(mu, grad(xsi))) * dx -
                (avg(dot(dot(grad(grad(psi)), n), n)) * jump(grad(xsi), n=n) +
                 avg(dot(dot(grad(grad(xsi)), n), n)) * jump(grad(psi), n=n) -
                 jump(nn * grad(psi), n=n) * jump(nn * grad(xsi), n=n)) *
                (dS_h + dS_v))

        Au = lhs(Equ)
        Lu = rhs(Equ)
        stmproblem = LinearVariationalProblem(Au, Lu, self.stm, bcs=bcs)
        self.stream_function_solver = LinearVariationalSolver(
            stmproblem, solver_parameters={'ksp_type': 'cg'})

        # solve for sawyer_eliassen u
        self.u = Function(Vu)
        utrial = TrialFunction(Vu)
        w = TestFunction(Vu)
        a = inner(w, utrial) * dx
        L = (w[0] * (-self.stm.dx(2)) + w[2] * (self.stm.dx(0))) * dx
        ugproblem = LinearVariationalProblem(a, L, self.u)
        self.sawyer_eliassen_u_solver = LinearVariationalSolver(
            ugproblem, solver_parameters={'ksp_type': 'cg'})
def generate_samples(k,h_spec,J,nu,M,
                     point_generation_method,
                     delta,lambda_mult,j_scaling,
                     qois,
                     num_spatial_cores,dim=2,
                     display_progress=False,physically_realistic=False,
                     nearby_preconditioning=False,
                     nearby_preconditioning_proportion=1):
    
    """Generates samples for Monte-Carlo methods for Helmholtz.

    Computes an approximation to the root-mean-squared error in
    Monte-Carlo or Quasi-Monte Carlo approximations of expectations of
    quantities of interest associated with the solution of a stochastic
    Helmholtz problem, where the randomness enters through a random
    field refractive index, given by an artificial-KL expansion.

    Parameters:

    k - positive float - the wavenumber for which to do computations.

    h_spec - 2-tuple - h_spec[0] should be a positive float and
    h_spec[1] should be a float. These specify the values of the mesh
    size h for which we will run experiments.
    h = h_spec[0] * k**h_spec[1].

    J - positive int - the stochastic dimension in the artificial-KL
    expansion for which to do experiments.

    nu - positive int - the number of random shifts to use in
    randomly-shifted QMC methods. Combines with M to give number of
    integration points for Monte Carlo.

    M - positive int - Specifies the number of integration points for
    which to do computations - NOTE: for Monte Carlo, the number of
    integration points will be given by nu*(2**M). For Quasi-Monte
    Carlo, we will sample 2**m integration points, and then randomly
    shift these nu times as part of the estimator.

    point_generation_method string - either 'mc' or 'qmc', specifying
    Monte-Carlo point generation or Quasi-Monte-Carlo (based on an
    off-the-shelf lattice rule). Monte-Carlo generation currently
    doesn't work, and so throws an error.

    delta - parameter controlling the rate of decay of the magntiude of
    the coefficients in the artifical-KL expansion - see
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff for more
    information.

    lambda_mult - parameter controlling the absolute magntiude of the
    coefficients in the artifical-KL expansion - see
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff for more
    information.


    j_scaling - parameter controlling the oscillation in the basis
    functions in the artifical-KL expansion - see
    helmholtz_firedrake.coefficients.UniformKLLikeCoeff for more
    information.

    qois - list of strings - the Quantities of Interest that are
    computed. Currently the only options for the elements of the string
    are:
        'integral' - the integral of the solution over the domain.
        'origin' the point value at the origin.
        'top_right' the point value at (1,1)
        'gradient_top_right' the gradient at (1,1)
    There are also the options 'testing' and 'testing_qmc', but these
    are used solely for testing the functions.

    num_spatial_cores - int - the number of cores we want to use to
    solve our PDE. (You need to specify this as we might use ensemble
    parallelism to speed things up.)

    dim - either 2 or 3 - the spatial dimension of the Helmholtz
    Problem.

    display_progress - boolean - if true, prints the sample number each
    time we sample.

    physically_realistic - boolean - if true, f and g correspond to a
    scattered plane wave, n is cut off away from the truncation
    boundary, and n is >= 0.1. Otherwise, f and g are given by a plane
    wave. The 'false' option is used to verify regression tests.

    nearby_preconditioning - boolean - if true, nearby preconditioning
    is used in the solves. A proportion (given by nearby_preconditioning
    proportion) of the realisations have their exact LU decompositions
    computed, and then these are used as preconditioners for all the
    other problems (where the preconditioner used is determined by the
    nearest problem, in some metric, that has had a preconditioner
    computed). Note that if ensembles are used to speed up the solution
    time, some LU decompositions may be calculated more than once. But
    for the purposes of assessing the effectiveness of the algorithm (in
    terms of total # GMRES iterations), this isn't a problem.

    nearby_preconditioning_proportion - float in [0,1]. See the text for
    nearby_preconditioning above.

    Output:
    If point_generation_method is 'qmc', then 
    output is a list: [k,samples,n_coeffs,GMRES_its,]

    k is a float - the wavenumber.

    samples is a list of length nu, where each entry of samples is a
    list of length num_qois, each entry of which is a numpy array of
    length 2**M, each entry of which is either: (i) a (complex-valued)
    float, or (ii) a numpy column vector, corresponding to a sample of
    the QoI.

    n_coeffs is a list of length nu, each entry of which is a 2**M by J
    numpy array, each row of which contains the KL-coefficients needed
    to generate the particular realisation of n.

    GMRES_its is a list of length nu, each entry of which is a list of
    length 2**M, containing ints - these are the number of GMRES
    iterations required for each sample.
    """
    
    if point_generation_method is 'mc':
        raise NotImplementedError("Monte Carlo sampling currently doesn't work")
        
    num_qois = len(qois)
    
    mesh_points = hh_utils.h_to_num_cells(h_spec[0]*k**h_spec[1],
                                              dim)
    
    ensemble = fd.Ensemble(fd.COMM_WORLD,num_spatial_cores)
    
    mesh = fd.UnitSquareMesh(mesh_points,mesh_points,comm=ensemble.comm)

    comm = ensemble.ensemble_comm

    n_coeffs = []
        
    if point_generation_method is 'mc':
        # This needs updating one I've figured out a way to do seeding
        # in a parallel-appropriate way
        N = nu*(2**M)
        kl_mc_points = point_gen.mc_points(
            J,N,point_generation_method,seed=1)

    elif point_generation_method is 'qmc':
        N = 2**M
        kl_mc_points = point_gen.mc_points(
            J,N,point_generation_method,section=[comm.rank,comm.size],seed=1)

    n_0 = 1.0

    kl_like = coeff.UniformKLLikeCoeff(
        mesh,J,delta,lambda_mult,j_scaling,n_0,kl_mc_points)       
        
    # Create the problem
    V = fd.FunctionSpace(mesh,"CG",1)
    prob = hh.StochasticHelmholtzProblem(
        k,V,A_stoch=None,n_stoch=kl_like,
        **{'A_pre' : fd.as_matrix([[1.0,0.0],[0.0,1.0]])})

    angle = np.pi/4.0
    
    if physically_realistic:

       make_physically_realistic(prob,angle)
    else:
        prob.f_g_plane_wave([np.cos(angle),np.sin(angle)])
                
    if point_generation_method is 'mc':

        samples = all_qoi_samples(prob,qois,ensemble.comm,display_progress)
                        
    elif point_generation_method == 'qmc':

        samples = []

        GMRES_its = []
                   
        for shift_no in range(nu):
            if display_progress:
                print('Shift number:',shift_no+1,flush=True)
            # Randomly shift the points
            prob.n_stoch.change_all_points(
                point_gen.shift(kl_mc_points,seed=shift_no))

            n_coeffs.append(deepcopy(prob.n_stoch.current_and_unsampled_points()))

            if nearby_preconditioning:
                [centres,nearest_centre] = find_nbpc_points(M,nearby_preconditioning_proportion,
                                                            prob.n_stoch,J,point_generation_method,
                                                            prob.n_stoch.current_and_unsampled_points(),
                                                            shift_no)
            else:
                centres = None
                nearest_centre = None

            [this_samples,this_GMRES_its] = all_qoi_samples(prob,qois,ensemble.comm,display_progress,
                                                            centres,nearest_centre,J,delta,lambda_mult,
                                                            j_scaling,n_0,angle,physically_realistic)
            
            # For outputting samples and GMRES iterations
            samples.append(this_samples)
            GMRES_its.append(this_GMRES_its)
            

    comm = ensemble.ensemble_comm

    samples = fancy_allgather(comm,samples,'samples')

    n_coeffs = fancy_allgather(comm,n_coeffs,'coeffs')

    # Have to hack around GMRES_its because it's not *quite* in the
    # right format

# list of list of Nones or Floats
# But if we don't use NBPC, then it's a list of Nones
    
    GMRES_its = [[np.array(ii)] for ii in GMRES_its]
    
    GMRES_its = fancy_allgather(comm,GMRES_its,'samples')

    GMRES_its = [ii[0].tolist() for ii in GMRES_its]
    
    return [k,samples,n_coeffs,GMRES_its,]
Example #29
0
def test_evp_convergence(state, norm_type, theta, family):
    timestep = 1
    dumpfreq = 10 ** 6
    timescale = 2
    number_of_triangles = [5, 10, 20, 40, 80]
    length = 5 * 10 ** 5
    pi_x = pi / length

    zero = Constant(0)
    zero_vector = Constant(as_vector([0, 0]))

    dirname = "./output/test-output/test.pvd"
    plot_dirname = "./output/test-output/srt-conv.png"

    error_values = []

    timestepping = TimesteppingParameters(timescale=timescale, timestep=timestep)
    output = OutputParameters(dirname=dirname, dumpfreq=dumpfreq)
    solver = SolverParameters()
    params = SeaIceParameters(rho_a=zero, C_a=zero, cor=zero)

    for values in number_of_triangles:
        mesh = SquareMesh(values, values, length)
        x, y = SpatialCoordinate(mesh)

        v_exp = as_vector([-sin(pi_x * x) * sin(pi_x * y), -sin(pi_x * x) * sin(pi_x * y)])
        sigma_exp = as_matrix([[-sin(pi_x * x) * sin(pi_x * y), -sin(pi_x * x) * sin(pi_x * y)],
                               [-sin(pi_x * x) * sin(pi_x * y), -sin(pi_x * x) * sin(pi_x * y)]])

        ocean_curr = as_vector([0.1 * (2 * y - length) / length, -0.1 * (length - 2 * x) / length])

        ic = {'u': v_exp, 'a' : 1, 'h' : 1, 's': sigma_exp}
        
        stabilised={'state':state ,'alpha':1}

        conditions = Conditions(ic=ic, ocean_curr=ocean_curr, stabilised=stabilised, family=family)

        evp = ElasticViscousPlastic(mesh=mesh, conditions=conditions, timestepping=timestepping, output=output, params=params,
                                    solver_params=solver)

        u1, s1 = split(evp.w1)
        u0, s0 = split(evp.w0)

        uh = (1-theta) * u0 + theta * u1
        sh = (1-theta) * s0 + theta * s1

        eqn = inner(params.rho * evp.h * (u1 - u0), evp.p) * dx
        eqn += timestep * inner(sh, grad(evp.p)) * dx
        eqn -= timestep * inner(params.rho_w * params.C_w * sqrt(dot(ocean_curr - uh, ocean_curr - uh)) * (ocean_curr - uh), evp.p) * dx

        # source terms in momentum equation=-==
        eqn += timestep * inner(div(sigma_exp), evp.p) * dx
        eqn += timestep * inner(params.rho_w * params.C_w * sqrt(dot(ocean_curr - v_exp, ocean_curr - v_exp)) * (ocean_curr - v_exp), evp.p) * dx

        zeta_exp = evp.zeta(evp.h, evp.a, evp.delta(v_exp))
        ep_dot_exp = evp.strain(grad(v_exp))
        rheology_exp = params.e ** 2 * sigma_exp + Identity(2) * 0.5 * ((1 - params.e ** 2) * tr(sigma_exp) + evp.Ice_Strength(evp.h, evp.a))
        zeta = evp.zeta(evp.h, evp.a, evp.delta(uh))
    
        eqn += inner(s1 - s0 + 0.5 * timestep * evp.rheology / params.T, evp.q) * dx
        eqn -= inner(evp.q * zeta * timestep / params.T, evp.ep_dot) * dx

        # source terms in rheology 
        eqn -= inner(0.5 * timestep * rheology_exp / params.T, evp.q) * dx
        eqn += inner(evp.q * zeta_exp * timestep / params.T, ep_dot_exp) * dx
    
        evp.assemble(eqn, evp.w1, evp.bcs, solver.srt_params)

        t = 0

        u1, s1 = evp.w1.split()
    
        evp.dump(u1, s1, t=0)

        while t < timescale - 0.5 * timestep:
            u0, s0 = evp.w0.split()
            evp.solve(evp.usolver)
            evp.update(evp.w0, evp.w1)
            t += timestep
            evp.dump(u1, s1, t=t)
            evp.progress(t)
            
        error_values.append(Error.compute(u1, v_exp, norm_type))
        
    h = [sqrt(2)*length/x for x in number_of_triangles]
    error_slope = float(format(np.polyfit(np.log(h), np.log(error_values), 1)[0], '.3f'))

    assert round(error_slope - 2, 1) == 0
Example #30
0
    def __init__(self,
                 k,
                 V,
                 A=fd.as_matrix([[1.0, 0.0], [0.0, 1.0]]),
                 n=1.0,
                 A_pre=None,
                 n_pre=None,
                 f=1.0,
                 g=0.0):
        """Creates an instance of HelmholtzProblem.

        Parameters:

        k - a positive float

        V - a Firedrake FunctionSpace defined on a mesh

        A - A UFL (possibly containing Firedrake Constants) expression
        for the 'diffusion coefficient'. Output should be a spatially
        heterogeneous symmetric 2x2 matrix.

        n - A UFL expression (possibly containing Firedrake Constants)
        for the 'squared slowness'. Output should be a spatially
        heterogeneous real.

        A_pre - None, or a UFL expression (possibly containing Firedrake
        Constants) for the 'diffusion coefficient' for the
        preconditioning problem. Output should be a spatially
        heterogeneous symmetric 2x2 matrix.

        n_pre - None, or a UFL expression (possibly containing Firedrake
        Constants) for the 'squared slowness' for the preconditioning
        problem. Output should be a spatially heterogeneous real.

        f - A UFL expression for the right-hand side of the Helmholtz
        PDE.

        g - A UFL expression for the right-hand side of the impedance
        boundary condition.
        """
        #import pdb; pdb.set_trace()
        self._initialised = False

        self.set_k(k)

        self.set_A(A)

        self.set_n(n)

        self.set_A_pre(A_pre)

        self.set_n_pre(n_pre)

        self.set_f(f)

        self.set_g(g)

        self.V = V

        self._solver_params_override = False

        self._using_GMRES = True

        self.GMRES_its = -1
        """int - number of GMRES iterations. Initialised as -1."""

        self.u_h = fd.Function(self.V)
        """Firedrake function - initialised as zero function."""