def make_from_data(data, assembly_type): """ Creating a finite element operator from internal data and an assembly type. :param: data: data defining the operator. :param: assembly_type: type of assembling procedure. """ operator = FiniteElementOperator(fe_space=fe_sp.FiniteElementSpace(), assembly_type=assembly_type) operator.assembly_type = assembly_type if assembly_type is AssemblyType.ASSEMBLED: if len(data.shape) is 2: operator.data = scipy.sparse.csc_matrix(data) else: raise ValueError( "Expecting two dimensional array when creating ASSEMBLED operator from data." ) elif assembly_type is AssemblyType.LOCALLY_ASSEMBLED: if len(data.shape) is 1: operator.data = data else: raise ValueError( "Expecting one dimensional array when creating LOCALLY_ASSEMBLED operator from data." ) elif assembly_type is AssemblyType.LUMPED: if len(data.shape) is 1: operator.data = data else: raise ValueError( "Expecting one dimensional array when creating LUMPED operator from data." ) return operator
def test_locals_to_globals(): """ Testing extracting of global indexes from an element index. """ fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, -1.0, -4.0]), fe_order=3) np_test.assert_array_equal(fe_space.locals_to_globals(1), [3, 4, 5, 6])
def test_get_coord(): """ Testing coordinate computation from parametric coordinate of an element. """ random.seed() # Mesh with positive coordinates. fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0, 4.0]), fe_order=3) for _ in range(50): v = random.random() np_test.assert_almost_equal(fe_space.get_coord(1, v), 1.0 + 3.0 * v) # Mesh with negative coordinates. fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, -1.0, -4.0]), fe_order=3) for _ in range(50): v = random.random() np_test.assert_almost_equal(fe_space.get_coord(0, v), -4.0 + 3.0 * v)
def test_locals_to_globals_discontinuous(): """ Testing extracting of global indexes in discontinuous numbering from an element index. """ fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, -1.0, -4.0]), fe_order=3) np_test.assert_array_equal(fe_space.locals_to_globals_discontinuous(0), [0, 1, 2, 3]) np_test.assert_array_equal(fe_space.locals_to_globals_discontinuous(1), [4, 5, 6, 7])
def test_assembled_stiffness_p2(): """ Testing assembling routine in the case of p2 finite element space on one element. """ p = 2.3 fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0]), fe_order=2, quad_order=2) stiffness = stiffness_assembler.assemble_stiffness(fe_space, lambda s: p) np_test.assert_array_almost_equal(stiffness.data.data, [7.0 * p / 3.0, -8.0 * p / 3.0, p / 3.0, -8.0 * p / 3.0, 16.0 * p / 3.0, -8.0 * p / 3.0, p / 3.0, -8.0 * p / 3.0, 7.0 * p / 3.0])
def test_get_quadrature_weight(): """ Testing extractin of quadrature weights. """ fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0]), fe_order=3, quad_order=4) _, w = lag_poly.make_quadrature_formula( 4, lag_poly.PointDistributionType.GAUSS_LOBATTO) for iq in range(len(w)): np_test.assert_almost_equal(fe_space.get_quadrature_weight(iq), w[iq])
def test_assembled_mass_p1(): """ Testing assembling routine in the case of p1 finite element space on one element. """ cte_density = 2.3 fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0]), fe_order=1, quad_order=2) mass = mass_assembler.assemble_mass(fe_space, lambda s: cte_density) np_test.assert_array_almost_equal(mass.data.data, [ cte_density / 3.0, cte_density / 6.0, cte_density / 6.0, cte_density / 3.0 ])
def test_apply_basis_diag_basis(): """ Testing basisx * diag * basis^T operation. """ distrib_type = lag_poly.PointDistributionType.EQUALLY_DISTRIBUTED fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0]), fe_order=2, basis_type=distrib_type, quad_order=2, quad_type=distrib_type) test_diag = [666.0, 666.0, 666.0] np_test.assert_array_almost_equal( fe_space.apply_basis_diag_basis(test_diag), np.diag(test_diag))
def test_make_finite_element_space(): """ Simple construction of a finite element space. """ fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0, 4.0]), fe_order=3, quad_order=4) np_test.assert_equal(fe_space.get_ndof(), 7) np_test.assert_equal(fe_space.get_nelem(), 2) np_test.assert_almost_equal(fe_space.get_elem_length(0), 1.0) np_test.assert_almost_equal(fe_space.get_elem_length(1), 3) np_test.assert_equal(fe_space.get_nlocaldof(), 4) np_test.assert_equal(fe_space.get_left_idx(), 0) np_test.assert_equal(fe_space.get_right_idx(), 6)
def test_lumped_mass_p2(): """ Testing mass lumping routine in the case of p2 finite element spaces. """ def density(x): return 2.3 * x + 1.3 fe_space = fe_sp.FiniteElementSpace(mesh.Mesh([0.0, 1.0, 4.0]), fe_order=2, quad_order=2) assemb_mass = mass_assembler.assemble_mass( fe_space, density, fe_op.AssemblyType.ASSEMBLED).data.todense() lumped_mass = np.diag( mass_assembler.assemble_mass(fe_space, density, fe_op.AssemblyType.LUMPED).data) np_test.assert_array_almost_equal(assemb_mass, lumped_mass)
def test_eval_at_quadrature_pnts(): """ Testing evaluation of callable at quadrature points. """ fe_space = fe_sp.FiniteElementSpace( mesh.Mesh([0.0, -1.0, -4.0]), quad_order=3, quad_type=lag_poly.PointDistributionType.EQUALLY_DISTRIBUTED) # Testing quadrature point indexes. np_test.assert_array_equal( fe_space.eval_at_quadrature_pnts(lambda k, s: k), [0, 1, 2, 3]) # Testing quadrature points coordinates. p, _ = lag_poly.make_quadrature_formula( 3, lag_poly.PointDistributionType.EQUALLY_DISTRIBUTED) np_test.assert_array_equal( fe_space.eval_at_quadrature_pnts(lambda k, s: s), p)
def assemble_discontinuous_mass(fe_space, density=lambda x: 1.0, assembly_type=fe_op.AssemblyType.ASSEMBLED): """ Assembling discontinuous mass matrix. :param fe_space: input finite element space. :param density: function of space variable. :param assembly_type: type of assembling procedure. :return: instance of FiniteElementOperator class representing the discontinuous mass operator. """ if assembly_type is fe_op.AssemblyType.LUMPED: discontinuous_mass = fe_op.FiniteElementOperator( fe_space=fe_sp.FiniteElementSpace(), assembly_type=assembly_type) discontinuous_mass.data = np.zeros(fe_space.get_nelem() * fe_space.get_nlocaldof()) apply_discontinuous_mass_lumping(fe_space, density, discontinuous_mass.data) return discontinuous_mass else: raise NotImplementedError()
def assemble_gradient(fe_space, param=lambda x: 1.0, assembly_type=fe_op.AssemblyType.ASSEMBLED): """ Assembling gradient operator applied on a unknown in H^1-conform discrete space and return a result in a L^2-conform discrete space. :param fe_space: input finite element space. :param param: function of space variable. :param assembly_type: type of assembling procedure. :return: instance of FiniteElementOperator class representing the gradient operator. """ if assembly_type is fe_op.AssemblyType.ASSEMBLED: # Computing operator data. lil_gradient = scipy.sparse.lil_matrix((fe_space.get_nelem() * fe_space.get_nlocaldof(), fe_space.get_ndof())) apply_gradient_assembling(fe_space, param, lil_gradient) # Setting operator data. gradient = fe_op.FiniteElementOperator(fe_space=fe_sp.FiniteElementSpace(), assembly_type=assembly_type) gradient.data = lil_gradient.tocsc() return gradient else: raise NotImplementedError()
# Creating left dirichlet boundary condition. left_bc = configuration.BoundaryCondition(boundary_condition_type=configuration.BoundaryConditionType.DIRICHLET, value=lambda t: functional.ricker(t - src_offset, central_frequency)) absorbing_param = np.sqrt(rho(0.) * modulus(0.)) right_bc = configuration.BoundaryCondition(boundary_condition_type=configuration.BoundaryConditionType.ABSORBING, value=lambda t: 0, param=absorbing_param) # Creating configuration. config = configuration.ViscoElasticKelvinVoigt(density=rho, modulus=modulus, eta=eta, left_bc=left_bc, right_bc=right_bc) # Creating finite element space. fe_space = fe_sp.FiniteElementSpace(mesh=mesh.make_mesh_from_npt(0.0, 10.0, 300), fe_order=5, quad_order=5) # Creating propagator. propag = visco_elastic_kelvin_voigt_propagator.ViscoElasticKelvinVoigt(config=config, fe_space=fe_space) # Initializing. propag.initialize() # Runing. if show_snapshot: fig, ax = plt.subplots() lines = ax.plot(propag.u0) ax.set_ylim((-1, 1)) plt.ylabel("u (mm)") plt.xlabel("x (mm)")