def linear_solve(self): """ Solve Ax = b with numpy and also with removal of uneccesary rows using the spaces object """ timings.startnext("Numpy linear solve") info("Numpy Linear Solve") dofs = self.problem.spaces.usefuldofs #Original np array b = -self.F.array() #New np array b_np = b[dofs] #Solve the system x_np = np.linalg.solve(self.J_np, b_np) #map the solution back to the bigger space x = np.zeros(len(b)) x[dofs] = x_np ## #Create a Vector x_vec = Vector(len(x)) x_vec[:] = x ## self.inc.vector()[:] = x timings.stop("Numpy linear solve")
def linear_solve(self): """ Solve Ax = b with numpy and also with removal of uneccesary rows using the spaces object """ timings.startnext("Numpy linear solve") info("Numpy Linear Solve") dofs = self.problem.spaces.usefuldofs #Original np array b = -self.F.array() #New np array b_np = b[dofs] #Solve the system x_np = np.linalg.solve(self.J_np,b_np) #map the solution back to the bigger space x = np.zeros(len(b)) x[dofs] = x_np ## #Create a Vector x_vec = Vector(len(x)) x_vec[:] = x ## self.inc.vector()[:] = x timings.stop("Numpy linear solve")
def build_jacobian(self): """Assemble Jacobian""" info("Assembling Jacobian") #If buffered matrix add the variable part to the buffered part. if self.problem.J_buff is not None: timings.startnext("Copy Buffered Jacobian") self.J = self.problem.J_buff.copy() timings.startnext("Jacobian Assembly") self.J = assemble(self.problem.j, tensor = self.J, cell_domains = self.problem.cell_domains, interior_facet_domains = self.problem.interior_facet_domains, exterior_facet_domains = self.problem.exterior_facet_domains, reset_sparsity = False, add_values = True, form_compiler_parameters = self.ffc_opt) timings.stop("Jacobian Assembly") else: #No buffering just assemble timings.startnext("Jacobian Assembly") self.J = assemble(self.problem.j, tensor = self.J, cell_domains = self.problem.cell_domains, interior_facet_domains = self.problem.interior_facet_domains, exterior_facet_domains = self.problem.exterior_facet_domains, form_compiler_parameters = self.ffc_opt) timings.stop("Jacobian Assembly") #Give the Jacobian it's BC. self.apply_ident_bc() #Create an LU Solver # Create linear solver and factorize matrix self.linsolver = LUSolver(self.J) self.linsolver.parameters["reuse_factorization"] = True
def build_residual(self): """Assemble Residual""" timings.startnext("Residual assembly") info("Residual Assembly") self.F = assemble(self.problem.f, tensor = self.F, cell_domains = self.problem.cell_domains, interior_facet_domains = self.problem.interior_facet_domains, exterior_facet_domains = self.problem.exterior_facet_domains) [bc.apply(self.F) for bc in self.problem.bc] timings.stop("Residual assembly")
def assemble_J_buff(self): """Assembles the buffered jacobian""" info("Assembling Buffered Jacobian") timings.startnext("Buffered Jacobian assembly") J_buff = assemble(self.j_buff, cell_domains = self.problem.meshfunctions["cell"], interior_facet_domains = self.problem.meshfunctions["interiorfacet"], exterior_facet_domains = self.problem.meshfunctions["exteriorfacet"] ) timings.stop("Buffered Jacobian assembly") return J_buff
def assemble_J_buff(self): """Assembles the buffered jacobian""" info("Assembling Buffered Jacobian") timings.startnext("Buffered Jacobian assembly") J_buff = assemble(self.j_buff, cell_domains = self.problem.cellfunc, interior_facet_domains = self.problem.fsiboundfunc, exterior_facet_domains = self.problem.extboundfunc) timings.stop("Buffered Jacobian assembly") return J_buff
def build_residual(self): """Assemble Residual""" timings.startnext("Residual assembly") info("Residual Assembly") self.F = assemble( self.problem.f, tensor=self.F, cell_domains=self.problem.cell_domains, interior_facet_domains=self.problem.interior_facet_domains, exterior_facet_domains=self.problem.exterior_facet_domains) [bc.apply(self.F) for bc in self.problem.bc] timings.stop("Residual assembly")
def __init__(self,problem,params = fsinewton_params): timings.startnext("Fsi Newton Solver init") info_blue("Initializing FSI Newton Solver") info("Using params \n" + str(params) ) #Initialize base class ccom.CBCSolver.__init__(self) self.problem = problem self.params = params #Define the various helper objects of the fsinewton solver self.spaces = FSISpaces(problem,params) self.fsibc = FSIBC(problem,self.spaces) #Define mixed Functions self.U0 = self.__initial_state() self.U1 = Function(self.spaces.fsispace) #Define Subfunction references to the mixed functions (self.U1_F,self.P1_F,self.L1_U,self.D1_S,self.U1_S,self.D1_F,self.L1_D) = self.U1.split() (self.U0_F,self.P0_F,self.L0_U,self.D0_S,self.U0_S,self.D0_F,self.L0_D) = self.U0.split() #Define list tensor references to the mixed funtions self.U1list = self.spaces.unpack_function(self.U1) self.U0list = self.spaces.unpack_function(self.U0) #Define Mixed Trial and Test Functions self.IU = TrialFunctions(self.spaces.fsispace) self.V = TestFunctions(self.spaces.fsispace) #Define time relevant variables self.dt = self.problem.initial_step() self.kn = Constant(self.dt) self.t = 0.0 #Define Time Descretized Functions self.Umid,self.Udot = self.time_discreteU(self.U1list,self.U0list,self.kn) self.IUmid,self.IUdot = self.time_discreteI(self.IU,self.kn) #Initialize any Body forces if present self.__init_forces() #Define Forms and buffered part of the jacobian matrix. self.r,self.j,self.j_buff = self.create_forms() self.runtimedata = FsiRunTimeData(self) timings.stop("Fsi Newton Solver init")
def build_jacobian(self): """Assemble Jacobian""" info("Assembling Jacobian") #If buffered matrix add the variable part to the buffered part. if self.problem.J_buff is not None: timings.startnext("Copy Buffered Jacobian") self.J = self.problem.J_buff.copy() timings.startnext("Jacobian Assembly") self.J = assemble( self.problem.j, tensor=self.J, cell_domains=self.problem.cell_domains, interior_facet_domains=self.problem.interior_facet_domains, exterior_facet_domains=self.problem.exterior_facet_domains, reset_sparsity=False, add_values=True, form_compiler_parameters=self.ffc_opt) timings.stop("Jacobian Assembly") else: #No buffering just assemble timings.startnext("Jacobian Assembly") self.J = assemble( self.problem.j, tensor=self.J, cell_domains=self.problem.cell_domains, interior_facet_domains=self.problem.interior_facet_domains, exterior_facet_domains=self.problem.exterior_facet_domains, form_compiler_parameters=self.ffc_opt) timings.stop("Jacobian Assembly") #Give the Jacobian it's BC. self.apply_ident_bc() #Create an LU Solver # Create linear solver and factorize matrix self.linsolver = LUSolver(self.J) self.linsolver.parameters["reuse_factorization"] = True
def linear_solve(self): """Dolfin/PETSc linear solve""" timings.startnext("PETSc linear solve") info("PETSc Linear Solve") self.linsolver.solve(self.inc.vector(),-self.F) timings.stop("PETSc linear solve")
def linear_solve(self): """Dolfin/PETSc linear solve""" timings.startnext("PETSc linear solve") info("PETSc Linear Solve") self.linsolver.solve(self.inc.vector(), -self.F) timings.stop("PETSc linear solve")
def solve_primal(self, problem, parameters): "Solve primal FSI problem" #def __init__() # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] uniform_timestep = parameters["uniform_timestep"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Update of user problem at t = 0 (important for initial conditions) problem.update(0.0, 0.0, dt) # Define the three subproblems F = FluidProblem(problem, solver_type=parameters["fluid_solver"]) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) info("FSI problem has %d dofs (%d + %d + %d)" % \ (num_dofs_FSM, F.num_dofs, S.num_dofs, M.num_dofs)) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Get reference value of goal functional if hasattr(problem, "reference_value"): reference_value = problem.reference_value() else: reference_value = None if parameters["primal_solver"] == "Newton": #If no initial_step function try to generate one if not hasattr(problem, "initial_step"): problem.initial_step = lambda: parameters["initial_timestep"] # Initialize an FSINewtonSolver Object fsinewtonsolver = FSINewtonSolver(problem,\ params = parameters["FSINewtonSolver"].to_dict()) #initialize the solve settings fsinewtonsolver.prepare_solve() #def solve_primal() while True: # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Update of user problem problem.update(t0, t1, dt) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) if parameters["primal_solver"] == "Newton": #Newtonsolver has it's own timings assert save_solution, "Parameter save_solution must be true to use the Newton Solver" U_S1, U_S0, P_S1, increment, numiter = newton_solve( F, S, M, U_S0, dt, parameters, itertol, problem, fsinewtonsolver) elif parameters["primal_solver"] == "fixpoint": timings.startnext("FixpointSolve") U_S0, U_S1, P_S1, increment, numiter = fixpoint_solve( F, S, U_S0, M, dt, t1, parameters, itertol, problem) timings.stop("FixpointSolve") else: raise Exception( "Only 'fixpoint' and 'Newton' are possible values \ for the parameter 'primal_solver'") self.g_numiter = numiter ##################################################### #The primal solve worked so now go to post processing ##################################################### #def postprocessing(): # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S0, U_M1) if problem.exact_solution() is not None: update_exactsol(u_F1, p_F1, U_S1, U_M1, F, problem, t1) info("") info_green( "Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, numiter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, numiter + 1, parameters) # Evaluate user goal functional goal_functional = assemble( problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt #End of Time loop #Call post processing for the Newton Solver if necessary. if parameters["primal_solver"] == "Newton": fsinewtonsolver.post_processing() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, reference_value, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution info(timings.report_str()) return (goal_functional, integrated_goal_functional)
def solve_primal(self,problem, parameters): "Solve primal FSI problem" #def __init__() # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] uniform_timestep = parameters["uniform_timestep"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Update of user problem at t = 0 (important for initial conditions) problem.update(0.0, 0.0, dt) # Define the three subproblems F = FluidProblem(problem, solver_type=parameters["fluid_solver"]) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) info("FSI problem has %d dofs (%d + %d + %d)" % \ (num_dofs_FSM, F.num_dofs, S.num_dofs, M.num_dofs)) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Get reference value of goal functional if hasattr(problem, "reference_value"): reference_value = problem.reference_value() else: reference_value = None if parameters["primal_solver"] == "Newton": #If no initial_step function try to generate one if not hasattr(problem,"initial_step"): problem.initial_step = lambda :parameters["initial_timestep"] # Initialize an FSINewtonSolver Object fsinewtonsolver = FSINewtonSolver(problem,\ params = parameters["FSINewtonSolver"].to_dict()) #initialize the solve settings fsinewtonsolver.prepare_solve() #def solve_primal() while True: # Display progress info("") info("-"*80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Update of user problem problem.update(t0, t1, dt) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) if parameters["primal_solver"] == "Newton": #Newtonsolver has it's own timings assert save_solution,"Parameter save_solution must be true to use the Newton Solver" U_S1,U_S0,P_S1,increment,numiter = newton_solve(F,S,M,U_S0,dt,parameters,itertol,problem,fsinewtonsolver) elif parameters["primal_solver"] == "fixpoint": timings.startnext("FixpointSolve") U_S0,U_S1,P_S1,increment,numiter = fixpoint_solve(F,S,U_S0,M,dt,t1,parameters,itertol,problem) timings.stop("FixpointSolve") else: raise Exception("Only 'fixpoint' and 'Newton' are possible values \ for the parameter 'primal_solver'") self.g_numiter = numiter ##################################################### #The primal solve worked so now go to post processing ##################################################### #def postprocessing(): # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S0, U_M1) if problem.exact_solution() is not None: update_exactsol(u_F1,p_F1,U_S1,U_M1,F,problem,t1) info("") info_green("Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, numiter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, numiter + 1, parameters) # Evaluate user goal functional goal_functional = assemble(problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt #End of Time loop #Call post processing for the Newton Solver if necessary. if parameters["primal_solver"] == "Newton": fsinewtonsolver.post_processing() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, reference_value, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution info(timings.report_str()) return (goal_functional, integrated_goal_functional)