Re: "automatic" piecewise function creation
- To: mathgroup at smc.vnet.net
- Subject: [mg105964] Re: "automatic" piecewise function creation
- From: "Norbert P." <bertapozar at gmail.com>
- Date: Mon, 28 Dec 2009 04:56:52 -0500 (EST)
- References: <hgafri$q8l$1@smc.vnet.net>
On Dec 16, 3:21 am, Giacomo Ciani <giacomo.ci... at gmail.com> wrote: > Hi all, > > I'll be honest, the following is not a real problem to me, as I can > solve it in an alternative way. However, it is interesting, and a good > occasion to learn some advanced Mathematica language. > > I have to implement a task that is easy to do with "traditional" > programming techniques (loops). However, I was wondering if there was > a more compact and elegant way of implementing this exploiting some > advanced Mathematica function to create lists and tables (or something > equivalent). > > INTRODUCTION TO THE PROBLEM (you can skip this and go to THE PROBLEM, > but reading it makes everything more comprehensible) > > The propagation of a gaussian laser beam through an optical system can > be conveniently calculated using a formalism in which a complex > parameter q(z) describes the beam characteristics along the > propagation direction z, and each optical element is associated with a > 2x2 matrix A. Each time that a light beam goes through an optical > element at position z0, its q parameter trasforms as: > > q'(z0) = (A_11 q(z0) + A_12)/(A_21 q(z0) + A_22) > > Where q(z0) is "immediately before" the optical element, and q'(z0) is > "immediately after". For your curiosity, this formalism is inherited > be geometric optics, in which a 2 element vector is used to describe > the beam, and the matrix formalism seems more natural. Nevertheless, > using this approach for gaussian beams still has the advantage that > when you have multiple optical elements in series, instead of > calculating q at each step you can just multiply the matrices together > (in the right order!) and the apply the result to q just once. > > Then from the parameter q(z) one can calculate, for example, the beam > width via a specific formula. > > Now, I would like to plot the beam width along my optical system. This > is an example code I use to do that. It describes an optical system > made of three lenses. The function that I actually plot is the > propagation of the beam along the direction "d" (my variable), but > every time it encounters a lens I have to multiply the parameter q > (propagate untill that point) by the lens matrix, and the start the > propagation again: > > Plot[Piecewise[{ > {w[apl[dst[d], q0]] /. vals, d < lns1Pos}, > {w[apl[dst[d - lns1Pos].lns[-0.050].dst[lns1Pos], q0]] /. vals, > d <= lns2Pos}, > {w[apl[ > dst[d - lns2Pos].lns[-0.038].dst[ > lns2Pos - lns1Pos].lns[-0.050].dst[lns1Pos], q0]] /. v= als, > d <= lns3Pos}, > {w[apl[ > dst[d - lns3Pos].lns[0.2].dst[ > lns3Pos - lns2Pos].lns[-0.038].dst[ > lns2Pos - lns1Pos].lns[-0.050].dst[lns1Pos], q0]] /. v= als, > d >= lns3Pos} > }], {d, 0, 1}] > > where: w[q] is a function that returns the width of the beam from its > parameter q, apl[A,q] is the function that applies the matrix A to the > parameter q to obtain the new parameter, and lns[f] and dst[l] are > functions that build the right matrix for lenses of focal length f and > propagation in space trough a distance l, respectively. > > THE PROBLEM: > > Summarizing, I have to build a piecewise function with this structure: > > Piecewise[{ > {g[f[A,q,x1,z]] z<x2}, > {g[f[B.A,q,x1,x2,z]] z<x3}, > {g[f[C.B.A,q,x1,x2,x3,z]] z<x4}, > ecc... > > }] > > Where g and f are functions, A,B,C, etc... are matrices (note that > they are multiplied together, not separated by commas), x1, x2, x3, > etc... are parameters and z is the free variable. > > Doing this starting from a list {{A,x1},{B,x2},{C,x3},...} would be > rather simple using a loop. But is it possible to do this in > Mathematica without using a loop? > > Hope you will be challenged by the problem! > (or maybe it's a problem only for me...) > > Thanks > > Giacomo Hi Giacomo, if you don't mind flipping the inequalities, here's a way without any intermediate expressions: In[5]:= t={{a,x1},{b,x2},{c,x3},{d,x4},{e,x5}}; Block[{Dot},Piecewise@Reverse@Rest@FoldList[{g[f[Prepend[#1 [[1,1,1]],First@#2],q,Sequence@@Append[#1 [[1,1,3;;-2]],Last@#2],z]],z>=Last@#2}&,{g[f[Dot[],q,z]]},t]] Out[6]= \[Piecewise]g[f[e.d.c.b.a,q,x1,x2,x3,x4,x5,z]] z>=x5 g[f[d.c.b.a,q,x1,x2,x3,x4,z]] z>=x4 g[f[c.b.a,q,x1,x2,x3,z]] z>=x3 g[f[b.a,q,x1,x2,z]] z>=x2 g[f[a,q,x1,z]] z>=x1 Best, Norbert