ó UÎ7Tc@s½y(ddlZddlZeje_WnMy2ddlZddlZeje_dGHdGHWqxdGHdGHqxXnXyddlTdGHWnQyddlTdGHWqßd GHd GHd GHd GHd GHdGHdGHddlTqßXnXdd$d„ƒYZddlm Z ddd„Z d„Z d„Z ddlZddd„Zdd%d„ƒYZd„Zdd&d„ƒYZdd'd„ƒYZdd(d„ƒYZd d)d!„ƒYZd"d*d#„ƒYZdS(+iÿÿÿÿNs&numpy not found. Using Numeric insteads=Everything should still work, but consider upgrading to numpys Neither numpy nor Numeric found.s,Please install numpy (preferred) or Numeric.(t*sUsing MatPlotLib graphicssUsing Ngl graphicss sGraphics not implemented.s&Plot routines will not produce graphs.s*Instead, you can save results from a Curves2object c into a text file using c.dump()s1and then plot the data using the graphics programsof your choice.tCurvecBsbeZd„Zddd„Zd„Zd„Zd„Zd„Zd„Zdd „Z d „Z RS( cCs‹d|_i|_i|_i|_g|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_dS(Nit(tNonetXidtdatatlabeltscattertidListt NumCurvest descriptiont PlotTitletswitchXYtreverseXtreverseYtXlogAxistYlogAxistXlabeltYlabel(tself((sClimateUtilities.pyt__init__ps              RcCsµ|jd7_t|ƒdkr5d|jd}nt|ƒtgƒkr_tj|ƒ}n||j|<|jdkr‡||_n|jj |ƒ||j |RR-Rtindex( tbufftinHeadert delimitert startDataLinet endDataLineR2tlineR5tistarttvarlisttitemstvardicttname((sClimateUtilities.pytscanøs@     )  % #  cCsEg|D]}|jƒ^q}xy|jdƒWq"Pq"Xq"|S(NR(tstriptremove(RCRH((sClimateUtilities.pyR?+scCsg}xrtt|ƒdƒD]Z}tt||jƒƒt||djƒƒƒ}|dks|j|dƒqqW|jt|ƒƒd}xStt|ƒdƒD];}||d||}||kr«|}||}q«q«W|dkr t|ƒ}d}n|||fS(Niiiÿÿÿÿ(R-RtabsRAR(RCt runStartsR5tdntnmaxR timax((sClimateUtilities.pyR@4s 4     c Csbt|ƒ}|jƒ}t|||ƒ\}}tƒ}x"|D]}|j|||ƒq@W|S(N(R+t readlinesRNRR( tfilenameRDREtfRCRR2R9tkey((sClimateUtilities.pyt readTableOs    tDummycBseZRS((R<R=(((sClimateUtilities.pyR[bscCs«t|ƒ}t|ƒt|ƒks-dGHdStj|tjƒ}tj|tjƒ}||(||(d}t|d|ƒ}xCt|ƒD]5}t|||ƒ} | |krŽ| }|}qŽqŽW||} xÓtd|ƒD]Â} xzt|| ƒD]h}|||} ||| |} ||d||}| || | ||<| || | ||cCs¥g|_g|_t|j|||jƒ|_|jj|jƒ|jj|jjƒ|jƒ}|jƒ}x-t ||ƒ|kr ||jƒ}}qtW|S(N( R…R†RrRXRwRRRvR|RQ(RRsRtt tolerancetoldvaltnewval((sClimateUtilities.pyRqs    N(R<R=RR|RRq(((sClimateUtilities.pyR}ìs  t integratorcBs/eZdZdd„Zd„Zdd„ZRS(s2 Runge-Kutta integrator, for 1D or multidimensional problems Usage: First you define a function that returns the derivative(s), given the independent and dependent variables as arguments. The independent variable (think of time) is always a scalar. The dependent variable (think of the x and y coordinates of a planet) can be either a scalar or a 1D array, according to the problem. For the multidimensional case, this integrator will work with any kind of array that behaves like a Numeric array, i.e. supports arithmetic operations. It will not work with plain Python lists. The derivative function should return an array of derivatives, in the multidimensional case. The derivative function can have any name. The derivative function can optionally have a third argument, to provide for passing parameters (e.g. the radius of the Earth) to the function. The "parameter" argument, if present, can be any Python entity whatsoever. If you need to pass multiple constants, or even tables or functions, to your derivative function, you can stuff them all into a list or a Python object. Example: In the 1D case, to solve the equation dz/dt = -a*t*t/(1.+z*z) in which z is the dependent variable and t is the independent variable, your derivative function would be def g(t,z): return -a*t*t/(1.+z*z) treating the parameter a as a global, or perhaps def g(t,z,params): return -params.a*t*t/(params.b+z*z) while in a 2D case, your function might look like: def g(t,z): return Numeric.array([-z[1],z[0]]) or perhaps something like: def g(t,z): return t*Numeric.sin(z) or even def g(t,z,params): return Numeric.matrixmultiply(params(t),z) where params(t) in this case is a function returning a Numeric square matrix of the right dimension to multiply z. BIG WARNING: Note that all the examples which return a Numeric array return a NEW INSTANCE (i.e. copy) of an array. If you try to set up a global array and re-use it to return your results from g, you will really be just returning a REFERENCE to the same array each time, and each call will change the value of all the previous results. This will mess up the computation of intermediate results in the Runge-Kutta step. An example of the sort of thing that will NOT work is: zprime = Numeric.zeros(2,Numeric.Float) def g(t,z,params): zprime[0] = z[1] zprime[1] = -z[0] return zprime Try it out. This defines the harmonic oscillator, and a plot of the orbit should give a circle. However, it doesn't The problem reference/value distinction. The right way to define the function would be def g(t,z): return Numeric.array([z[1],-z[0]]) Try this one. It should work properly now. Note that any arithmetic performed on Numeric array objects returns a new instance of an Array object. Hence, a function definition like def g(t,z): return t*z*z+1. will work fine. Once you have defined the derivitave function, you then proceed as follows. First c reate an integrator instance: int_g = integrator(g,0.,start,.01) where "0." in the argument list is the initial value for the independent variable, "start" is the initial value for the dependent variable, and ".01" is the step size. You then use the integrator as follows: int_g.setParams(myParams) while int_g.x < 500: print int_g.next() The call to setParams is optional. Just use it if your function makes use of a parameter object. The next() method accepts the integration increment (e.g. dx) as an optional argument. This is in case you want to change the step size, which you can do at any time. The integrator continues using the most recent step size it knows. Each call to int_g.next returns a list, the first of whose elements is the new value of the independent variable, and the second of whose elements is a scalar or array giving the value of the dependent variable(s) at the incremented independent variable. cs’|ˆ_|jj}|dkr-|ˆ_n9|dkrT‡fd†}|ˆ_n|j}d|GH|ˆ_d|ˆ_|ˆ_dˆ_ dS(Niicsˆj||ƒS(N(tderivsin(R`ReR(R(sClimateUtilities.pytderivs1Áss'Error: %s has wrong number of argumentsg( RŒR‚RƒtderivsR„R`ReRzRRt(RRŽtxstarttystartRzR‡RRM((RsClimateUtilities.pyR´s           cCs ||_dS(N(Rt(RRt((sClimateUtilities.pyt setParamsÔsc Cs*|dks||_n|j}|d}|d}|j|}|j|j|j|jƒ}|j||}|j|||jƒ}|j||}|j|||jƒ} |j|| }| |7} |j|j|||jƒ}|j|||d| 7_|j|7_|j|jfS(Ngà?g@g@(RRzR`RŽReRt( RRzththhth6txhtdydxtyttdyttdym((sClimateUtilities.pytnextÚs"       N(R<R=t__doc__RRR‘Rš(((sClimateUtilities.pyR‹Gsl t newtSolvecBs;eZdZdd„Zdd„Zd„Zdd„ZRS(sÿ Newton method solver for function of 1 variable A class implementing Newton's method for solving f(x) = 0. Usage: solver = newtSolve(f), where f is a function with calling sequence f(x,params). Values of x such that f(x,params) = 0 are then found by invoking solver(guess), where guess is the initial guess. The solver returns the string 'No Convergence' if convergence fails. The argument params allows parameters to be passed to the function. It can be left out of the function definition if you don't need it. Note that params can be any Python object at all (including,e.g.,lists, functions or more complex user-defined objects) Optionally, one can specify the derivative function in the creator,e.g. solver = newtSolve(f,fp). If the derivative function isn't specified, the solver computes the derivative approximately using a centered difference. Note that in either case you can access the derivative function by invoking solver.deriv(x) As for f, fp can be optionally defined with a parameter argument if you need it. The same parameter object is passed to f and fp. Use solver.setParams(value) to set the parameter object Alternately, the parameter argument can be passed as an optional second argument in the solver call. (see example below). Adjustable constants: eps Increment for computing numerical approximation to the derivative of f tolerance Accuracy criterion for ending the iteration (an approximation to the error in the root) nmax maximum number of iterations e.g. to change the maximum number of iterations for an instance of the class, set solver.nmax = 10 . ----------------Usage Examples----------------------------- Example 1: Function without parameters: def g(x): return x*x - 1. roots = newtSolve(g) roots(2.) Example 2, Function with parameters: def g(x,constants): return constants.a*x*x - constants.b roots = newtSolve(g) constants = Dummy() constants.a = 1. constants.b = 2. roots.setParam(constants) roots(2.) roots(1.) Example 2a: Instead of using roots.setParam(...) we could do roots(2.,constants) roots(1.) the parameters are remembered constants.a = 3. roots(1.,constants) We changed the constants Example 3, using scan to find initial guesses: def g(x): return x*x - 1. roots = newtSolve(g) guesses = roots.scan([-2.,2.],100) for guess in guesses: print roots(guess) cs|ˆ_|jj}|dkr-|ˆ_n9|dkrT‡fd†}|ˆ_n|j}d|GHdˆ_‡fd†}|dkr–|ˆ_nf|jj}|dkrº|ˆ_nB|dkrê|ˆ_‡fd†}|ˆ_n|j}d|GHdˆ_ dˆ_ dˆ_ dS( Niics ˆj|ƒS(N(R~(R`R(R(sClimateUtilities.pyR€Gss'Error: %s has wrong number of argumentsgíµ ÷Æ°>cs9ˆj|ˆj|ƒˆj|ˆj|ƒdˆjS(Ng@(RXteps(R`Rt(R(sClimateUtilities.pytderivNscs ˆj|ƒS(N(tfprimein(R`R(R(sClimateUtilities.pytfprime1Zsid( R~R‚RƒRXR„RRRžRŸRˆRTRt(RRXtfprimeR‡R€RMRžR ((RsClimateUtilities.pyR?s2                     cCs‹|dks|j|ƒn|}xbt|jƒD]Q}|j||jƒ|j||jƒ}||}t|ƒ|jkr2|Sq2WdS(NsNo Convergence( RR‘R-RTRXRtRžRQRˆ(RtxGuessRtR`R5Rz((sClimateUtilities.pyRqcs ( cCs ||_dS(N(Rt(RRt((sClimateUtilities.pyR‘msi c CsÍg}|d|d|d}|j|d|jƒ}xgtd|ƒD]}|d||^qLD]]}|j||jƒ}|dk|dk@s¯|dk|dk@r¿|j|ƒn|}qhW|S(Niig(RXRtR-R( RRsR t guessListRztflastR5R`tfnow((sClimateUtilities.pyRNqs 5, N(R<R=R›RRRqR‘RN(((sClimateUtilities.pyRœõs I $ ((((((((tnumpyRtfloatR$tClimateGraphicsMPLtClimateGraphicst DummyGraphicsRtstringR>RRNR?R@RZR[RjRkRrR}R‹Rœ(((sClimateUtilities.pyt-sV           w3   ;0[®