Exemplo n.º 1
0
 def integrate(self):
     vector_over_time = list()
     N = self._function_over_time[0].N
     for function in self._function_over_time:
         assert function.N == N
         vector_over_time.append(function.vector())
     integrated_vector = simps(vector_over_time, dx=self._time_step_size, axis=0)
     integrated_function = Function(N)
     integrated_function.vector()[:] = integrated_vector
     return integrated_function
Exemplo n.º 2
0
class _ScipyImplicitEuler(object):
    def __init__(self, residual_eval, solution, solution_dot, bc_eval, jacobian_eval, set_time, problem_type):
        self.residual_eval = residual_eval
        self.solution = solution
        self.solution_dot = solution_dot
        self.solution_previous = Function(solution.vector().N) # equal to zero
        self.zero = Function(self.solution.vector().N) # equal to zero
        self.bc_eval = bc_eval
        self.jacobian_eval = jacobian_eval
        self.set_time = set_time
        self.problem_type = problem_type
        # Setup solver
        if problem_type == "linear":
            class _LinearSolver(LinearSolver):
                def __init__(self_, t):
                    self.set_time(t)
                    minus_solution_previous_over_dt = self.solution_previous
                    minus_solution_previous_over_dt.vector()[:] /= - self._time_step_size
                    lhs = self.jacobian_eval(t, self.zero, self.zero, 1./self._time_step_size)
                    rhs = - self.residual_eval(t, self.zero, minus_solution_previous_over_dt)
                    bcs_t = self.bc_eval(t)
                    LinearSolver.__init__(self_, lhs, self.solution, rhs, bcs_t)
                
            self.solver_generator = _LinearSolver
        elif problem_type == "nonlinear":
            class _NonlinearSolver(NonlinearSolver):
                def __init__(self_, t):
                    class _NonlinearProblemWrapper(NonlinearProblemWrapper):
                        def __init__(self_):
                            self.set_time(t)
                        def _store_solution_and_solution_dot(self_, solution):
                            self.solution.vector()[:] = solution.vector()
                            self.solution_dot.vector()[:] = (solution.vector() - self.solution_previous.vector())/self._time_step_size
                        def jacobian_eval(self_, solution):
                            self_._store_solution_and_solution_dot(solution)
                            return self.jacobian_eval(t, self.solution, self.solution_dot, 1./self._time_step_size)
                        def residual_eval(self_, solution):
                            self_._store_solution_and_solution_dot(solution)
                            return self.residual_eval(t, self.solution, self.solution_dot)
                        def bc_eval(self_):
                            return self.bc_eval(t)
                    NonlinearSolver.__init__(self_, _NonlinearProblemWrapper(), self.solution)
                
            self.solver_generator = _NonlinearSolver
        # Additional storage which will be setup by set_parameters
        self._final_time = None
        self._initial_time = 0.
        self._nonlinear_solver_parameters = None
        self._max_time_steps = None
        self._monitor = None
        self._report = None
        self._time_step_size = None
    
    def set_parameters(self, parameters):
        for (key, value) in parameters.items():
            if key == "final_time":
                self._final_time = value
            elif key == "initial_time":
                self._initial_time = value
            elif key == "integrator_type":
                assert value == "beuler"
            elif key == "max_time_steps":
                self._max_time_steps = value
            elif key == "monitor":
                self._monitor = value
            elif key == "nonlinear_solver":
                self._nonlinear_solver_parameters = value
            elif key == "problem_type":
                assert value == self.problem_type
            elif key == "report":
                if value is True:
                    def print_time(t):
                        print("# t = {0:g}".format(t))
                    self._report = print_time
                else:
                    self._report = None
            elif key == "time_step_size":
                self._time_step_size = value
            else:
                raise ValueError("Invalid paramater passed to _ScipyImplicitEuler object.")
                
    def solve(self):
        assert self._max_time_steps is not None or self._time_step_size is not None
        if self._time_step_size is not None:
            all_t = arange(self._initial_time, self._final_time + self._time_step_size, self._time_step_size)
        elif self._max_time_steps is not None:
            all_t = linspace(self._initial_time, self._final_time, num=self._max_time_steps+1)
            self._time_step_size = float(all_t[2] - all_t[1])
            
        all_solutions = list()
        all_solutions.append(function_copy(self.solution))
        all_solutions_dot = list()
        all_solutions_dot.append(function_copy(self.solution_dot))
        self.solution_previous.vector()[:] = self.solution.vector()
        for t in all_t[1:]:
            if self._report is not None:
                self._report(t)
            solver = self.solver_generator(t)
            if self.problem_type == "nonlinear":
                if self._nonlinear_solver_parameters is not None:
                    solver.set_parameters(self._nonlinear_solver_parameters)
            solver.solve()
            all_solutions.append(function_copy(self.solution))
            self.solution_dot.vector()[:] = (all_solutions[-1].vector() - all_solutions[-2].vector())/self._time_step_size
            all_solutions_dot.append(function_copy(self.solution_dot))
            self.solution_previous.vector()[:] = self.solution.vector()
            if self._monitor is not None:
                self._monitor(t, self.solution, self.solution_dot)
        
        return all_t, all_solutions, all_solutions_dot