def _ydot_scratch(self, n_indent, of): # Assign scratch variables if self.use_cse: for si in self.ydot_out_scratch: siname = si[0] sivalue = self.fortranify( sympy.fcode(si[1], precision=15, source_format='free', standard=95)) of.write('{}{} = {}\n'.format(self.indent * n_indent, siname, sivalue))
def _ydot(self, n_indent, of): # Write YDOT for i, n in enumerate(self.unique_nuclei): sol_value = self.fortranify( sympy.fcode(self.ydot_out_result[i], precision=15, source_format='free', standard=95)) of.write('{}{}(j{}) = ( &\n'.format(self.indent * n_indent, self.name_ydot_nuc, n)) of.write("{}{} &\n".format(self.indent * (n_indent + 1), sol_value)) of.write("{} )\n\n".format(self.indent * n_indent))
def _set_axis_and_point(self, cond_eq: sympy.Equality, coords: cs.CoordinateSystem): coord_vars = coords.axises() self.axis, self.axis_point = None, None U = sympy.Function("u") u_entrances = list(cond_eq.find(U)) if len(u_entrances) != 1: raise ValueError( "Cannot contain different args in U for derivative and u function" ) a1 = sympy.Wild("a1", properties=[lambda x: x.is_constant]) a2 = sympy.Wild("a2", properties=[lambda x: x.is_constant]) u_pow = sympy.Wild("u_pow", properties=[lambda x: x.is_constant]) axis = sympy.Wild("axis", properties=[lambda x: x.is_symbol]) U_pattern = sympy.WildFunction("U_pattern", nargs=len(coords.axises())) res = cond_eq.lhs.match( a1 * U_pattern ** u_pow + a2 * sympy.Derivative(U_pattern, axis) ) if res is None: raise ValueError(f"Cannot parse {cond_eq}") self.a1 = res[a1] self.a2 = res[a2] u_with_args = res[U_pattern] if self.a1 != 0 and self.a2 == 0: self.kind = ConditionKind.First.name elif self.a1 == 0 and self.a2 != 0: self.kind = ConditionKind.Second.name elif self.a1 != 0 and self.a2 != 0: self.kind = ConditionKind.Third.name else: raise ValueError( f"Left side of boundary condition: {cond_eq} does" "not contain u function" ) for i, arg in enumerate(u_with_args.args): if arg.is_constant(): self.axis = coord_vars[i] self.axis_point = sympy.fcode(arg.evalf()) self._axis_point = arg break if self.axis is None: raise ValueError( "Bondary condition cannot be parsed" "Probably you did not specified U arguments or" "there is no constant in arguments" )
def _get_partial_pressure_code(self, str_list, str_trans): # Calculate flowrate of all gas species flowratecode = [] flowrate = 0 for species in self._species: if isinstance(species, _Fluid): flowrate += species.symbol fcode = sym.fcode(flowrate, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) flowratecode.append(f' flowrate = {fcode}') return flowratecode
def writeCode_Fortran95(self, outname): ## Write Fortran-95 Solver Subroutine try: fo = open(outname, 'w') except: raise indent = ' '*2 fo.write('module gauss_jordan_module\n') fo.write('{}implicit none\n'.format(indent)) fo.write('\n') fo.write('contains\n') fo.write('\n') fo.write('{}subroutine gauss_jordan_solve(A, x, b)\n'.format(indent)) fo.write('{}double precision, dimension({},{}), intent(in) :: A\n'.format( indent*2, self.nvars, self.nvars)) fo.write('{}double precision, dimension({}), intent(out) :: x\n'.format( indent*2, self.nvars)) fo.write('{}double precision, dimension({}), intent(in) :: b\n'.format( indent*2, self.nvars)) if self.cse_rep: for rep in self.cse_rep: fo.write('{}double precision :: {}\n'.format(indent*2, rep[0])) fo.write('\n') for rep in self.cse_rep: rep_value = self.fortranify(sympy.fcode(rep[1], precision = 15, source_format = 'free', standard = 95)) fo.write('{}{} = {}\n'.format(indent*2, rep[0], rep_value)) fo.write('\n') for i, sol in enumerate(self.solution): sol_value = self.fortranify(sympy.fcode(sol, precision = 15, source_format = 'free', standard = 95)) fo.write('{}x({}) = {}\n'.format(indent*2, i+1, sol_value)) fo.write('{}end subroutine gauss_jordan_solve\n'.format(indent)) fo.write('end module gauss_jordan_module\n') fo.close()
def _jacnuc(self, n_indent, of): # now make the JACOBIAN n_unique_nuclei = len(self.unique_nuclei) for jnj, nj in enumerate(self.unique_nuclei): for ini, ni in enumerate(self.unique_nuclei): jac_idx = n_unique_nuclei * jnj + ini jvalue = self.fortranify( sympy.fcode(self.jac_out_result[jac_idx], precision=15, source_format='free', standard=95)) of.write("{}{}(j{},j{}) = ( &\n".format( self.indent * n_indent, self.name_jacobian_nuc, nj, ni)) of.write("{}{} &\n".format(self.indent * (n_indent + 1), jvalue)) of.write("{} )\n\n".format(self.indent * n_indent))
def _jacnuc(self, n_indent, of): # now make the Jacobian n_unique_nuclei = len(self.unique_nuclei) for jnj, nj in enumerate(self.unique_nuclei): for ini, ni in enumerate(self.unique_nuclei): jac_idx = n_unique_nuclei*jnj + ini if not self.jac_null_entries[jac_idx]: jvalue = self.fortranify(sympy.fcode(self.jac_out_result[jac_idx], precision=15, source_format='free', standard=95)) of.write("{}scratch = (&\n".format(self.indent*(n_indent))) of.write("{}{} &\n".format(self.indent*(n_indent+1), jvalue)) of.write("{} )\n".format(self.indent*n_indent)) of.write("{}call set_jac_entry({}, j{}, j{}, scratch)\n\n".format( self.indent*n_indent, self.name_jacobian, nj, ni))
def expressionToCode(expression, language): '''Converts a SymPy Expression to a line of code in the target language''' if (language == "python"): return sympy.pycode(expression) elif (language == "javascript" or language == "typescript"): return sympy.jscode(expression) elif (language == "c"): return sympy.ccode(expression) elif (language == "cpp"): return sympy.cxxcode(expression) elif (language == "r"): return sympy.rcode(expression) elif (language == "fortran"): return sympy.fcode(expression) elif (language == "mathematica"): return sympy.mathematica_code(expression) elif (language == "matlab" or language == "octave"): return sympy.octave_code(expression) elif (language == "rust"): return sympy.rust_code(expression)
def camb_fortran(expr, name='camb_function', frame='CDM', expand=False): """ Convert symbolic expression to CAMB fortran code, using CAMB variable notation. This is not completely general, but it will handle conversion of Newtonian gauge variables like Psi_N, and most derivatives up to second order. :param expr: symbolic sympy expression using camb.symbolic variables and functions (plus any standard general functions that CAMB can convert to fortran). :param name: lhs variable string to assign result to :param frame: frame in which to interret non gauge-invariant expressions. By default uses CDM frame (synchronous gauge), as used natively by CAMB. :param expand: do a sympy expand before generating code :return: fortran code snippet """ camb_diff_vars = 'etakdot qgdot qrdot vbdot pigdot pirdot pinudot ' + \ 'octg octgdot polterdot polterddot diff_rhopi sigmadot phidot ' + \ 'ddvisibility dvisibility dopacity ddopacity' camb_arr_vars = 'Edot E' tau = _camb_cache.setdefault('tau', Symbol('tau')) etakdot, qgdot, qrdot, vbdot, pigdot, pirdot, pinudot, octg, octgdot, \ polterdot, polterddot, diff_rhopi, sigmadot, phidot, \ ddvisibility, dvisibility, dopacity, ddopacity = \ define_variables(camb_diff_vars, _camb_cache) Edot, E = \ sympy.symbols(camb_arr_vars, cls=sympy.IndexedBase, shape=(sympy.oo,)) # Keep everything except baryons pressure which is very small camb_diff_subs = [(diff(q_g, t), qgdot), (diff(pi_g, t), pigdot), (diff(pi_r, t), pirdot), (diff(q_r, t), qrdot), (diff(v_b, t), vbdot), (diff(visibility, t, t), ddvisibility), (diff(visibility, t), dvisibility), (diff(opacity, t, t), ddopacity), (diff(opacity, t), dopacity), (diff(J_3, t), octgdot), (diff(E_2, t), Edot[2]), (diff(E_3, t), Edot[3]), (diff(pi_nu, t), pinudot), (diff(eta, t), -2 * etakdot / k), (diff(Pi, t), diff_rhopi / kappa / a**2), (diff(polter, t, t), polterddot), (diff(polter, t), polterdot), (diff(sigma, t), sigmadot), (diff(phi, t), phidot), (diff(p_b, t), 0)] if frame != 'CDM': expr = make_frame_invariant(expr, frame) # substitute for variables not available in CAMB function expr = cdm_gauge( subs(Newt_vars + synchronous_vars + [hdot_sub, z_sub], expr)).doit().simplify() res = cdm_gauge( subs(background_eqs + total_eqs, expr).subs(camb_diff_subs)) if 'Derivative' in str(res): raise Exception( 'Unknown derivatives, generally can only handle up to second.\nRemaining derivatives: ' + str(res)) res = cdm_gauge(subs([K_sub, hdot_sub, z_sub], res)) camb_var_subs = [] for var in res.atoms(Function): camb_var = getattr(var, 'camb_var', None) if camb_var: if isinstance(camb_var, (list, tuple)): for x in camb_var: define_variable(x) camb_sub = getattr(var, 'camb_sub', None) if not camb_sub: raise Exception( 'must have camb_sub if camb_var has more than one variable' ) else: camb_var = define_variable(camb_var) camb_sub = getattr(var, 'camb_sub', None) or camb_var if camb_sub: if isinstance(camb_sub, six.string_types): camb_sub = eval(camb_sub) camb_var_subs.append((var, camb_sub)) camb_subs = camb_var_subs + [(p_b, 0), (E_2, E[2]), (E_3, E[3]), (J_3, octg), (K_fac, Kf[1])] res = res.subs(camb_subs).simplify() no_arg_funcs = [ f for f in res.atoms(Function) if f.args[0] == t and not f is f_K ] res = res.subs( zip(no_arg_funcs, [Symbol(str(x.func)) for x in no_arg_funcs])) res = res.subs(t, tau) if expand: res = res.expand() res = res.collect([ Symbol(str(x.func)) for x in [k, sigma, opacity, visibility, dopacity, dvisibility, ddvisibility] ]) res = sympy.fcode(res, source_format='free', standard=95, assign_to=name, contract=False) import textwrap if not 'if ' in res: lines = res.split('\n') for i, line in enumerate(lines): if '=' in line: res = '\n'.join(lines[i:]) break res = ''.join([x.strip() for x in res.split('&')]) res = ' &\n '.join(textwrap.wrap(res)) return res
def FORTRAN_jacobian(x, jac, parameters=[]): # TODO document # TODO remove this function if unused in paper NX = len(x) NP = len(parameters) Nrowpd = jac.shape[0] Ncolpd = jac.shape[1] if NX != Nrowpd != Ncolpd: raise Exception("System is not square!") _X = sy.tensor.IndexedBase("X", shape=(NX, )) X = [_X[i + 1] for i in xrange(NX)] X = X + [_X[NX + i + 1] for i in xrange(NP)] if type(jac) == sy.Matrix: jac = sy.Matrix(jac) jac_sub = jac.subs(zip(list(x) + list(parameters), X)) ijs = [i for i in it.product(xrange(Nrowpd), xrange(Ncolpd))] # generate FORTRAN code fstrs = [sy.fcode(jac_ij) for jac_ij in jac_sub] # remove whitespace and newlines fstrs = ["".join(jac_ij.split()) for jac_ij in fstrs] # remove all @ (FORTRAN line continuation indicator) fstrs = [jac_ij.replace("@", "") for jac_ij in fstrs] # find FORTRAN inline merge statements and replace with a hidden "switch" # variable whose value is set by a full IF statement at the start of the # function call. # -- this is needed because FORTRAN77 doesn't support inline merge statements Hstrs = [] # to hold hidden switch expressions for i in xrange(len(fstrs)): while fstrs[i].find("merge") != -1: H = "H(" + str(len(Hstrs) + 1) + ")" i_merge_start, i_merge_end, Hstr = parse_merge(H, fstrs[i]) fstrs[i] = fstrs[i][:i_merge_start] + H + fstrs[i][i_merge_end:] Hstrs.append(Hstr) NH = len(Hstrs) # format the fstrs wrapper = textwrap.TextWrapper(expand_tabs=True, replace_whitespace=True, initial_indent=" ", subsequent_indent=" @ ", width=60) for k in xrange(len(fstrs)): i, j = ijs[k] fstrs[k] = wrapper.fill("pd(" + str(i + 1) + "," + str(j + 1) + ")=" + fstrs[k]) + "\n" # put the above elements together into a FORTRAN subroutine hdr = " subroutine jac_f77(neq, t, X, ml, mu, pd, nrowpd) \n" +\ "Cf2py intent(hide) neq, ml, mu, nrowpd \n" +\ "Cf2py intent(out) pd \n" +\ " integer neq, ml, mu, nrowpd \n" +\ " double precision t, X, pd \n" +\ " dimension X(neq), pd(neq, neq) \n" if NH > 0: hdr += " real, dimension(" + str(NH) + ") :: H \n" H_block = "".join(Hstrs) pd_block = "".join(fstrs) fcode = hdr + H_block + pd_block + " return \n" + " end \n" return fcode
def _to_fcode(expr): return sympy.fcode(sympy.simplify(expr).evalf()).replace("\n", "").replace("@", "")
def sympy_to_muparser(expr): code = sympy.fcode(expr) code = code.replace('\n @', '') code = code.replace('**', '^') return code
def f90code(r, l): f90sym, f90fun, f90cod = fcode(r.evalf(6), l, source_format = 'free', \ standard = 2008, human = False) return f90cod
def main(argv): # Define arguments applicable to all commands from argparse import ArgumentParser, RawDescriptionHelpFormatter, SUPPRESS p = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) p.add_argument('-v', '--verbosity', action='count', help='increase verbosity; may be supplied repeatedly') p.add_argument('-n', '--newline', action='store_const', dest='statements', const=statements_by_newline, default=statements_by_semicolon, help='expect newline-delimited input with "#" comments;' ' otherwise semicolons delimit with "//" comments') p.add_argument('-d', '--decl', action='append', default=[], help='file containing SymPy-based declarations defaulting' ' to standard input when declarations required') # Control C vs Fortran vs SymPy (default) output for expressions g = p.add_mutually_exclusive_group() g.add_argument('-c', '--ccode', dest='style', default=str, help='output symbolic expressions as C code', action='store_const', const=lambda expr: sympy.ccode(expr, human=False)[2]) g.add_argument('-f', '--fcode', dest='style', default=SUPPRESS, help='output symbolic expressions as Fortran code', action='store_const', const=lambda expr: sympy.fcode(expr, source_format='free', human=False)[2]) # Control order of the approximation to any used expectations g = p.add_mutually_exclusive_group() g.add_argument('-1', dest='order', action='store_const', const=1, help='employ 1st order approximation to the expectation') g.add_argument('-2', dest='order', action='store_const', const=2, help='employ 2nd order approximation to the expectation') p.set_defaults(order=2) # Add command-specific subparsers sp = p.add_subparsers(title='subcommands, each possibly using declarations', metavar='') sp_chk = sp.add_parser('chk', help='run verification sanity checks', description='run verification sanity checks') sp_dec = sp.add_parser('dec', help='output known declarations', description='output known declarations') sp_lib = sp.add_parser('lib', help='list undefined symbols in declarations', description=prerequisites.__doc__, formatter_class=RawDescriptionHelpFormatter) sp_pre = sp.add_parser('pre', help='list prerequisites for E[f(x)], Var[f(x)]', description=prerequisites.__doc__, formatter_class=RawDescriptionHelpFormatter) sp_exp = sp.add_parser('exp', help='tabulate terms in E[f(x)]', description=expectation.__doc__, formatter_class=RawDescriptionHelpFormatter) sp_var = sp.add_parser('var', help='tabulate terms in Var[f(x)]', description=variance.__doc__, formatter_class=RawDescriptionHelpFormatter) # Some of the subparsers take one or more symbols to process f_help = 'quantities of interest; if empty, process all declarations' sp_dec.add_argument('f', nargs='*', help=f_help) sp_lib.add_argument('f', nargs='*', help=f_help) sp_pre.add_argument('f', nargs='*', help=f_help) sp_exp.add_argument('f', nargs='*', help=f_help) sp_var.add_argument('f', nargs='*', help=f_help) # Each command dispatches to one of the following methods sp_chk.set_defaults(command=command_chk) sp_dec.set_defaults(command=command_dec) sp_lib.set_defaults(command=command_lib) sp_pre.set_defaults(command=command_pre) sp_exp.set_defaults(command=command_exp) sp_var.set_defaults(command=command_var) # Parse the incoming command line args = p.parse_args() # Supply "all known declarations" behavior for any f arguments first # parsing any requested files into one unified dictionary "args.syms". # Additionally, provide nicer error messages on unknown symbols # (otherwise a messy stacktrace appears and folks doubt the code). if ('f' in args): args.syms = parser(args.statements(args.decl)) if not args.f: args.f = args.syms.keys() else: unknown = filter(lambda k: k not in args.syms, args.f) if unknown: raise LookupError("Requested but not in declarations: %s" % ', '.join(unknown)) # Dispatch to the chosen command retval = args.command(args) # Warn if the results are likely bogus due to an older SymPy version if ( distutils.version.LooseVersion(sympy.__version__) < distutils.version.LooseVersion('0.7.2') ): print('WARN: %s notes SymPy %s older than minimum 0.7.2' % (argv[0], sympy.__version__), file=sys.stderr) return retval
def camb_fortran(expr, name='camb_function', frame='CDM', expand=False): """ Convert symbolic expression to CAMB fortran code, using CAMB variable notation. This is not completely general, but it will handle conversion of Newtonian gauge variables like Psi_N, and most derivatives up to second order. :param expr: symbolic sympy expression using camb.symbolic variables and functions (plus any standard general functions that CAMB can convert to fortran). :param name: lhs variable string to assign result to :param frame: frame in which to interret non gauge-invariant expressions. By default uses CDM frame (synchronous gauge), as used natively by CAMB. :param expand: do a sympy expand before generating code :return: fortran code snippet """ camb_diff_vars = 'etakdot qgdot qrdot vbdot pigdot pirdot pinudot ' + \ 'octg octgdot polterdot polterddot diff_rhopi sigmadot phidot ' + \ 'ddvisibility dvisibility dopacity ddopacity' camb_arr_vars = 'Edot E' tau = _camb_cache.setdefault('tau', Symbol('tau')) etakdot, qgdot, qrdot, vbdot, pigdot, pirdot, pinudot, octg, octgdot, \ polterdot, polterddot, diff_rhopi, sigmadot, phidot, \ ddvisibility, dvisibility, dopacity, ddopacity = \ define_variables(camb_diff_vars, _camb_cache) Edot, E = \ sympy.symbols(camb_arr_vars, cls=sympy.IndexedBase, shape=(sympy.oo,)) # Keep everything except baryons pressure which is very small camb_diff_subs = [(diff(q_g, t), qgdot), (diff(pi_g, t), pigdot), (diff(pi_r, t), pirdot), (diff(q_r, t), qrdot), (diff(v_b, t), vbdot), (diff(visibility, t, t), ddvisibility), (diff(visibility, t), dvisibility), (diff(opacity, t, t), ddopacity), (diff(opacity, t), dopacity), (diff(J_3, t), octgdot), (diff(E_2, t), Edot[2]), (diff(E_3, t), Edot[3]), (diff(pi_nu, t), pinudot), (diff(eta, t), -2 * etakdot / k), (diff(Pi, t), diff_rhopi / kappa / a ** 2), (diff(polter, t, t), polterddot), (diff(polter, t), polterdot), (diff(sigma, t), sigmadot), (diff(phi, t), phidot), (diff(p_b, t), 0)] if frame != 'CDM': expr = make_frame_invariant(expr, frame) # substitute for variables not available in CAMB function expr = cdm_gauge(subs(Newt_vars + synchronous_vars + [hdot_sub, z_sub], expr)).doit().simplify() res = cdm_gauge(subs(background_eqs + total_eqs, expr).subs(camb_diff_subs)) if 'Derivative' in str(res): raise Exception( 'Unknown derivatives, generally can only handle up to second.\nRemaining derivatives: ' + str(res)) res = cdm_gauge(subs([K_sub, hdot_sub, z_sub], res)) camb_var_subs = [] for var in res.atoms(Function): camb_var = getattr(var, 'camb_var', None) if camb_var: if isinstance(camb_var, (list, tuple)): for x in camb_var: define_variable(x) camb_sub = getattr(var, 'camb_sub', None) if not camb_sub: raise Exception('must have camb_sub if camb_var has more than one variable') else: camb_var = define_variable(camb_var) camb_sub = getattr(var, 'camb_sub', None) or camb_var if camb_sub: if isinstance(camb_sub, six.string_types): camb_sub = eval(camb_sub) camb_var_subs.append((var, camb_sub)) camb_subs = camb_var_subs + [(p_b, 0), (E_2, E[2]), (E_3, E[3]), (J_3, octg), (K_fac, Kf[1])] res = res.subs(camb_subs).simplify() no_arg_funcs = [f for f in res.atoms(Function) if f.args[0] == t and not f is f_K] res = res.subs(zip(no_arg_funcs, [Symbol(str(x.func)) for x in no_arg_funcs])) res = res.subs(t, tau) if expand: res = res.expand() res = res.collect([Symbol(str(x.func)) for x in [k, sigma, opacity, visibility, dopacity, dvisibility, ddvisibility]]) res = sympy.fcode(res, source_format='free', standard=95, assign_to=name, contract=False) import textwrap if not 'if ' in res: lines = res.split('\n') for i, line in enumerate(lines): if '=' in line: res = '\n'.join(lines[i:]) break res = ''.join([x.strip() for x in res.split('&')]) res = ' &\n '.join(textwrap.wrap(res)) return res
def FORTRAN_f(x, f, parameters=[], verbose=False): """ Produce FORTRAN function for evaluating a vector-valued SymPy expression f given a state vector x. The FORTRAN function will have the signature f_f77(neq, t, X, Y) where neq is hidden and Y is an output matrix. """ # TODO remove code for dealing with stochastic systems -- it is not used in # this paper x = list(x) + list(parameters) f = list(f) + [0] * len(parameters) rv = list( set((np.concatenate([sy.stats.random_symbols(f_i) for f_i in f])))) NR = len(rv) if NR > 0: x += [sy.symbols("dt"), sy.symbols("seed")] f += [0, 0] NX = len(x) NY = len(f) if NX != NY: raise Exception("System is not square!") if verbose: print "generating FORTRAN matrices..." _X = sy.tensor.IndexedBase("X", shape=(NX, )) X = [_X[i + 1] for i in xrange(NX)] _R = sy.tensor.IndexedBase("R", shape=(NR, )) R = [_R[i + 1] for i in xrange(NR)] if type(f) != sy.Matrix: f = sy.Matrix(f) # WARNING : These substitution steps are VERY SLOW!!! It might be wise to # parallelise them in the future, or at least substitute into one dynamical # equation at a time so that progress can be monitored. if verbose: print "substituting matrix elements for original state variables and parameters (WARNING: SLOW)..." f_sub = f.subs(zip(x, X)) if verbose: print "substituting matrix elements for random variables (WARNING: SLOW)..." f_sub = f_sub.subs(zip(rv, R)) # generate FORTRAN code if verbose: print "generating FORTRAN code from dynamics equations..." fstrs = [sy.fcode(fi, standard=95) for fi in f_sub] # remove whitespace and newlines if verbose: print "removing whitespace and newlines..." fstrs = ["".join(fi.split()) for fi in fstrs] # remove all @ (FORTRAN line continuation indicator) if verbose: print "removing line continuations..." fstrs = [fi.replace("@", "") for fi in fstrs] # find FORTRAN inline merge statements and replace with a hidden "switch" # variable whose value is set by a full IF statement at the start of the # function call. # -- this is needed because FORTRAN77 doesn't support inline merge statements Hstrs = [] # to hold hidden switch expressions if verbose: print "formatting piecewise functions..." for i in xrange(len(fstrs)): while fstrs[i].find("merge") != -1: H = "H(" + str(len(Hstrs) + 1) + ")" i_merge_start, i_merge_end, Hstr = parse_merge(H, fstrs[i]) fstrs[i] = fstrs[i][:i_merge_start] + H + fstrs[i][i_merge_end:] Hstrs.append(Hstr) NH = len(Hstrs) # format the fstrs wrapper = textwrap.TextWrapper(expand_tabs=True, replace_whitespace=True, initial_indent=" ", subsequent_indent=" @ ", width=60) if verbose: print "formatting state equations..." for i in xrange(len(fstrs)): fstrs[i] = wrapper.fill("Y(" + str(i + 1) + ")=" + fstrs[i]) + "\n" # put the above elements together into a FORTRAN subroutine if verbose: print "formatting preamble..." hdr = " subroutine f_f77(neq, t, X, Y) \n" +\ "Cf2py intent(hide) neq \n" +\ "Cf2py intent(out) Y \n" +\ " integer neq \n" +\ " double precision t, X, Y \n" +\ " dimension X(neq), Y(neq) \n" if NH > 0: hdr += " real, dimension(" + str(NH) + ") :: H \n" # TODO fix the following -- assumes dt = 0.01 # NOTE this is only important when dealing with stochastic systems if NR > 0: hdr += " real, dimension(" + str(NR) + ") :: R \n" +\ " integer :: SEED \n" +\ " real :: RTRASH \n" +\ " SEED = INT((t/" + sy.fcode(X[-2]).strip() +\ ") + " + sy.fcode(X[-1]).strip() + ") \n" +\ " CALL SRAND(SEED) \n" +\ " DO i=1,4 \n" +\ " RTRASH=RAND(0) \n" +\ " END DO \n" R_block = "".join([sy.fcode(R_i) + "=RAND(0) \n" for R_i in R]) H_block = "".join(Hstrs) Y_block = "".join(fstrs) if verbose: print "assembling source code blocks..." fcode = hdr + R_block + H_block + Y_block + " return \n" + " end \n" # final formatting if verbose: print "final source code formatting..." wrapper = textwrap.TextWrapper(expand_tabs=True, replace_whitespace=True, initial_indent="", subsequent_indent=" @ ", width=60) fcode = "".join([wrapper.fill(src) + "\n" for src in fcode.split("\n")]) return fcode
def setup_execs(self): from micki.fortran2 import f90_template, pyf_template from numpy import f2py # y_vec is an array symbol that will represent the species # concentrations provided by the differential equation solver inside # the Fortran code (that is, y_vec is an INPUT to the functions that # calculate the residual, Jacobian, and rate) y_vec = sym.IndexedBase('y', shape=(self.nvariables, )) vac_vec = sym.IndexedBase('vac', shape=(len(self.vacancy), )) # Map y_vec elements (1-indexed, of course) onto 'modelparam' symbols trans = {self.symbols[i]: y_vec[i + 1] for i in range(self.nvariables)} trans.update( {vac.symbol: y_vec[i + 1] for i, vac in enumerate(self.vacancy)}) # Map string represntation of 'modelparam' symbols onto string # representation of y-vec elements str_trans = {} for i, symbol in enumerate(self.symbols): str_trans[sym.fcode(symbol, source_format='free')] = \ sym.fcode(y_vec[i + 1], source_format='free') for i, vac in enumerate(self.vacancy): str_trans[sym.fcode(vac.symbol, source_format='free')] = \ sym.fcode(vac_vec[i + 1], source_format='free') str_list = [key for key in str_trans] str_list.sort(key=len, reverse=True) # these will contain lists of strings, with each element being one # Fortran assignment for the master equation, Jacobian, and # rate expressions dypdrcode = [] drdycode = [] vaccode = [] drdvaccode = [] dvacdycode = [] for i, expr in enumerate(self.vac_sym): fcode = sym.fcode(expr, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) vaccode.append(' vac({}) = '.format(i + 1) + fcode) for i, row in enumerate(self.drdvac): for j, elem in enumerate(row): if elem != 0: fcode = sym.fcode(elem, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) drdvaccode.append( ' drdvac({}, {}) = '.format(i + 1, j + 1) + fcode) for i, row in enumerate(self.dvacdy): for j, elem in enumerate(row): if elem != 0: dvacdycode.append( ' dvacdy({}, {}) = '.format(i + 1, j + 1) + sym.fcode(elem, source_format='free')) for i, row in enumerate(self.dypdr): for j, elem in enumerate(row): if elem != 0: dypdrcode.append( ' dypdr({}, {}) = '.format(i + 1, j + 1) + sym.fcode(elem, source_format='free')) # Effectively the same as above, except on the two-dimensional Jacobian # matrix. for i, row in enumerate(self.drdy): for j, elem in enumerate(row): if elem != 0: fcode = sym.fcode(elem, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) drdycode.append(' drdy({}, {}) = '.format(i + 1, j + 1) + fcode) ratecode = self._get_rate_code(str_list, str_trans) #flowratecode = self._get_flowrate_code(str_list, str_trans) is_gas = [' isgas = 0'] for idx, species in enumerate(self._variable_species): if isinstance(species, _Fluid): is_gas.append(f' isgas({idx+1}) = 1') else: is_gas.append(f' isgas({idx+1}) = 0') # We insert all of the parameters of this differential equation into # the prewritten Fortran template, including the residual, Jacobian, # and rate expressions we just calculated. program = f90_template.format( neq=self.nvariables, nx=1, nrates=len(self.rates), nvac=len(self.vacancy), dypdrcalc='\n'.join(dypdrcode), drdycalc='\n'.join(drdycode), ratecalc='\n'.join(ratecode), vaccalc='\n'.join(vaccode), drdvaccalc='\n'.join(drdvaccode), dvacdycalc='\n'.join(dvacdycode), isgas='\n'.join(is_gas), ) # Generate a randomly-named temp directory for compiling the module. # We will name the actual module file after the directory. dname = tempfile.mkdtemp() modname = os.path.split(dname)[1] fname = modname + '.f90' pyfname = modname + '.pyf' # For debugging purposes, write out the generated module with open('solve_ida.f90', 'w') as f: f.write(program) # Write the pertinent data into the temp directory with open(os.path.join(dname, pyfname), 'w') as f: f.write( pyf_template.format(modname=modname, neq=self.nvariables, nrates=len(self.rates), nvac=len(self.vacancy))) # Compile the module with f2py lapack = "-lmkl_rt" if "MICKI_LAPACK" in os.environ: lapack = os.environ["MICKI_LAPACK"] os.environ["CFLAGS"] = "-w" f2py.compile(program, modulename=modname, extra_args='--quiet ' '--f90flags="-Wno-unused-dummy-argument ' '-Wno-unused-variable -Wno-unused-func -w" ' '-lsundials_fida ' '-lsundials_fnvecserial ' '-lsundials_ida ' '-lsundials_fsunlinsollapackdense ' '-lsundials_sunlinsollapackdense ' '-lsundials_nvecserial ' + lapack + ' ' + os.path.join(dname, pyfname), source_fn=os.path.join(dname, fname), verbose=0) # Delete the temporary directory shutil.rmtree(dname) # Import the module on-the-fly with __import__. This is kind of a hack. solve_ida = __import__(modname) self._solve_ida = solve_ida # The Fortran module's initialize, solve, and finalize routines # are mapped onto finitialize, fsolve, and ffinalize inside the Model # object. We don't want users touching these manually self.finitialize = solve_ida.initialize self.ffind_steady_state = solve_ida.find_steady_state self.fsolve = solve_ida.solve self.ffinalize = solve_ida.finalize # Delete the module file. We've already imported it, so it's in memory. modulefile = glob.glob(f'{modname}*.so')[0] os.remove(modulefile)
for i in range(3): eqstream.append(Eq(yvar[i], sympy_exp(logY[i].subs(f, ff(r))))) temp = Symbol('logR') r12, r23 = symbols('r12 r23', real=True, positive=True) f12, f23 = symbols('f12 f23', real=True, negative=False) # przejscie 1->2 eq = nsimplify(logY_all[1][0]) - 3 * nsimplify(logY_all[1][1]) - sympy_log( (2 * cgs_stef * cgs_mhydr) / (3 * cgs_boltz * cgs_c)) for x in solveset(eq.replace(sympy_log(r), temp), temp): eqstream.append(Eq(r12, sympy_exp(x.subs(f, ff(r12))))) # przejscie 2->3 eq = nsimplify( logY_all[1][0]) - Rational(7, 2) * nsimplify(logY_all[1][1]) - sympy_log( kappa_es / kappa_abs_0) for x in solveset(eq.replace(sympy_log(r), temp), temp): eqstream.append(Eq(r23, sympy_exp(x.subs(f, ff(r23))))) with open('3zones.f90', 'w') as f: for eq in eqstream: f.write( fcode(eq.rhs.evalf(6), eq.lhs, standard=2008, source_format='free', contract=False, user_functions={'f': 'f'}) + "\n")
if signu is 'fixed': ei.signu = '%f_wp' % (0.5 * proxy.std()) print(ei.signu) ei.nextra_para = 2 else: ei.signu = 'para(self%nA+self%nF+2)' ei.nextra_para = 2 x = sympy.symbols( ['para({:d})'.format(i + 1) for i in range(ei.nA + ei.nF)], positive=True) a0, aplus = ei.para_trans(x, dtype=object) mat_str = lambda *x: ' {}({}, {}) = {}'.format(*x) A0str = [ mat_str('A', i + 1, j + 1, sympy.fcode(value, source_format='free')) for (i, j), value in np.ndenumerate(a0) if value > 0 ] Apstr = [ mat_str('F', i + 1, j + 1, sympy.fcode(value, source_format='free')) for (i, j), value in np.ndenumerate(aplus) if value > 0 ] varfile = open('svar.f90', 'r').read() varfile = varfile.format(assign_para='\n'.join(A0str + Apstr), **vars(ei)) other_files = { 'data.txt': data['1993':'2007-06'][model['yy']].values, 'proxy.txt': proxy.values, 'priordraws.txt': priorsim[:args.nsim].T, 'phistar.txt': phihatT.flatten(order='F'),
def setup_execs(self): from micki.fortran import f90_template, pyf_template from numpy import f2py # y_vec is an array symbol that will represent the species # concentrations provided by the differential equation solver inside # the Fortran code (that is, y_vec is an INPUT to the functions that # calculate the residual, Jacobian, and rate) y_vec = sym.IndexedBase('yin', shape=(self.nvariables, )) # Map y_vec elements (1-indexed, of course) onto 'modelparam' symbols trans = {self.symbols[i]: y_vec[i + 1] for i in range(self.nvariables)} # Map string represntation of 'modelparam' symbols onto string # representation of y-vec elements str_trans = {} for i in range(self.nvariables): str_trans[sym.fcode(self.symbols[i], source_format='free')] = \ sym.fcode(y_vec[i + 1], source_format='free') str_list = [key for key in str_trans] str_list.sort(key=len, reverse=True) # these will contain lists of strings, with each element being one # Fortran assignment for the master equation, Jacobian, and # rate expressions rescode = [] jaccode = [] ratecode = [] # Convert symbolic master equation into a valid Fortran string for i in range(self.nvariables): fcode = sym.fcode(self.f_sym[i], source_format='free') # Replace modelparam symbols with their y_vec counterpart for key in str_list: fcode = fcode.replace(key, str_trans[key]) # Create actual line of code for calculating residual rescode.append(' res({}) = '.format(i + 1) + fcode) # Effectively the same as above, except on the two-dimensional Jacobian # matrix. for i in range(self.nvariables): for j in range(self.nvariables): expr = self.jac_sym[j, i] # Unlike the residual, some elements of the Jacobian can be 0. # We don't need to bother writing 'jac(x,y) = 0' a hundred # times in Fortran, so we omit those. if expr != 0: fcode = sym.fcode(expr, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) jaccode.append(' jac({}, {}) = '.format(j + 1, i + 1) + fcode) # See residual above for i, rate in enumerate(self.rates): fcode = sym.fcode(rate, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) ratecode.append(' rates({}) = '.format(i + 1) + fcode) # We insert all of the parameters of this differential equation into # the prewritten Fortran template, including the residual, Jacobian, # and rate expressions we just calculated. program = f90_template.format(neq=self.nvariables, nx=1, nrates=len(self.rates), rescalc='\n'.join(rescode), jaccalc='\n'.join(jaccode), ratecalc='\n'.join(ratecode)) # Generate a randomly-named temp directory for compiling the module. # We will name the actual module file after the directory. dname = tempfile.mkdtemp() modname = os.path.split(dname)[1] fname = modname + '.f90' pyfname = modname + '.pyf' # For debugging purposes, write out the generated module with open('solve_ida.f90', 'w') as f: f.write(program) # Write the pertinent data into the temp directory with open(os.path.join(dname, pyfname), 'w') as f: f.write( pyf_template.format(modname=modname, neq=self.nvariables, nrates=len(self.rates))) # Compile the module with f2py f2py.compile(program, modulename=modname, extra_args='--quiet ' '--f90flags="-Wno-unused-dummy-argument ' '-Wno-unused-variable -w -fopenmp" ' '-lsundials_fcvode ' '-lsundials_cvode -lsundials_fnvecopenmp ' '-lsundials_nvecopenmp -lopenblas_openmp -lgomp ' + os.path.join(dname, pyfname), source_fn=os.path.join(dname, fname), verbose=0) # Delete the temporary directory shutil.rmtree(dname) # Import the module on-the-fly with __import__. This is kind of a hack. solve_ida = __import__(modname) # The Fortran module's initialize, solve, and finalize routines # are mapped onto finitialize, fsolve, and ffinalize inside the Model # object. We don't want users touching these manually self.finitialize = solve_ida.initialize self.ffind_steady_state = solve_ida.find_steady_state self.fsolve = solve_ida.solve self.ffinalize = solve_ida.finalize # Delete the module file. We've already imported it, so it's in memory. os.remove(modname + '.so')
# + [markdown] {"slideshow": {"slide_type": "slide"}} # ## Code printers # The most basic form of code generation are the code printers. They convert SymPy expressions into over a dozen target languages. # # + {"slideshow": {"slide_type": "fragment"}} x = symbols('x') expr = abs(sin(x**2)) expr # + {"slideshow": {"slide_type": "fragment"}} sym.ccode(expr) # + {"slideshow": {"slide_type": "fragment"}} sym.fcode(expr, standard=2003, source_format='free') # + {"slideshow": {"slide_type": "fragment"}} from sympy.printing.cxxcode import cxxcode cxxcode(expr) # + {"slideshow": {"slide_type": "slide"}} sym.tanh(x).rewrite(sym.exp) # + {"slideshow": {"slide_type": "fragment"}} from sympy import sqrt, exp, pi expr = 1/sqrt(2*pi*sigma**2)* exp(-(x-mu)**2/(2*sigma**2)) print(sym.fcode(expr, standard=2003, source_format='free')) # + [markdown] {"slideshow": {"slide_type": "slide"}} # ## Creating a function from a symbolic expression
def dalton_functional_printer(kernel, routinename, input_variables, output_variables, shortrange=False, description=["No description.\n"], diff_order=[1], diff_idx=[[0]], output_files=[]): """ shortrange = True, if mu is an input parameter diff_order, is a list that indicatices how many of of each derivative that is present diff_order[0] = Energy, diff_order[1] = number of first derivatives diff_idx, is a list of lists that containts the idx of the given derivatives. """ if len(diff_order) != len(diff_idx): print("ERROR: order of derivatives does not match number of idx lists") for i in range(0, len(diff_order)): if diff_order[i] != len(diff_idx[i]): print( "ERROR: Number of " + i + "'th derivatives does not match lenght of corrosponding idx list" ) # Format kernel expression #kernel = kernel.evalf() # evalf is super slow! E_cse = cse(kernel, optimizations="basic") E_clean = [] E_clean_temp = [] for i in range(len(E_cse[0])): E_clean.append((E_cse[0][i][0], E_cse[0][i][1].evalf())) for i in range(len(E_cse[1])): E_clean_temp.append(E_cse[1][i].evalf()) E_clean = (E_clean, E_clean_temp) string_list = [] subroutine_input = ", ".join(input_variables) if shortrange == True: subroutine_input += ", mu" subroutine_input += ", " + ", ".join( output_variables[0:int(len(output_variables) / 4)]) string_list.append( "C*****************************************************************************\n" ) string_list.append("pure subroutine " + routinename + "(" + subroutine_input + ")\n") string_list.append( "C*****************************************************************************\n" ) for i in description: string_list.append("C " + i) string_list.append("C\nC Subroutine generated using Sympy " + str(sympy.__version__) + "\n") string_list.append("C Generated: " + datetime.datetime.now().strftime("%B %d, %Y") + "\n") string_list.append( "C*****************************************************************************\n" ) string_list.append("implicit none\n") string_list.append("real*8, intent(in) :: " + ", ".join(input_variables)) if shortrange == True: string_list[-1] += ", mu" string_list[-1] += "\n" string_list.append( "real*8, intent(out) :: " + ", ".join(output_variables[0:int(len(output_variables) / 4)]) + "\n") if "d1Ea" in output_variables: string_list[-1] = string_list[-1].replace("d1Ea", "d1Ea(4)") else: string_list[-1] = string_list[-1].replace("d1E", "d1E(9)") if "d2Ea" in output_variables: string_list[-1] = string_list[-1].replace("d2Ea", "d2Ea(10)") else: string_list[-1] = string_list[-1].replace("d2E", "d2E(45)") string_list.append( "real*8 :: PBE_value, PBE_alpha_value, PBE_beta_value\n") if len(E_clean[0]) > 0: string_list.append("real*8 :: ") for term in E_clean[0]: for letter in str( fcode(term[0], source_format="free").replace('&\n ', "")): string_list[-1] += letter if term != E_clean[0][-1]: string_list[-1] += ", " string_list[-1] += "\n" if len(diff_order) / 4 >= 1 and "Ea" in output_variables: string_list.append("Ea = 0.0d0\n") elif len(diff_order) / 4 >= 1: string_list.append("E = 0.0d0\n") if len(diff_order) / 4 >= 2 and "d1Ea" in output_variables: string_list.append("d1Ea(:) = 0.0d0\n") elif len(diff_order) / 4 >= 2: string_list.append("d1E(:) = 0.0d0\n") if len(diff_order) / 4 >= 3 and "d2Ea" in output_variables: string_list.append("d2Ea(:) = 0.0d0\n") elif len(diff_order) / 4 >= 3: string_list.append("d2E(:) = 0.0d0\n") for term in E_clean[0]: string_list.append(str(term[0]) + " = ") for letter in str( fcode(term[1], source_format="free").replace('&\n ', "").replace( "parameter (pi = 3.1415926535897932d0)\n", "")): string_list[-1] += letter string_list[-1] += "\n" output_counter = 0 diff_counter = 0 term_counter = 0 for term in E_clean[1]: if term_counter < 3: if term_counter == 0: string_list.append("PBE_value = ") elif term_counter == 2: string_list.append("PBE_alpha_value = ") elif term_counter == 1: string_list.append("PBE_beta_value = ") for letter in str( fcode(term, source_format="free").replace( '&\n ', "").replace("parameter (pi = 3.1415926535897932d0)\n", "")): string_list[-1] += letter string_list[-1] += "\n" term_counter += 1 else: # divide by four because of 4 different cases if len(diff_order) / 4 - len(diff_order) / 4 == diff_counter: string_list.append( "if ((PBE_alpha_value .ge. PBE_value) .and. (PBE_beta_value .ge. PBE_value)) then\n" ) elif len(diff_order) / 4 * 2 - len(diff_order) / 4 == diff_counter: string_list.append("end if\n") string_list.append( "if ((PBE_alpha_value .ge. PBE_value) .and. (PBE_beta_value .lt. PBE_value)) then\n" ) elif len(diff_order) / 4 * 3 - len(diff_order) / 4 == diff_counter: string_list.append("end if\n") string_list.append( "if ((PBE_alpha_value .lt. PBE_value) .and. (PBE_beta_value .ge. PBE_value)) then\n" ) elif len(diff_order) / 4 * 4 - len(diff_order) / 4 == diff_counter: string_list.append("end if\n") string_list.append( "if ((PBE_alpha_value .lt. PBE_value) .and. (PBE_beta_value .lt. PBE_value)) then\n" ) if diff_idx[diff_counter][output_counter] == 0: string_list.append(output_variables[0] + " = ") else: string_list.append( output_variables[diff_counter] + "(" + str(diff_idx[diff_counter][output_counter]) + ") = ") for letter in str( fcode(term, source_format="free").replace( '&\n ', "").replace("parameter (pi = 3.1415926535897932d0)\n", "")): string_list[-1] += letter string_list[-1] += "\n" output_counter += 1 if diff_order[diff_counter] == output_counter: output_counter = 0 diff_counter += 1 string_list.append("end if\n") string_list.append("end subroutine") for output_file in output_files: print_function(string_list, output_file)
def setup_execs(self): from micki.fortran import f90_template, pyf_template from numpy import f2py # y_vec is an array symbol that will represent the species # concentrations provided by the differential equation solver inside # the Fortran code (that is, y_vec is an INPUT to the functions that # calculate the residual, Jacobian, and rate) y_vec = sym.IndexedBase('yin', shape=(self.nvariables,)) # Map y_vec elements (1-indexed, of course) onto 'modelparam' symbols trans = {self.symbols[i]: y_vec[i + 1] for i in range(self.nvariables)} # Map string represntation of 'modelparam' symbols onto string # representation of y-vec elements str_trans = {} for i in range(self.nvariables): str_trans[sym.fcode(self.symbols[i], source_format='free')] = \ sym.fcode(y_vec[i + 1], source_format='free') str_list = [key for key in str_trans] str_list.sort(key=len, reverse=True) # these will contain lists of strings, with each element being one # Fortran assignment for the master equation, Jacobian, and # rate expressions rescode = [] jaccode = [] ratecode = [] # Convert symbolic master equation into a valid Fortran string for i in range(self.nvariables): fcode = sym.fcode(self.f_sym[i], source_format='free') # Replace modelparam symbols with their y_vec counterpart for key in str_list: fcode = fcode.replace(key, str_trans[key]) # Create actual line of code for calculating residual rescode.append(' res({}) = '.format(i + 1) + fcode) # Effectively the same as above, except on the two-dimensional Jacobian # matrix. for i in range(self.nvariables): for j in range(self.nvariables): expr = self.jac_sym[j, i] # Unlike the residual, some elements of the Jacobian can be 0. # We don't need to bother writing 'jac(x,y) = 0' a hundred # times in Fortran, so we omit those. if expr != 0: fcode = sym.fcode(expr, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) jaccode.append(' jac({}, {}) = '.format(j + 1, i + 1) + fcode) # See residual above for i, rate in enumerate(self.rates): fcode = sym.fcode(rate, source_format='free') for key in str_list: fcode = fcode.replace(key, str_trans[key]) ratecode.append(' rates({}) = '.format(i + 1) + fcode) # We insert all of the parameters of this differential equation into # the prewritten Fortran template, including the residual, Jacobian, # and rate expressions we just calculated. program = f90_template.format(neq=self.nvariables, nx=1, nrates=len(self.rates), rescalc='\n'.join(rescode), jaccalc='\n'.join(jaccode), ratecalc='\n'.join(ratecode)) # Generate a randomly-named temp directory for compiling the module. # We will name the actual module file after the directory. dname = tempfile.mkdtemp() modname = os.path.split(dname)[1] fname = modname + '.f90' pyfname = modname + '.pyf' # For debugging purposes, write out the generated module with open('solve_ida.f90', 'w') as f: f.write(program) # Write the pertinent data into the temp directory with open(os.path.join(dname, pyfname), 'w') as f: f.write(pyf_template.format(modname=modname, neq=self.nvariables, nrates=len(self.rates))) # Compile the module with f2py f2py.compile(program, modulename=modname, extra_args='--quiet ' '--f90flags="-Wno-unused-dummy-argument ' '-Wno-unused-variable -w -fopenmp" ' '-lsundials_fcvode ' '-lsundials_cvode -lsundials_fnvecopenmp ' '-lsundials_nvecopenmp -lopenblas_openmp -lgomp ' + os.path.join(dname, pyfname), source_fn=os.path.join(dname, fname), verbose=0) # Delete the temporary directory shutil.rmtree(dname) # Import the module on-the-fly with __import__. This is kind of a hack. solve_ida = __import__(modname) # The Fortran module's initialize, solve, and finalize routines # are mapped onto finitialize, fsolve, and ffinalize inside the Model # object. We don't want users touching these manually self.finitialize = solve_ida.initialize self.ffind_steady_state = solve_ida.find_steady_state self.fsolve = solve_ida.solve self.ffinalize = solve_ida.finalize # Delete the module file. We've already imported it, so it's in memory. os.remove(modname + '.so')
modules=_lambdify_modules) _ufns = {'argmax': 'argmax'} #pylint: disable=unnecessary-lambda _code_printers = { 'c': lambda expr, **kw: sp.ccode( expr, standard='c99', user_functions=_ufns, **kw), 'cxx': lambda expr, **kw: sp.cxxcode(expr, user_functions=_ufns, **kw), 'rust': lambda expr, **kw: sp.rust_code(expr, user_functions=_ufns, **kw), 'fortran': lambda expr, **kw: sp.fcode(expr, standard=95, user_functions=_ufns, **kw), 'js': lambda expr, **kw: sp.jscode(expr, user_functions=_ufns, **kw), 'r': lambda expr, **kw: sp.rcode(expr, user_functions=_ufns, **kw), 'julia': lambda expr, **kw: sp.julia_code(expr, user_functions=_ufns, **kw), 'mathematica': lambda expr, assign_to=None, **kw: sp.mathematica_code( expr, user_functions=_ufns, **kw), 'octave': lambda expr, **kw: sp.octave_code(expr, user_functions=_ufns, **kw), } def to_code(syexpr, dialect, assign_to='y', **kw):