def _calc_optimal_C0(self, solution, start, end): ret_val = C0 anal_sol = -1 / x if C0 in solution.free_symbols: integrand = self._subs_solution(solution) # integrand = solution - anal_sol integrand *= integrand # integrand = integrand.subs({C0: -0.11077}) squared_residual = integrate(integrand, (x, start, end)) # print("total error is ", squared_residual) # assert False det_eq = squared_residual.diff(C0) print('squared res is ') print(det_eq) ans = solveset(det_eq, C0, domain=S.Reals) print("C0 opt vals are: ", ans) ISR_l = lambdify(C0, squared_residual) # print('min error is ', ISR_l(-0.0633790771568749)) # print('min error is ', ISR_l(-0.313647060539033)) # print('min error is ', ISR_l(-0.177974008726031)) assert False pass else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_val
def set_eq(self, expr): # TODO add an exception here to catch SympifyError in order to handle it. inc_expr = ham_sympify(expr) if not check_eq_algebr_valid(inc_expr): ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__BAD_ALGEBRAIC_EQUATION') else: self.eq = inc_expr
def parse_bcs(self, t_bcs_obj): for bcs_dict in t_bcs_obj: if 2 == len(bcs_dict): a_new_bcs = self._parse_a_bcs(bcs_dict) if a_new_bcs.is_well_defined(): self.bcs.append(a_new_bcs) else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED')
def check_type(self): if TaskType.ALGEBRAIC_EQ_TASK == self.bvp_type: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') elif TaskType.ODE_TASK == self.bvp_type: self._check_ODE_bc() elif TaskType.PDE_TASK == self.bvp_type or TaskType.STEFAN_TASK == self.bvp_type: self._check_PDE_bc() return
def calc_solution(self, n): # TODO should return tuple (value, bool=sympy_solved) ans = None if n >= 0: self._calc_terms(n) ans = sum(self.homotopy_terms) else: ham_error('HAM_ERROR_HANDLED', 'HANDLED__GENERAL') return ans, True
def calc_solution(self, n): ans = None if n >= 0: self._calc_terms(n) print("Homotopy terms analytically: ", self.homotopy_terms) # TODO here return the answer only by adding n terms and not all stored ans = sum(self.homotopy_terms) else: ham_error('HAM_ERROR_HANDLED', 'HANDLED_REQUEST_FOR_NEGATIVE_APPROXIMATIONS_NUMBER') return ans
def ask_for_output_filename(): output_filename = input( "pyHAM: provide path for output file or leave blank:\n") if not is_valid_output_filename(output_filename): ham_error('HAM_ERROR_HANDLED', 'HANDLED__INVALID_OUTPUT_FILENAME_TERMINAL') output_filename = generate_current_filename() print("Results will be written to file: " + os.getcwd() + output_filename) return output_filename
def _calc_terms(self, n): prev_num = len(self.deform_eqs) if prev_num != len(self.homotopy_terms): ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') if n > prev_num - 1: self._build_f_vals(n) temp_lex = self._build_temp_lexicon(n) d_times = n - prev_num + 1 for i in range(d_times): self._populate(temp_lex)
def ask_for_input_filename(): ret_str = None complain = False while not is_valid_filename(ret_str): if complain: ham_error('HAM_ERROR_HANDLED', 'HANDLED__INVALID_INPUT_FILENAME_TERMINAL') ret_str = input("pyHAM: provide a valid path for the input file:\n") complain = True return ret_str
def calc(self, solution, bcs): ans = 0. # TODO if C0 from parse -> calc optimal C0 else just produce error lambdify_holds = True self._domain_def(bcs) point = self.domain_start # optimal_C0 = -1. # sol_to_use = solution.subs({C0: optimal_C0}) sol_to_use = solution # sol_to_use = solution.subs({p1: 1.}) # self.deq = self.deq.subs({p1: 1.}) # optimal_C0 = self._calc_optimal_C0(sol_to_use, self.domain_start, self.domain_end) # print('optimal C0 is ', optimal_C0) # print('sol to use:') # print(sol_to_use) # return S(0) if self.step: step_to_use = self.step else: step_to_use = (self.domain_end - self.domain_start) / (self.points + 1) # print('sol to use: ', sol_to_use) expr_to_eval = simplify(self._subs_solution(sol_to_use)) # print('expr eval: ', expr_to_eval) # anal_sol = p1*x**2*(3*p3**2 - 5*p3*x + 2*x**2)/(48*p2) # anal_sol = anal_sol.subs({p3: 1.}) # expr_to_eval = simplify(sol_to_use - anal_sol) expr_eval_l = lambdify(x, expr_to_eval, modules=['math', 'sympy']) # print('expr to eval') while point <= self.domain_end and lambdify_holds: try: curr_error = expr_eval_l(point) ans += curr_error * curr_error point += step_to_use except TypeError: print('lambdify failed') assert False lambdify_holds = False if lambdify_holds: ans = simplify(ans) else: ans = self._calc_with_subs(sol_to_use, bcs) if x in ans.free_symbols: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') # print('error ') # print(ans) # ans /= self.points # opt = ans.diff(C0) # opt_ans = solveset(opt, C0, domain=S.Reals) # print('opt C0 is ', opt_ans) # l_opt = lambdify(C0, ans) # print('opt error is ', l_opt(-0.5)) # print('opt error2 is ', l_opt(-0.319094219626965)) # print('opt error3 is ', l_opt(-0.15812531498891)) return ans
def calc_solution(self, n): # TODO should return tuple (value, sympy_solved) ans = None if n >= 0: self._calc_terms(n) print("Homotopy terms analytically: ", self.homotopy_terms) # TODO return only n terms and not all sum ans = sum(self.homotopy_terms) else: ham_error('HAM_ERROR_HANDLED', "HANDLED_REQUEST_FOR_NEGATIVE_APPROXIMATIONS_NUMBER") return ans, True
def solve_kernel(self): if TaskType.ALGEBRAIC_EQ_TASK == self.task_type: solve_kernel_algebraic(self) elif TaskType.ODE_TASK == self.task_type: solve_kernel_ODE(self) elif TaskType.PDE_TASK == self.task_type: solve_kernel_PDE(self) elif TaskType.STEFAN_TASK == self.task_type: solve_kernel_Stefan(self) else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED')
def __init__(self, task_type): if task_type == 'HAM_TASK': ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__VIRTUAL_METHOD_CALLED') else: super().__init__(task_type) self.eq = None self.parsing_status = False self.initial_guesses = [] self.c0_vals = [] self.approximations = [] self.to_solve = True self.solutions = []
def _plot(self): if self.status: if PlotType.PLOT == self.plt_type: self._plot_plot() elif PlotType.CONTOUR_PLOT == self.plt_type: self._plot_cplot() elif PlotType.ANIMATED_PLOT == self.plt_type: self._plot_ani_plot() elif PlotType.ANIMATED_CONTOUR_PLOT == self.plt_type: self._plot_ani_cplot() else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED')
def do_the_plot(self, u_fun, points, parametric=None, style=None): if ham_not_none(parametric): ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__NOT_IMPLEMENTED_YET') if ham_not_none(style): self.style = style self._reset() self._set_fun(u_fun) self._set_points(points) self._set_parametric(parametric) self._preliminary_checks() self._build_data() self._plot()
def p_list(self, symb_in): symb_out = [] for symb in symb_in: if x == symb: symb_out.append(self.x) elif y == symb: symb_out.append(self.y) elif t == symb: symb_out.append(self.t) else: ham_error('HAM_ERROR_HANDLED', 'HANDLED__SOFT_ASSERT') return symb_out
def vars_by_plot_type(plot_type): ret_vars = None if plot_type == PlotType.PLOT: ret_vars = [x] elif plot_type == PlotType.CONTOUR_PLOT: ret_vars = [x, y] elif plot_type == PlotType.ANIMATED_PLOT: ret_vars = [x, t] elif plot_type == PlotType.ANIMATED_CONTOUR_PLOT: ret_vars = [x, y, t] else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_vars
def _calc_replacement(self, der): d_metrics = der.variable_count x_times = 0 q_times = 0 for var_count in d_metrics: if var_count[0] == x: x_times = var_count[1] elif var_count[0] == q: q_times = var_count[1] replacer = factorial(q_times)*self.homotopy_terms[q_times] replacer = replacer.diff(x, x_times) if q in replacer.atoms(Symbol): ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return replacer
def _preliminary_checks(self): self.plt_type = decide_plot_type(self.points) if self.plt_type != PlotType.UNAVAILABLE: vars_in = vars_by_plot_type(self.plt_type) vars_in_expr = self.fun.atoms(Symbol) bad_gen = (var for var in vars_in_expr if var not in vars_in) for var in bad_gen: self.status = False ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') break else: # TODO : bad request for plot. Mention back self.status = False ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED')
def _check_if_sufficient_bcs(self): ans = False lin_op_orders = orders_of_pde(self.lin_op) the_sum = 0 if lin_op_orders[0] > 0: the_sum += lin_op_orders[0] if lin_op_orders[1] > 0: the_sum += lin_op_orders[1] if lin_op_orders[2] > 0: the_sum += lin_op_orders[2] if the_sum > 0: ans = the_sum == len(self.bcs) else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ans
def _symbol_str(self): ret_val = None if self.bvp_type == TaskType.ODE_TASK: ret_val = str(ODE_F_EXPRESSIONS[self.fx_order]) elif self.bvp_type == TaskType.PDE_TASK: symb_list = [ 'u', 'x', str(self.fx_order), 'y', str(self.fy_order), 't', str(self.ft_order) ] ret_val = ''.join(symb_list) else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_val
def try_clear_expr(expr): ret_expr = expr uneval_integrals = expr.atoms(Integral) if uneval_integrals and len(uneval_integrals) > 0: times = 0 unevals = len(uneval_integrals) while unevals > 0 and times < 10: ret_expr = ret_expr.doit() uneval_integrals = ret_expr.atoms(Integral) unevals = len(uneval_integrals) times += 1 if times >= 10: ret_expr = expr ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_expr
def parse_bcs(self, t_bcs_obj): for bcs_dict in t_bcs_obj: if 2 == len(bcs_dict): a_new_bcs = BoundaryCondition(TaskType.ODE_TASK) for key, val in bcs_dict.items(): if 'x' == key: a_new_bcs.x = ham_sympify(val) else: key_s = ham_sympify(key) val_s = ham_sympify(val) a_new_bcs.set_f_der_val(key_s, val_s) a_new_bcs.check_type() self.bcs.append(a_new_bcs) else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED')
def build_task_type(self, inp_dict): ret_task = None t_type = inp_dict.get('type') if t_type: if 'algebraic' == t_type: ret_task = HamTaskAlgebraic() elif 'ODE' == t_type: ret_task = HamTaskODE() elif 'PDE' == t_type: ret_task = HamTaskPDE() elif 'Stefan' == t_type: ret_task = HamTaskStefan else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_task
def __str__(self): ret_str = '' if self.bvp_type == TaskType.ODE_TASK: ret_str = '( x: ' + str(self.x) + ', ' ret_str += self._symbol_str() + ': ' + str(self.value) + ')\n' elif self.bvp_type == TaskType.PDE_TASK: ret_str += '( ' if self.x is not None: ret_str += 'x: ' + str(self.x) + ', ' if self.y is not None: ret_str += 'y: ' + str(self.y) + ', ' if self.t is not None: ret_str += 't: ' + str(self.t) + ', ' ret_str += self._symbol_str() + ': ' + str(self.value) + ')\n' else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_str
def _compute_ani_data(self, ani_data_in): if PlotType.ANIMATED_PLOT == self.plt_type: the_vars = [x] else: the_vars = [x, y] curr_time = ani_data_in[0].time fun_to_use = simplify(self.fun.subs({t: curr_time})) u_l = lambdify(the_vars, fun_to_use, modules=['math', 'sympy']) x_vals = [] u_vals = [] if PlotType.ANIMATED_PLOT == self.plt_type: for t_data in ani_data_in: # type: TimeData x_vals.append(t_data.data[0]) u_vals.append(u_l(t_data.data[0])) x_vals_to_ret = np.array(x_vals) u_vals_to_ret = np.array(u_vals) ret_val = (x_vals_to_ret, u_vals_to_ret) else: # TODO fill when ready for contour plots ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ret_val
def calc(self, solution, bcs): error_value = -1. if ham_not_none(self.domain): ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__NOT_IMPLEMENTED_YET') elif len(self.eval_points) > 0: error_value = 0. the_vars = self._consistent_points() if ham_not_none(the_vars): expr_to_eval = self._subs_solution(solution) expr_eval_l = lambdify(the_vars, expr_to_eval, modules=['math', 'sympy']) if len(self.eval_points) > 0: for pnt in self.eval_points: # type: HamPoint get_back_vars = pnt.p_list(the_vars) error_value += expr_eval_l(get_back_vars[0], get_back_vars[1], get_back_vars[2]) error_value /= len(self.eval_points) else: error_value = 'N/A' else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return error_value
def satisfied_by(self, expr): ans = False if self.explicit: subs_lexicon = {} the_symbols = self.value.atoms(Symbol) gen = (var for var in the_symbols if var in PDE_U_EXPRESSIONS) for u_fun in gen: x_ord, y_ord, t_ord = decode_der_orders_pde(u_fun) expr_to_use = expr.diff(x, x_ord) expr_to_use = expr_to_use.diff(y, y_ord) expr_to_use = expr_to_use.diff(t, t_ord) subs_lexicon[u_fun] = simplify(expr_to_use) gen = (var for var in the_symbols if var in MOVING_BOUNDARY_EXP) for r_fun in gen: indx = MOVING_BOUNDARY_EXP.index(r_fun) subs_lexicon[r_fun] = expr.diff(t, indx) subs_lexicon[self.explicit_symbol] = self.boundary outcome = simplify(self.value.subs(subs_lexicon)) print('outcome is ', outcome) ans = outcome == S(0) or float(outcome) < 1e-10 else: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') return ans
def _calc_integration_constants(self, solution): ret_expr = solution lin_eqs = [] constants = self._produce_integr_constants_list() for curr_bcs in self.bcs: # type: hamTask.BoundaryCondition a_new_lin_eq = solution.diff(x, curr_bcs.fx_order) a_new_lin_eq = a_new_lin_eq.subs({x: curr_bcs.x}) lin_eqs.append(a_new_lin_eq) assert len(constants) == len(lin_eqs) try: ans = linsolve(lin_eqs, constants) except ValueError: ham_error('HAM_ERROR_CRITICAL', 'CRITICAL__ASSERT_NOT_REACHED') ans = nonlinsolve(lin_eqs, constants) if isinstance(ans, FiniteSet): vals_lex = {} ans = (list(ans))[0] for i in range(len(ans)): vals_lex[constants[i]] = ans[i] ret_expr = solution.subs(vals_lex) elif isinstance(ans, EmptySet): self.sympy_solved = False return ret_expr
def _populate(self, fvals_lexicon): last_deform_eq = self.deform_eqs[-1] print('last deform eq is ', last_deform_eq) ldeq_diffed = simplify(last_deform_eq.diff(q)) print('diffed: ', ldeq_diffed) self.deform_eqs.append(ldeq_diffed) ldeq_subs_homotopies = ldeq_diffed.xreplace(ALG_LEXICON) print('homotopies after xreplace: ', ldeq_subs_homotopies) ldeq_subs_homotopies = ldeq_subs_homotopies.xreplace(ALG_LEXICON_SECOND) print("after secondary xrepl: ", ldeq_subs_homotopies) ldeq_subs_homotopies = ldeq_subs_homotopies.xreplace(ALG_LEXICON_THIRD) print("after third xrepl: ", ldeq_subs_homotopies) var_to_solve_for = XTERMS_LIST[len(self.deform_eqs) - 1] print('var to solve for: ', var_to_solve_for) next_term = solve(ldeq_subs_homotopies, var_to_solve_for) print("next term is ", next_term) temp_lex = fvals_lexicon.copy() self._enrich_dict_with_x_vals(temp_lex) if next_term and len(next_term) == 1: next_term_calced = next_term[0].subs(temp_lex) else: ham_error('HAM_ERROR_HANDLED', 'HANDLED_GENERAL') next_term_calced = sympify(0.) self.homotopy_terms.append(next_term_calced)