def _generate_fun(self, funcname, reusestr, specnames, pardefines, vardefines, inpdefines, parundefines, varundefines, inpundefines, docodeinserts): sig = "void " + funcname + "(unsigned n_, unsigned np_, double t, double *Y_, " \ + \ "double *p_, double *f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_)" # specstr = sig + "{\n\n" + pardefines + vardefines + "\n" specstr = sig + "{" + pardefines + vardefines + inpundefines + "\n" if docodeinserts and self.opts['start']: specstr += self._format_user_code(self.opts['start']) + '\n' specstr += (len(reusestr) > 0) * "/* reused term definitions */\n" \ + reusestr + "\n" auxdefs_parsed = {} # add function body for i in range(len(specnames)): xname = specnames[i] fbody = self.fspec.varspecs[xname] fbody_parsed = self._processSpecialC(fbody) if self.fspec.auxfns: fbody_parsed = addArgToCalls(fbody_parsed, list(self.fspec.auxfns.keys()), "p_, wk_, xv_") if 'initcond' in self.fspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax fbody_parsed = wrapArgInCall(fbody_parsed, 'initcond', '"') specstr += "f_[" + str(i) + "] = " + fbody_parsed + ";\n" auxdefs_parsed[xname] = fbody_parsed if docodeinserts and self.opts['end']: specstr += '\n' + self._format_user_code(self.opts['end']) specstr += "\n" + parundefines + varundefines + inpundefines + "}\n\n" self.fspec._auxdefs_parsed = auxdefs_parsed return (specstr, funcname)
def test_combo_wrapArgInCall_and_addArgToCalls(): """Test combo of addArgToCalls and wrapArgInCall with embedded calls""" fs = "1/zeta(y_rel(y,initcond(y)+initcond(z)),z-initcond(x))+zeta(0.)" fs_p = addArgToCalls(fs, ['zeta', 'y_rel', 'initcond', 'nothing'], "p") assert '1/zeta(y_rel(y,initcond(y, p)+initcond(z, p), p),z-initcond(x, p), p)+zeta(0., p)' == fs_p assert '1/zeta(y_rel(y,initcond("y", p)+initcond("z", p), p),z-initcond("x", p), p)+zeta(0., p)' == wrapArgInCall(fs_p, 'initcond', '"')
def test_combo_wrapArgInCall_and_addArgToCalls(): """Test combo of addArgToCalls and wrapArgInCall with embedded calls""" fs = "1/zeta(y_rel(y,initcond(y)+initcond(z)),z-initcond(x))+zeta(0.)" fs_p = addArgToCalls(fs, ['zeta', 'y_rel', 'initcond', 'nothing'], "p") assert '1/zeta(y_rel(y,initcond(y, p)+initcond(z, p), p),z-initcond(x, p), p)+zeta(0., p)' == fs_p assert '1/zeta(y_rel(y,initcond("y", p)+initcond("z", p), p),z-initcond("x", p), p)+zeta(0., p)' == wrapArgInCall( fs_p, 'initcond', '"')
def makeAutoLibSource(self, include=[]): """makeAutoLibSource generates the C source for the vector field specification. It should be called only once per vector field.""" # Make vector field (and event) file for compilation assert isinstance(include, list), "includes must be in form of a list" # codes for library types (default is USERLIB, since compiler will look in standard library d STDLIB = 0 USERLIB = 1 libinclude = dict([('math.h', STDLIB), ('stdio.h', STDLIB), ('stdlib.h', STDLIB), ('string.h', STDLIB), ('autovfield.h', USERLIB), ('auto_c.h', USERLIB)]) include_str = '#include "auto_f2c.h"\n' # This must come first for libstr, libtype in libinclude.items(): if libtype == STDLIB: quoteleft = '<' quoteright = '>' else: quoteleft = '"' quoteright = '"' include_str += "#include " + quoteleft + libstr + quoteright + "\n" if include != []: assert isUniqueSeq(include), "list of library includes must not contain repeats" for libstr in include: if libstr in libinclude: # don't repeat libraries print("Warning: library '" + libstr + "' already appears in list"\ + " of imported libraries") else: include_str += "#include " + '"' + libstr + '"\n' # f2c auto conventions (dirty trick!) #define_str = "\n#define double doublereal\n#define int integer\n\n" define_str = "" allfilestr = "/* Vector field and other functions for Auto continuer.\n " \ + " This code was automatically generated by PyDSTool, but may be modified " \ + "by hand. */\n\n" + include_str + define_str + """ double *gICs; double **gBds; double globalt0; static double pi = 3.1415926535897931; """ pardefines = "" ## parundefines = "" vardefines = "" ## varundefines = "" inpdefines = "" ## inpundefines = "" # sorted version of var, par, and input names vnames = self.gensys._var_ixmap pnames = self.funcspec.pars inames = self.funcspec.inputs pnames.sort() inames.sort() for i in range(self.gensys.numpars): p = pnames[i] # add to defines (WATCH OUT FOR PERIOD _T!!!) if (i < 10): pardefines += self.funcspec._defstr+" "+p+"\tp_["+str(i)+"]\n" elif (i >= 10): pardefines += self.funcspec._defstr+" "+p+"\tp_["+str(i+40)+"]\n" # add period _T pardefines += self.funcspec._defstr+" _T\tp_[10]\n" for i in range(self.gensys.dimension): v = vnames[i] # add to defines vardefines += self.funcspec._defstr+" "+v+"\tY_["+str(i)+"]\n" ## # add to undefines ## varundefines += self.funcspec._undefstr+" "+v+"\n" for i in range(len(self.funcspec.inputs)): inp = inames[i] # add to defines inpdefines += self.funcspec._defstr+" "+inp+"\txv_["+str(i)+"]\n" ## # add to undefines ## inpundefines += self.funcspec._undefstr+" "+inp+"\n" allfilestr += "\n/* Variable, parameter, and input definitions: */ \n" \ + pardefines + vardefines + inpdefines + "\n" # add signature for auxiliary functions if self.funcspec.auxfns: allfilestr += "\n" for finfo in self.funcspec.auxfns.values(): allfilestr += finfo[1] + ";\n" allfilestr += "\nvoid auxvars(unsigned, unsigned, double, double*, double*, " \ + "double*, unsigned, double*, unsigned, double*);\n" \ + """void jacobian(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); void jacobianParam(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); """ if self.funcspec.auxvars == []: allfilestr += "int N_AUXVARS = 0;\n\n\n" else: allfilestr += "int N_AUXVARS = " + str(len(self.funcspec.auxvars)) \ + ";\n\n\n" allfilestr += self.funcspec.spec[0] + "\n\n" if self.funcspec.auxfns: for fname, finfo in self.funcspec.auxfns.items(): fbody = finfo[0] # subs _p into auxfn-to-auxfn calls (but not to the signature) fbody_parsed = addArgToCalls(fbody, list(self.funcspec.auxfns.keys()), "p_, wk_, xv_", notFirst=fname) if 'initcond' in self.funcspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax, but don't affect the # function signature! fbody_parsed = wrapArgInCall(fbody_parsed, 'initcond', '"', notFirst=True) allfilestr += "\n" + fbody_parsed + "\n\n" # add auxiliary variables (shell of the function always present) # add event functions allfilestr += self.funcspec.auxspec[0] # if jacobians or mass matrix not present, fill in dummy if not self.gensys.haveJacobian(): allfilestr += """ void jacobian(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if not self.gensys.haveJacobian_pars(): allfilestr += """ void jacobianParam(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ #+ "\n/* Variable and parameter substitutions undefined:*/\n" + parundefines + varundefines + "\n" # write out C file vffile = os.path.join(self._compilation_tempdir, self._vf_file) try: file = open(vffile, 'w') #allfilestr = allfilestr.replace("double ","doublereal ") #allfilestr = allfilestr.replace("double*","doublereal *") #allfilestr = allfilestr.replace("double**","doublereal **") file.write(allfilestr) file.close() except IOError as e: print("Error opening file "+self._vf_file+" for writing") raise IOError(e)
def addParToCall(s): return addArgToCalls( self._processSpecialC(s), list(self.fspec.auxfns.keys()), "p_, wk_, xv_", )
def generate_user_module(self, fspec, eventstruct, name="", include=None): include = include or [] # Make vector field (and event) file for compilation assert isinstance(include, list), "includes must be in form of a list" # codes for library types (default is USERLIB, since compiler will look in standard library d STDLIB = 0 USERLIB = 1 libinclude = [ ("math.h", STDLIB), ("Python.h", STDLIB), ("stdio.h", STDLIB), ("stdlib.h", STDLIB), ("string.h", STDLIB), ("events.h", USERLIB), ("maxmin.h", USERLIB), ("signum.h", USERLIB), ("vfield.h", USERLIB), ] include_str = "" for libstr, libtype in libinclude: if libtype == STDLIB: quoteleft = "<" quoteright = ">" else: quoteleft = '"' quoteright = '"' include_str += "#include " + quoteleft + libstr + quoteright + "\n" if include != []: incs = [libstr for libstr, _ in libinclude] assert isUniqueSeq( include ), "list of library includes must not contain repeats" for libstr in include: if libstr in incs: # don't repeat libraries print( "Warning: library '%s' already appears in list" % libstr + " of imported libraries" ) else: include_str += "#include " + '"' + libstr + '"\n' allfilestr = ( "/* Vector field function and events for %s integrator.\n" % name + " This code was automatically generated by PyDSTool, but may be modified " + "by hand. */\n\n" + include_str + """ extern double *gICs; extern double **gBds; extern double globalt0; static double pi = 3.1415926535897931; double signum(double x) { if (x<0) { return -1; } else if (x==0) { return 0; } else if (x>0) { return 1; } else { /* must be that x is Not-a-Number */ return x; } } """ ) pardefines = "" vardefines = "" auxvardefines = "" inpdefines = "" for i, p in enumerate(fspec.pars): pardefines += fspec._defstr + " " + p + "\tp_[" + str(i) + "]\n" for i, v in enumerate(fspec.vars): vardefines += fspec._defstr + " " + v + "\tY_[" + str(i) + "]\n" for i, v in enumerate(fspec.auxvars): auxvardefines += ( fspec._defstr + " " + v + "\t(" + fspec._auxdefs_parsed[v] + ")\n" ) for i, inp in enumerate(fspec.inputs): inpdefines += fspec._defstr + " " + inp + "\txv_[" + str(i) + "]\n" allfilestr += ( "\n/* Variable, aux variable, parameter, and input definitions: */ \n" + pardefines + vardefines + auxvardefines + inpdefines + "\n" ) # preprocess event code allevs = "" eventNames = eventstruct.sortedEventNames() numevs = len(eventNames) for evname in eventNames: ev = eventstruct.events[evname] evfullfn = "" from PyDSTool.Events import LowLevelEvent assert isinstance(ev, LowLevelEvent), ( "Radau can only " "accept low level events" ) evsig = ev._LLreturnstr + " " + ev.name + ev._LLargstr assert ev._LLfuncstr.index(";") > 1, ( "Event function code " "error: Have you included a ';' character at the end of" "your 'return' statement?" ) fbody = ev._LLfuncstr # check fbody for calls to user-defined aux fns # and add hidden p argument if fspec.auxfns: fbody_parsed = addArgToCalls( fbody, list(fspec.auxfns.keys()), "p_, wk_, xv_" ) if "initcond" in fspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax fbody_parsed = wrapArgInCall(fbody_parsed, "initcond", '"') else: fbody_parsed = fbody evbody = " {\n" + fbody_parsed + "\n}\n\n" allevs += evsig + evbody allfilestr += evsig + ";\n" # add signature for auxiliary functions if fspec.auxfns: allfilestr += "\n" for finfo in sorted(fspec.auxfns.values()): allfilestr += finfo[1] + ";\n" assignEvBody = "".join( ["events[%d] = &%s;\n" % (i, name) for i, name in enumerate(eventNames)] ) allfilestr += ( "\nint N_EVENTS = " + str(numevs) + ";\nvoid assignEvents(" + "EvFunType *events){\n " + assignEvBody + "\n}\n\nvoid auxvars(unsigned, unsigned, double, double*, double*, " + "double*, unsigned, double*, unsigned, double*);\n" + """void jacobian(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); void jacobianParam(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); """ ) allfilestr += "int N_AUXVARS = %d;\n\n\n" % len(fspec.auxvars) allfilestr += "int N_EXTINPUTS = %d;\n\n\n" % len(fspec.inputs) allfilestr += fspec.spec[0] + "\n\n" if fspec.auxfns: for fname, finfo in sortedDictItems(fspec.auxfns): fbody = finfo[0] # subs _p into auxfn-to-auxfn calls (but not to the signature) fbody_parsed = addArgToCalls( fbody, list(fspec.auxfns.keys()), "p_, wk_, xv_", notFirst=fname ) if "initcond" in fspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax, but don't affect the # function signature! fbody_parsed = wrapArgInCall( fbody_parsed, "initcond", '"', notFirst=True ) allfilestr += "\n" + fbody_parsed + "\n\n" # add auxiliary variables (shell of the function always present) # add event functions allfilestr += fspec.auxspec[0] + allevs # if jacobians or mass matrix not present, fill in dummy if "massMatrix" not in fspec.auxfns: allfilestr += """ void massMatrix(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if "Jacobian" not in fspec.auxfns: allfilestr += """ void jacobian(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if "Jacobian_pars" not in fspec.auxfns: allfilestr += """ void jacobianParam(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ return allfilestr
def makeAutoLibSource(self, include=[]): """makeAutoLibSource generates the C source for the vector field specification. It should be called only once per vector field.""" # Make vector field (and event) file for compilation assert isinstance(include, list), "includes must be in form of a list" # codes for library types (default is USERLIB, since compiler will look in standard library d STDLIB = 0 USERLIB = 1 libinclude = dict([('math.h', STDLIB), ('stdio.h', STDLIB), ('stdlib.h', STDLIB), ('string.h', STDLIB), ('autovfield.h', USERLIB), ('auto_c.h', USERLIB)]) include_str = '#include "auto_f2c.h"\n' # This must come first for libstr, libtype in libinclude.items(): if libtype == STDLIB: quoteleft = '<' quoteright = '>' else: quoteleft = '"' quoteright = '"' include_str += "#include " + quoteleft + libstr + quoteright + "\n" if include != []: assert isUniqueSeq( include), "list of library includes must not contain repeats" for libstr in include: if libstr in libinclude: # don't repeat libraries print("Warning: library '" + libstr + "' already appears in list"\ + " of imported libraries") else: include_str += "#include " + '"' + libstr + '"\n' # f2c auto conventions (dirty trick!) #define_str = "\n#define double doublereal\n#define int integer\n\n" define_str = "" allfilestr = "/* Vector field and other functions for Auto continuer.\n " \ + " This code was automatically generated by PyDSTool, but may be modified " \ + "by hand. */\n\n" + include_str + define_str + """ double *gICs; double **gBds; double globalt0; static double pi = 3.1415926535897931; """ pardefines = "" ## parundefines = "" vardefines = "" ## varundefines = "" inpdefines = "" ## inpundefines = "" # sorted version of var, par, and input names vnames = self.gensys._var_ixmap pnames = self.funcspec.pars inames = self.funcspec.inputs pnames.sort() inames.sort() for i in range(self.gensys.numpars): p = pnames[i] # add to defines (WATCH OUT FOR PERIOD _T!!!) if (i < 10): pardefines += self.funcspec._defstr + " " + p + "\tp_[" + str( i) + "]\n" elif (i >= 10): pardefines += self.funcspec._defstr + " " + p + "\tp_[" + str( i + 40) + "]\n" # add period _T pardefines += self.funcspec._defstr + " _T\tp_[10]\n" for i in range(self.gensys.dimension): v = vnames[i] # add to defines vardefines += self.funcspec._defstr + " " + v + "\tY_[" + str( i) + "]\n" ## # add to undefines ## varundefines += self.funcspec._undefstr+" "+v+"\n" for i in range(len(self.funcspec.inputs)): inp = inames[i] # add to defines inpdefines += self.funcspec._defstr + " " + inp + "\txv_[" + str( i) + "]\n" ## # add to undefines ## inpundefines += self.funcspec._undefstr+" "+inp+"\n" allfilestr += "\n/* Variable, parameter, and input definitions: */ \n" \ + pardefines + vardefines + inpdefines + "\n" # add signature for auxiliary functions if self.funcspec.auxfns: allfilestr += "\n" for finfo in self.funcspec.auxfns.values(): allfilestr += finfo[1] + ";\n" allfilestr += "\nvoid auxvars(unsigned, unsigned, double, double*, double*, " \ + "double*, unsigned, double*, unsigned, double*);\n" \ + """void jacobian(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); void jacobianParam(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); """ if self.funcspec.auxvars == []: allfilestr += "int N_AUXVARS = 0;\n\n\n" else: allfilestr += "int N_AUXVARS = " + str(len(self.funcspec.auxvars)) \ + ";\n\n\n" allfilestr += self.funcspec.spec[0] + "\n\n" if self.funcspec.auxfns: for fname, finfo in self.funcspec.auxfns.items(): fbody = finfo[0] # subs _p into auxfn-to-auxfn calls (but not to the signature) fbody_parsed = addArgToCalls(fbody, list(self.funcspec.auxfns.keys()), "p_, wk_, xv_", notFirst=fname) if 'initcond' in self.funcspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax, but don't affect the # function signature! fbody_parsed = wrapArgInCall(fbody_parsed, 'initcond', '"', notFirst=True) allfilestr += "\n" + fbody_parsed + "\n\n" # add auxiliary variables (shell of the function always present) # add event functions allfilestr += self.funcspec.auxspec[0] # if jacobians or mass matrix not present, fill in dummy if not self.gensys.haveJacobian(): allfilestr += """ void jacobian(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if not self.gensys.haveJacobian_pars(): allfilestr += """ void jacobianParam(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ #+ "\n/* Variable and parameter substitutions undefined:*/\n" + parundefines + varundefines + "\n" # write out C file vffile = os.path.join(self._compilation_tempdir, self._vf_file) try: file = open(vffile, 'w') #allfilestr = allfilestr.replace("double ","doublereal ") #allfilestr = allfilestr.replace("double*","doublereal *") #allfilestr = allfilestr.replace("double**","doublereal **") file.write(allfilestr) file.close() except IOError as e: print("Error opening file " + self._vf_file + " for writing") raise IOError(e)
def adjust_call(self): """Callable which adds parameter argument to auxiliary function calls (if any)""" if self.fspec.auxfns: return lambda s: addArgToCalls(s, self.fspec.auxfns.keys(), 'p_') return idfn
def adjust_call(self): """Callable which adds parameter argument to auxiliary function calls (if any)""" if self.fspec._auxfnspecs: return lambda s: addArgToCalls( s, list(self.fspec._auxfnspecs.keys()), 'p_') return idfn
def addParToCall(s): return addArgToCalls(self._processSpecialC(s), list(self.fspec.auxfns.keys()), "p_, wk_, xv_")
def generate_user_module(self, fspec, eventstruct, name='', include=None): include = include or [] # Make vector field (and event) file for compilation assert isinstance(include, list), "includes must be in form of a list" # codes for library types (default is USERLIB, since compiler will look in standard library d STDLIB = 0 USERLIB = 1 libinclude = [ ('math.h', STDLIB), ('Python.h', STDLIB), ('stdio.h', STDLIB), ('stdlib.h', STDLIB), ('string.h', STDLIB), ('events.h', USERLIB), ('maxmin.h', USERLIB), ('signum.h', USERLIB), ('vfield.h', USERLIB), ] include_str = '' for libstr, libtype in libinclude: if libtype == STDLIB: quoteleft = '<' quoteright = '>' else: quoteleft = '"' quoteright = '"' include_str += "#include " + quoteleft + libstr + quoteright + "\n" if include != []: incs = [libstr for libstr, _ in libinclude] assert isUniqueSeq(include), "list of library includes must not contain repeats" for libstr in include: if libstr in incs: # don't repeat libraries print("Warning: library '%s' already appears in list" % libstr\ + " of imported libraries") else: include_str += "#include " + '"' + libstr + '"\n' allfilestr = "/* Vector field function and events for %s integrator.\n" % name \ + " This code was automatically generated by PyDSTool, but may be modified " \ + "by hand. */\n\n" + include_str + """ extern double *gICs; extern double **gBds; extern double globalt0; static double pi = 3.1415926535897931; double signum(double x) { if (x<0) { return -1; } else if (x==0) { return 0; } else if (x>0) { return 1; } else { /* must be that x is Not-a-Number */ return x; } } """ pardefines = "" vardefines = "" auxvardefines = "" inpdefines = "" for i, p in enumerate(fspec.pars): pardefines += fspec._defstr + " " + p + "\tp_[" + str(i) + "]\n" for i, v in enumerate(fspec.vars): vardefines += fspec._defstr + " " + v + "\tY_[" + str(i) + "]\n" for i, v in enumerate(fspec.auxvars): auxvardefines += fspec._defstr+" "+v+"\t("+fspec._auxdefs_parsed[v]+")\n" for i, inp in enumerate(fspec.inputs): inpdefines += fspec._defstr + " " + inp + "\txv_[" + str(i) + "]\n" allfilestr += "\n/* Variable, aux variable, parameter, and input definitions: */ \n" \ + pardefines + vardefines + auxvardefines + inpdefines + "\n" # preprocess event code allevs = "" eventNames = eventstruct.sortedEventNames() numevs = len(eventNames) for evname in eventNames: ev = eventstruct.events[evname] evfullfn = "" from PyDSTool.Events import LowLevelEvent assert isinstance(ev, LowLevelEvent), ("Radau can only " "accept low level events") evsig = ev._LLreturnstr + " " + ev.name + ev._LLargstr assert ev._LLfuncstr.index(';') > 1, ("Event function code " "error: Have you included a ';' character at the end of" "your 'return' statement?") fbody = ev._LLfuncstr # check fbody for calls to user-defined aux fns # and add hidden p argument if fspec.auxfns: fbody_parsed = addArgToCalls(fbody, list(fspec.auxfns.keys()), "p_, wk_, xv_") if 'initcond' in fspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax fbody_parsed = wrapArgInCall(fbody_parsed, 'initcond', '"') else: fbody_parsed = fbody evbody = " {\n" + fbody_parsed + "\n}\n\n" allevs += evsig + evbody allfilestr += evsig + ";\n" # add signature for auxiliary functions if fspec.auxfns: allfilestr += "\n" for finfo in sorted(fspec.auxfns.values()): allfilestr += finfo[1] + ";\n" assignEvBody = ''.join([ "events[%d] = &%s;\n" % (i, name) for i, name in enumerate(eventNames) ]) allfilestr += "\nint N_EVENTS = " + str(numevs) + ";\nvoid assignEvents(" \ + "EvFunType *events){\n " + assignEvBody \ + "\n}\n\nvoid auxvars(unsigned, unsigned, double, double*, double*, " \ + "double*, unsigned, double*, unsigned, double*);\n" \ + """void jacobian(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); void jacobianParam(unsigned, unsigned, double, double*, double*, double**, unsigned, double*, unsigned, double*); """ allfilestr += "int N_AUXVARS = %d;\n\n\n" % len(fspec.auxvars) allfilestr += "int N_EXTINPUTS = %d;\n\n\n" % len(fspec.inputs) allfilestr += fspec.spec[0] + "\n\n" if fspec.auxfns: for fname, finfo in sortedDictItems(fspec.auxfns): fbody = finfo[0] # subs _p into auxfn-to-auxfn calls (but not to the signature) fbody_parsed = addArgToCalls(fbody, list(fspec.auxfns.keys()), "p_, wk_, xv_", notFirst=fname) if 'initcond' in fspec.auxfns: # convert 'initcond(x)' to 'initcond("x")' for # compatibility with C syntax, but don't affect the # function signature! fbody_parsed = wrapArgInCall(fbody_parsed, 'initcond', '"', notFirst=True) allfilestr += "\n" + fbody_parsed + "\n\n" # add auxiliary variables (shell of the function always present) # add event functions allfilestr += fspec.auxspec[0] + allevs # if jacobians or mass matrix not present, fill in dummy if 'massMatrix' not in fspec.auxfns: allfilestr += """ void massMatrix(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if 'Jacobian' not in fspec.auxfns: allfilestr += """ void jacobian(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ if 'Jacobian_pars' not in fspec.auxfns: allfilestr += """ void jacobianParam(unsigned n_, unsigned np_, double t, double *Y_, double *p_, double **f_, unsigned wkn_, double *wk_, unsigned xvn_, double *xv_) { } """ return allfilestr