# A time vector, noting 1600sps is used. tt = np.linspace(0, 32*10/1600, 32*10, endpoint=False) # A phase comparison vector. This should be the idea output. pt = np.concatenate((((2*np.pi*50.0*tt+np.pi) % (2*np.pi) - np.pi),(2*np.pi*ft*tt+np.pi) % (2*np.pi) - np.pi)) # The test input vector yt = np.concatenate((mag*np.cos(2*np.pi*50*tt) + dc_offset, mag*np.cos(2*np.pi*ft*tt) + dc_offset)) # Re-define tt to extend the full length. tt = np.linspace(0, 2*32*10/1600, 2*32*10, endpoint=False) step_time = (32*10)/1600 # used for drawing a line of the plots # Create and run the filter, noting increasing the number of iterations # will reduce the LES filter settling time at the cost of higher computation time. les = LES(iterations=1) les_out = les.run_les(yt) # Visualisation of the output fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex=True, sharey=False) fig.suptitle('LES Freq Step Test', fontsize=16) # Plots have the LES generated lines wider so the correct lines is overlayed and visable. # Plot the phases ax1.plot(tt, les_out[1], linewidth=3) ax1.plot(tt, pt) ax1.set_title('Phase (rad)') ax1.axvline(x=step_time, ls='--', c='red') # Plot the freqency
def solve(self, annotate=True): ''' Solve the shallow water equations ''' ############################### Setting up the equations ########################### # Initialise solver settings if not type(self.problem) == SWProblem: raise TypeError("Do not know how to solve problem of type %s." % type(self.problem)) # Get parameters problem_params = self.problem.parameters solver_params = self.parameters farm = problem_params.tidal_farm if farm: turbine_friction = farm.friction_function # Performance settings parameters['form_compiler']['quadrature_degree'] = \ solver_params.quadrature_degree parameters['form_compiler']['cpp_optimize_flags'] = \ " ".join(solver_params.cpp_flags) parameters['form_compiler']['cpp_optimize'] = True parameters['form_compiler']['optimize'] = True # Get domain measures ds = problem_params.domain.ds dx = problem_params.domain.dx # Get the boundary normal direction n = FacetNormal(self.mesh) # Get temporal settings theta = Constant(problem_params.theta) dt = Constant(problem_params.dt) finish_time = Constant(problem_params.finish_time) t = Constant(problem_params.start_time) # Get equation settings g = problem_params.g h = problem_params.depth nu = problem_params.viscosity include_advection = problem_params.include_advection include_viscosity = problem_params.include_viscosity linear_divergence = problem_params.linear_divergence f_u = problem_params.f_u include_les = solver_params.les_model # Get boundary conditions bcs = problem_params.bcs # Get function spaces V, Q = self.V, self.Q dgu = "Discontinuous" in str(V) # Test and trial functions v = TestFunction(V) u = TrialFunction(V) q = TestFunction(Q) eta = TrialFunction(Q) # Functions u00 = Function(V) u0 = Function(V, name="u0") ut = Function(V) # Tentative velocity u1 = Function(V, name="u") eta0 = Function(Q, name="eta0") eta1 = Function(Q, name="eta") # Large eddy model if include_les: les_V = FunctionSpace(problem_params.domain.mesh, "CG", 1) les = LES(les_V, u0, solver_params.les_parameters['smagorinsky_coefficient']) eddy_viscosity = les.eddy_viscosity nu += eddy_viscosity else: eddy_viscosity = None # Define the water depth if linear_divergence: H = h else: H = eta0 + h if f_u is None: f_u = Constant((0, 0)) # Bottom friction friction = problem_params.friction if farm: friction += Function(turbine_friction, name="turbine_friction", annotate=annotate) # Load initial conditions # Projection is necessary to obtain 2nd order convergence # FIXME: The problem should specify the ic for each component separately. u_ic = project(problem_params.initial_condition_u, self.V) u0.assign(u_ic, annotate=False) u00.assign(u_ic, annotate=False) eta_ic = project(problem_params.initial_condition_eta, self.Q) eta0.assign(eta_ic, annotate=False) eta1.assign(eta_ic, annotate=False) # Tentative velocity step u_mean = theta * u + (1. - theta) * u0 u_bash = 3. / 2 * u0 - 1. / 2 * u00 u_diff = u - u0 norm_u0 = inner(u0, u0)**0.5 F_u_tent = ((1 / dt) * inner(v, u_diff) * dx() + inner(v, grad(u_bash) * u_mean) * dx() + g * inner(v, grad(eta0)) * dx() + friction / H * norm_u0 * inner(u_mean, v) * dx - inner(v, f_u) * dx()) # Viscosity term if dgu: # Taken from http://maths.dur.ac.uk/~dma0mpj/summer_school/IPHO.pdf sigma = 1. # Penalty parameter. # Set tau=-1 for SIPG, tau=0 for IIPG, and tau=1 for NIPG tau = 0. edgelen = FacetArea(self.mesh)('+') # Facetarea is continuous, so # we can select either side alpha = sigma / edgelen F_u_tent += nu * inner(grad(v), grad(u_mean)) * dx() for d in range(2): F_u_tent += -nu * inner(avg(grad(u_mean[d])), jump(v[d], n)) * dS F_u_tent += -nu * tau * inner(avg(grad(v[d])), jump(u[d], n)) * dS F_u_tent += alpha * nu * inner(jump(u[d], n), jump(v[d], n)) * dS else: F_u_tent += nu * inner(grad(v), grad(u_mean)) * dx() a_u_tent = lhs(F_u_tent) L_u_tent = rhs(F_u_tent) # Pressure correction eta_diff = eta - eta0 ut_mean = theta * ut + (1. - theta) * u0 F_p_corr = (q * eta_diff + g * dt**2 * theta**2 * H * inner(grad(q), grad(eta_diff))) * dx() + dt * q * div( H * ut_mean) * dx() a_p_corr = lhs(F_p_corr) L_p_corr = rhs(F_p_corr) # Velocity correction eta_diff = eta1 - eta0 a_u_corr = inner(v, u) * dx() L_u_corr = inner(v, ut) * dx() - dt * g * theta * inner( v, grad(eta_diff)) * dx() bcu, bceta = self._generate_strong_bcs(dgu) # Assemble matrices A_u_corr = assemble(a_u_corr) for bc in bcu: bc.apply(A_u_corr) a_u_corr_solver = LUSolver(A_u_corr) a_u_corr_solver.parameters["reuse_factorization"] = True if linear_divergence: A_p_corr = assemble(a_p_corr) for bc in bceta: bc.apply(A_p_corr) a_p_corr_solver = LUSolver(A_p_corr) a_p_corr_solver.parameters["reuse_factorization"] = True yield ({ "time": t, "u": u0, "eta": eta0, "eddy_viscosity": eddy_viscosity, "is_final": self._finished(t, finish_time) }) log(INFO, "Start of time loop") adjointer.time.start(t) timestep = 0 # De/activate annotation annotate_orig = parameters["adjoint"]["stop_annotating"] parameters["adjoint"]["stop_annotating"] = not annotate while not self._finished(t, finish_time): # Update timestep timestep += 1 t = Constant(t + dt) # Update bc's t_theta = Constant(t - (1.0 - theta) * dt) bcs.update_time(t, only_type=["strong_dirichlet"]) bcs.update_time(t_theta, exclude_type=["strong_dirichlet"]) # Update source term if f_u is not None: f_u.t = Constant(t_theta) if include_les: log(PROGRESS, "Compute eddy viscosity.") les.solve() # Compute tentative velocity step log(PROGRESS, "Solve for tentative velocity.") A_u_tent = assemble(a_u_tent) b = assemble(L_u_tent) for bc in bcu: bc.apply(A_u_tent, b) solve(A_u_tent, ut.vector(), b) # Pressure correction log(PROGRESS, "Solve for pressure correction.") b = assemble(L_p_corr) for bc in bceta: bc.apply(b) if linear_divergence: a_p_corr_solver.solve(eta1.vector(), b) else: A_p_corr = assemble(a_p_corr) for bc in bceta: bc.apply(A_p_corr) solve(A_p_corr, eta1.vector(), b) # Velocity correction log(PROGRESS, "Solve for velocity update.") b = assemble(L_u_corr) for bc in bcu: bc.apply(b) a_u_corr_solver.solve(u1.vector(), b) # Rotate functions for next timestep u00.assign(u0) u0.assign(u1) eta0.assign(eta1) # Increase the adjoint timestep adj_inc_timestep(time=float(t), finished=self._finished(t, finish_time)) yield ({ "time": t, "u": u0, "eta": eta0, "eddy_viscosity": eddy_viscosity, "is_final": self._finished(t, finish_time) }) # Reset annotation flag parameters["adjoint"]["stop_annotating"] = annotate_orig log(INFO, "End of time loop.")