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 initialize(self, timestep=None, cfl_factor=0.95): """ Initializing discrete propagator. :param timestep: intput timestep, if timestep is None, time step is computed using CFL condition. :param cfl_factor: factor to be applied on CFL condition. """ ndof_h1 = self.fe_space.get_ndof() ndof_l2 = self.fe_space.get_nelem() * self.fe_space.get_nlocaldof() # Allocating displacement unknown. self.u0 = np.zeros(ndof_h1) self.u1 = np.zeros(ndof_h1) self.u2 = np.zeros(ndof_h1) self.ustar = np.zeros(ndof_h1) # Allocating internal variable unknown. self.s0 = np.zeros(ndof_l2) self.s1 = np.zeros(ndof_l2) self.sstar = np.zeros(ndof_l2) # Extracting material parameteris. rho = self.config.density modulus = self.config.modulus eta = self.config.eta tau = self.config.tau # Definition of material parameters used in assembling procedures. def tau_s(x): return 1.0 / (tau(x) * (eta(x) - modulus(x))) def tau_prime_s(x): return 1.0 / (eta(x) - modulus(x)) # Assembling displacement operators. mass_rho = mass_assembler.assemble_mass(self.fe_space, rho, fe_op.AssemblyType.LUMPED) stiffness_MR = stiffness_assembler.assemble_stiffness( self.fe_space, modulus) # Assembling internal variable operators. mass_tau_s = mass_assembler.assemble_discontinuous_mass( self.fe_space, tau_s, fe_op.AssemblyType.LUMPED) mass_tau_prime_s = mass_assembler.assemble_discontinuous_mass( self.fe_space, tau_prime_s, fe_op.AssemblyType.LUMPED) # Computing gradient operators. self.gradient = gradient_assembler.assemble_gradient(self.fe_space) self.transposed_gradient = gradient_assembler.assemble_transposed_gradient( self.fe_space) # Computing CFL or setting timestep if timestep is None: stiffness_k1 = stiffness_assembler.assemble_stiffness( self.fe_space, eta) cfl = 2.0 / np.sqrt(fe_op.spectral_radius(mass_rho, stiffness_k1)) self.timestep = cfl_factor * cfl else: self.timestep = timestep # Computing operator applied on u1 self.operator1_u = fe_op.linear_combination(2.0, mass_rho, -self.timestep**2, stiffness_MR) # Computing operator applied on u2 self.operator2_u = fe_op.clone(-1.0, mass_rho) self.__add_boundary_contrib_operator2( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_operator2( self.config.right_boundary_condition, self.fe_space.get_right_idx()) # Computing inv operator applied on displacement unknown. self.inv_operator_u = fe_op.clone(1.0, mass_rho) self.__add_boundary_contrib_inv_operator( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_inv_operator( self.config.right_boundary_condition, self.fe_space.get_right_idx()) fe_op.inv(self.inv_operator_u) # Computing operator applied on s1. self.operator1_s = fe_op.linear_combination(1.0, mass_tau_prime_s, -self.timestep * 0.5, mass_tau_s) # Computing inv operator applied on internal variable. self.inv_operator_s = fe_op.linear_combination(1.0, mass_tau_prime_s, self.timestep * 0.5, mass_tau_s) fe_op.inv(self.inv_operator_s) # Computing rhs operator. if self.config.rhs is not None: raise NotImplementedError() # Applying initial conditions. if self.init_cond_type is not InitialConditionType.NONE: raise NotImplementedError()
def initialize(self, timestep=None, cfl_factor=0.95): """ Initializing discrete propagator. :param timestep: intput timestep, if timestep is None, time step is computed using CFL condition. :param cfl_factor: factor to be applied on CFL condition. """ # Allocating and applying initial conditions. ndof = self.fe_space.get_ndof() self.u0 = np.zeros(ndof) self.u1 = np.zeros(ndof) self.u2 = np.zeros(ndof) self.ustar = np.zeros(ndof) # Assembling mass, stiffness and viscosity operators. mass = mass_assembler.assemble_mass(self.fe_space, self.config.density, fe_op.AssemblyType.LUMPED) stiffness = stiffness_assembler.assemble_stiffness( self.fe_space, self.config.modulus) viscosity = stiffness_assembler.assemble_stiffness( self.fe_space, self.config.eta) if self.scheme_type is SchemeType.IMPLICIT_ORDERTWO: # Computing CFL or setting timestep. if timestep is None: cfl = 2.0 / np.sqrt(fe_op.spectral_radius(mass, stiffness)) self.timestep = cfl_factor * cfl else: self.timestep = timestep # Computing operator to apply on u1. self.operator1 = fe_op.linear_combination(2.0, mass, -self.timestep**2, stiffness) # Computing operator to apply on u2. self.operator2 = fe_op.linear_combination(-1.0, mass, self.timestep * 0.5, viscosity) self.__add_boundary_contrib_operator2( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_operator2( self.config.right_boundary_condition, self.fe_space.get_right_idx()) # Computing rhs operator. if self.config.rhs is not None: self.rhs_operator = mass_assembler.assemble_mass( lambda x: 1.0, self.fe_space, fe_op.AssemblyType.LUMPED) # Computing inv operator. self.inv_operator = fe_op.linear_combination( 1.0, mass, self.timestep * 0.5, viscosity) self.__add_boundary_contrib_inv_operator( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_inv_operator( self.config.right_boundary_condition, self.fe_space.get_right_idx()) fe_op.inv(self.inv_operator) elif self.scheme_type is SchemeType.EXPLICIT_ORDERONE: # Computing CFL or setting timestep. if timestep is None: r_stiff = fe_op.spectral_radius(mass, stiffness) r_visc = fe_op.spectral_radius(mass, viscosity) cfl = (np.sqrt((4.0 * r_stiff) / (r_visc**2) + 1.0) - 1.0) * (r_visc / r_stiff) self.timestep = cfl_factor * cfl else: self.timestep = timestep # Computing operator to apply on u1. tmp_operator = fe_op.linear_combination(2.0, mass, -self.timestep**2, stiffness) self.operator1 = fe_op.linear_combination(1.0, tmp_operator, -self.timestep, viscosity) # Computing operator to apply on u2. self.operator2 = fe_op.linear_combination(-1.0, mass, self.timestep, viscosity) self.__add_boundary_contrib_operator2( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_operator2( self.config.right_boundary_condition, self.fe_space.get_right_idx()) # Computing rhs operator. if self.config.rhs is not None: self.rhs_operator = mass_assembler.assemble_mass( lambda x: 1.0, self.fe_space, fe_op.AssemblyType.LUMPED) # Computing inv operator. self.inv_operator = fe_op.clone(1.0, mass) self.__add_boundary_contrib_inv_operator( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_inv_operator( self.config.right_boundary_condition, self.fe_space.get_right_idx()) fe_op.inv(self.inv_operator) # Applying initial conditions. if self.init_cond_type is not InitialConditionType.NONE: raise NotImplementedError()
def initialize(self, timestep=None, cfl_factor=0.95): """ Initializing discrete propagator. :param timestep: intput timestep, if timestep is None, time step is computed using CFL condition. :param cfl_factor: factor to be applied on CFL condition. """ # Allocating and applying initial conditions. ndof = self.fe_space.get_ndof() self.u0 = np.zeros(ndof) self.u1 = np.zeros(ndof) self.u2 = np.zeros(ndof) self.ustar = np.zeros(ndof) # Assembling mass and stiffness operators. mass = mass_assembler.assemble_mass(self.fe_space, self.config.alpha, self.mass_assembly_type) stiffness = stiffness_assembler.assemble_stiffness( self.fe_space, self.config.beta, self.stiffness_assembly_type) # Computing CFL or setting timestep. if timestep is None: cfl = 2.0 / np.sqrt(fe_op.spectral_radius(mass, stiffness)) self.timestep = cfl_factor * cfl else: self.timestep = timestep # Computing operator to apply on u1. self.operator1 = fe_op.linear_combination(2.0, mass, -self.timestep**2, stiffness) # Computing operator to apply on u2. self.operator2 = fe_op.clone(-1.0, mass) self.__add_boundary_contrib_operator2( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_operator2( self.config.right_boundary_condition, self.fe_space.get_right_idx()) # Computing rhs operator. if self.config.rhs is not None: self.rhs_operator = mass_assembler.assemble_mass( lambda x: 1.0, self.fe_space, self.mass_assembly_type) # Computing inv operator. self.inv_operator = fe_op.clone(1.0, mass) self.__add_boundary_contrib_inv_operator( self.config.left_boundary_condition, self.fe_space.get_left_idx()) self.__add_boundary_contrib_inv_operator( self.config.right_boundary_condition, self.fe_space.get_right_idx()) fe_op.inv(self.inv_operator) # Applying initial conditions. if self.init_cond_type is InitialConditionType.ORDERONE: for i, x in enumerate(self.fe_space.get_dof_coords()): self.u2[i] = self.config.init_field(x) self.u1[i] = self.timestep * self.config.init_velocity( x) + self.u2[i] elif self.init_cond_type is InitialConditionType.ORDERTWO: for i, x in enumerate(self.fe_space.get_dof_coords()): self.u2[i] = self.config.init_field(x) fe_op.mlt(stiffness, self.u2, self.ustar) fe_op.inv(mass) fe_op.mlt(mass, self.ustar, self.u1) for i, x in enumerate(self.fe_space.get_dof_coords()): self.u1[i] = self.timestep * self.config.init_velocity(x) + self.u2[i] \ - 0.5 * (self.timestep ** 2) * self.u1[i]
fig, ax = plt.subplots() ax.plot(*np.array(observer).T, label='observer values') ax.legend(loc='upper right') ax.set_xlabel('time') ax.set_title('observable (velocity at $x=L$)') # plt.show() # Step 2: perform Newton iterative descent # ======================================== propag_builder = partial(elastic_propagator.Elastic, fe_space=fe_space, mass_assembly_type=fe_op.AssemblyType.LUMPED, stiffness_assembly_type=fe_op.AssemblyType.ASSEMBLED) k = stiffness_assembler.assemble_stiffness(fe_space) minv = mass_assembler.assemble_mass(fe_space, density=alpha, assembly_type=fe_op.AssemblyType.LUMPED) fe_op.inv(minv) minv.data = scipy.sparse.dia_matrix((minv.data, [0]), shape=k.data.shape) minv_k = fe_op.make_from_data(minv.data * k.data, assembly_type=fe_op.AssemblyType.ASSEMBLED) current_theta = THETA_INIT convergence_reached = False step = 0 while not convergence_reached: dthetaJ = JREGUL * current_theta d2thetaJ = JREGUL