14
$\begingroup$

Personally, I feel the design of FourierSeries/FourierSinSeries/FourierCosSeries/FourierTrigSeries not convenient enough because:

  1. They can't give general formula of series as output, one must set a specific integer as the order of series.

  2. One cannot define the domain to be expanded in a convenient way. What if I want to expand a function $f(x)$ in e.g. $x\in(2,10)$?

Can we make them more handy?

$\endgroup$

2 Answers 2

18
$\begingroup$

For the reasons mentioned above, I wrote the following "shell" for these functions:

(* Weak test for singularity *)
findSingular[coe_, k_, assump___] := 
 Piecewise[{{{}, # === k}}, #] &[
  k /. Union@Solve[{assump, Denominator@Together@coe == 0, k ∈ Integers}, k]]

generalTerm[expr_, {t_, a_, b_}, n_: C][coefunc_, termfunc_, assump___] := 
 With[{generalCoe = coefunc[expr, {t, a, b}, \[FormalK]]}, 
  With[{singularity = findSingular[generalCoe, \[FormalK], assump]}, 
   Piecewise[{{generalCoe, And @@ (\[FormalK] != # & /@ singularity)}, 
      Sequence @@ ({coefunc[expr, {t, a, b}, #], \[FormalK] == #} & /@ 
         singularity)}] termfunc[{t, a, b}, \[FormalK]]]]

summation[lowerbound_, upperbound_] := 
 HoldForm@Sum[#, {\[FormalK], lowerbound, upperbound}] &

trans[old_, new_, var_] := First@RescalingTransform[{new}, {old}][{var}]

easyFourierSinCoefficient[expr_, {t_, a_, b_}, k_] := 
 FourierSinCoefficient[expr /. t -> trans[{a, b}, {0, Pi}, t], t, k] /. 
  t -> trans[{0, Pi}, {a, b}, t]

Block[{t, a, b, k},
  easySinTerm[{t_, a_, b_}, k_] = Sin[k t] /. t -> trans[{0, Pi}, {a, b}, t] // Simplify];

easyFourierSinSeries[expr_, {t_, a_, b_}, n_: C] := 
 summation[1, n]@
  generalTerm[expr, {t, a, b}][easyFourierSinCoefficient, easySinTerm, \[FormalK] > 0]

easyFourierCoefficient[expr_, {t_, a_, b_}, k_] := 
 FourierCoefficient[expr /. t -> trans[{a, b}, {-Pi, Pi}, t], t, k] /. 
  t -> trans[{-Pi, Pi}, {a, b}, t]

Block[{t, a, b, k},
  easyTerm[{t_, a_, b_}, k_] = 
   Exp[I k t] /. t -> trans[{-Pi, Pi}, {a, b}, t] // Simplify];

easyFourierSeries[expr_, {t_, a_, b_}, n_: C] := 
 summation[-n, n]@
  PiecewiseExpand@
   Piecewise[{{generalTerm[expr, {t, a, b}][easyFourierCoefficient, 
       easyTerm], \[FormalK] != 0}}, 
    easyFourierCoefficient[expr, {t, a, b}, 0] easyTerm[{t, a, b}, 0]]

easyFourierCosCoefficient[expr_, {t_, a_, b_}, k_] := 
 FourierCosCoefficient[expr /. t -> trans[{a, b}, {0, Pi}, t], t, k] /. 
  t -> trans[{0, Pi}, {a, b}, t]

Block[{t, a, b, k},
  easyCosTerm[{t_, a_, b_}, k_] = Cos[k t] /. t -> trans[{0, Pi}, {a, b}, t] // Simplify];

easyFourierCosSeries[expr_, {t_, a_, b_}, n_: C] := 
 easyFourierCosCoefficient[expr, {t, a, b}, 0]/2 + 
  summation[1, n]@
   generalTerm[expr, {t, a, b}][easyFourierCosCoefficient, easyCosTerm, \[FormalK] > 0]

Block[{t, a, b, k},
  easyTrigTerm[{t_, a_, b_}, 
    k_] = {Cos[k t], Sin[k t]} /. t -> trans[{-Pi, Pi}, {a, b}, t] // Simplify];

easyFourierTrigSeries[expr_, {t_, a_, b_}, n_: C] := 
 easyFourierCoefficient[expr, {t, a, b}, 0] + 
  summation[1, n]@
   Collect[Simplify[
     generalTerm[expr, {t, a, b}][easyFourierCoefficient, 
        ExpToTrig@easyTerm@## &, \[FormalK] != 
         0] /. {{\[FormalK] -> \[FormalK]}, {\[FormalK] -> -\[FormalK]}} // 
      Total, \[FormalK] > 0 && \[FormalK] ∈ Integers], (Cos | Sin)[_]]

I'm still in v9 so choose HoldForm rather than Inactivate to hold Sum.

The usage of these functions are simple and straightforward. For example, suppose I want to expand

$$ f(x)=\left\{ \begin{array}{ll} x & -\frac{1}{2}\leq x<0 \\ 1 & 0\leq x<\frac{1}{2} \\ -1 & \frac{1}{2}\leq x<\frac{3}{2} \\ \end{array}\right.$$

in $-\frac{1}{2}<x<\frac{3}{2}$ with Fourier sine series, then I just need to write

expr = Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}]
series = easyFourierSinSeries[expr, {x, -1/2, 3/2}]

Mathematica graphics

If you want to plot or do numeric calculation with the result, just replace C with a specific integer and ReleaseHold:

Plot[{expr, series /. C -> 24 // ReleaseHold} // Evaluate, {x, -1/2, 3/2}, 
 PlotRange -> All]

Mathematica graphics

$\endgroup$
9
  • $\begingroup$ Thanks, the built-in functions are indeed kind of hard to remember so I usually rescale arguments by hand before using them... $\endgroup$
    – Jens
    Commented Jul 1, 2017 at 16:05
  • $\begingroup$ These procedures are really very helpful. Thanks for this work. (+1) $\endgroup$
    – user36273
    Commented Jul 2, 2017 at 13:22
  • $\begingroup$ Please be careful in handling these procedures! For example: f = Piecewise[{{x Sin[x], 0 <= x <= 2 Pi}}] , series = easyFourierSinSeries[f, {x, 0, 2 Pi}] /. C -> 5 // ReleaseHold $\endgroup$
    – user36273
    Commented Jul 2, 2017 at 17:51
  • $\begingroup$ @rewi OK, the problem is harder than I expected… The core issue is that we don't have a general function for obtaining singularity (see discussion here for more information). Anyway, I've modified the code to make the shell more general, have a look. $\endgroup$
    – xzczd
    Commented Jul 2, 2017 at 20:21
  • $\begingroup$ Fantastic! The above example is now properly calculated, furthermore, I have also given difficult examples, e.g. Phase control; it works. $\endgroup$
    – user36273
    Commented Jul 2, 2017 at 21:15
7
$\begingroup$

Regarding the above Piecewise[ ] function:

Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}]

There is another package (FS.m) that can compute the Fourier series of this type of function. It is located at https://arxiv.org/src/0806.0150v3/anc/FS.m (Most of the package was written long before FourierCoefficient[ ], etc. came along).

You can read in the package with something like << "C:\someDir\FS.m"

If all you want is a nicely-formatted expression for the Fourier series, then use formatSeries:

formatSeries[x, {x, 1, -1}, {-1/2, 0, 1/2, 3/2}, n]

If you don't care about the formatting, but instead just want expressions for the coefficients in terms of n, along with a graph of the function and 10 terms of its Fourier series, then use fSeries:

coeffs = fSeries[x, {x, 1, -1}, {-1/2, 0, 1/2, 3/2}, n, 10]

fSeries returns a list of three items:

coeffs = { aZeroOver2 , an , bn }

aZeroOver2 is the constant term; an and bn are the expressions for the nth cosine and sine terms.

I often find it easier to specify piecewise-continuous functions with a list of (x, y) pairs at endpoints, corners, and jumps:

xyPairs = { {-1/2, -1/2}, {0, 0}, {0, 1}, {1/2, 1}, {1/2, -1}, {3/2, -1} }

formatSeries and fSeries can also work with these (x, y) pairs:

formatSeries[x, xyPairs, n]

fSeries[x, xyPairs, n, 10]

In the above example, the period is $p = 3/2 - (-1/2) = 2$, so $2\pi/p = \pi$, so the Fourier series is

a0/2 + Sum[an * Cos[n Pi x] + bn * Sin[n Pi x], {n, 1, Infinity}]

The following plots the sum of 10 terms of the series over a larger interval that includes three periods:

Plot[coeffs[[1]] + Sum[(coeffs[[2]])*Cos[n Pi x] + (coeffs[[3]])*Sin[n Pi x], {n, 1, 10}], {x, -1/2 - 2, 3/2 + 2}]
$\endgroup$
1
  • $\begingroup$ Happy to see another answer! Then, I think it's worth pointing out that 1. formatSeries can actually handle Piecewise directly, one just needs to make the second argument a List: formatSeries[x, List@Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}] , {-1/2, 3/2}, n] (Well, I think this design isn't that convenient and can be improved.) 2. This package currently has trouble in handling some edge cases e.g. formatSeries[x, {x Sin[x]}, {0, 2 Pi}, n] $\endgroup$
    – xzczd
    Commented Jul 19, 2017 at 4:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.