I have a Hermite Cubic Finite Element Space on a computer in the form of Matlab m-files. More specifically, I can evaluate four "shape functions" $N_1, N_2, N_3,$ and $N_4$, for which the following holds on the boundary of the "reference element" $K_R= [-1,1]$: 
\begin{align*}
N_1(-1) = 1, N_1(1) = 0, N_1'(-1) = 0, N_1'(1) = 0,\\
N_2(-1) = 0, N_2(1) = 1, N_2'(-1) = 0, N_2'(1) = 0,\\
N_3(-1) = 0, N_3(1) = 0, N_3'(-1) = 1, N_3'(1) = 0,\\
N_4(-1) = 0, N_4(1) = 0, N_4'(-1) = 0, N_4'(1) = 1.
\end{align*}
Here is what they look like:
[![enter image description here][1]][1]


I can map an arbitrary element $K = [a,b]$ to $K_R$, evaluate the shape functions over $K_R$, then "map back", so that the above conditions on my shape functions hold on the boundary of arbitrary elements.

I want to use this Finite Element Space to approximate $u(x) = \sin(2\pi x)$ for $x \in \Omega = [2,3]$. To do so, I complete the following steps:

 1. Make an evenly spaced Mesh of the domain.
 2. Make relevant data structures needed to access the shape functions.
 3. Create an array of values of $u(x)$ evaluated at the Mesh nodes.
 4. Loop over each element: Extract the values of $u(x)$ at the Mesh node for this element $K$ with $u_1 = u(a)$ and $u_2 = u(b)$, where $a$ and $b$ are the endpoints of the element. Then do $u(x) \approx u_1 N_1(x) + u_2 N_2(x) + u_1 N_3(x) + u_2 N_4(x)$ for x = linspace(a,b,resolution). Then plot the result.

My problem is the Hermite Cubic Finite Element Space doesn't approximate $\sin(2 \pi x)$ very well using this method; the approximation wiggles a lot. Below is my plot using a Mesh with 100 elements, and using a resolution of 21. [![enter image description here][2]][2]

I repeated the same procedure as above except using a Lagrange Cubic Finite Element Space, so that the shape functions over $K_R$ satisfy
\begin{align*}
N_1(-1) = 1, N_1(-1/3) = 0, N_1(1/3) = 0, N_1(1) = 0, \\
N_2(-1) = 0, N_2(-1/3) = 1, N_2(1/3) = 0, N_2(1) = 0, \\
N_3(-1) = 0, N_3(-1/3) = 0, N_3(1/3) = 1, N_3(1) = 0, \\
N_4(-1) = 0, N_4(-1/3) = 0, N_4(1/3) = 0, N_4(1) = 1.
\end{align*}

Here is what the Lagrange shape functions look like:[![enter image description here][3]][3]


With $u_1, u_2, u_3, u_4$ corresponding to $-1, -1/3, 1/3, 1$, the approximation I used on each element was $u(x) \approx u_1 N_1(x) + u_2 N_2(x) +  u_3 N_3(x) +  u_4 N_4(x)$. Doing this gets me much nicer results:

[![enter image description here][4]][4]

What is the deal? Why does the Lagrange FE space work so nice, and the Hermite FE space fail? This might be more of a "numerical analysis" question rather than a "scientific computing" question, but I thought I would try here first.

____
EDIT: 

One of the comments suggested to use the formula
$u(x) \approx u_1 N_1(x) + u_2 N_2(x) + u_1' N_3(x) + u_2' N_4(x)$ instead of $u(x) \approx u_1 N_1(x) + u_2 N_2(x) + u_1 N_3(x) + u_2 N_4 (x)$. I agree that using this formula is what I should have done in this first place. I implement this by computing $u_1' = 2\pi \cos(2\pi a)$ and $u_2' = 2\pi \cos(2\pi b)$ for each element $K = [a,b]$. Then my Hermite approximation to $\sin(2 \pi x)$ looks like:

[![enter image description here][5]][5]

Which is clearly very wrong. In case it helps, here is the MATLAB code for my problem. I use a few of my own finite element computer programs here.

    % Make the mesh:
    domain = [2,3]; nElement = 100;
    Mesh = mesh_generator_1d(domain, nElement);
    
    % Form a data structure to access the finite element basis:
    iDegree = 3; Fem = femherm1d(Mesh, iDegree); hDegree = 1;
    
    % Create an array with the first 100 entries corresponding to the values
    % of sin(2*pi*x) evaluated at the Mesh nodes:
    uGlobal = sin(2*pi*Fem.point(1:nElement+1)); iDerivative = 0;
    
    % Extend the array so that the last 100 entries correspond to the values of
    % 2*pi*cos(2*pi*x) evaluated at the Mesh nodes:
    uGlobal(nElement+2:2*(nElement+1)) = 2*pi*cos(2*pi*Fem.point(nElement+2:2*(nElement+1)));
    
    % Set the resolution and prepare the figure:
    reso = 20; figure(1); clf; hold on;
    uInterpolate = zeros(1,(reso+1)*size(Mesh.element,2));
    
    for k = 1:size(Mesh.element,2) % Loop over each element in the mesh
        element = Mesh.node(Mesh.element(:,k)); % Extract element endpoints
        uLocal = uGlobal(Fem.T(:,k)); % uLocal(1) = u1, uLocal(2) = u2, uLocal(3) = u1', uLocal(4) = u2'
        x = linspace(element(1), element(2), reso+1); % x contains the points we are evaluating the shape functions at
        uInterpolate(((k-1)*(reso+1)+1):(k*(reso+1))) = evalfeherm1d(x, uLocal, ...
            element, hDegree, 0); % Evaluate shape functions at x and scale by corresponding coefficients in uLocal 
        plot(x,uInterpolate(((k-1)*(reso+1)+1):(k*(reso+1)))); % Plot the result
    end
    hold off


  [1]: https://i.sstatic.net/u8BNv.png
  [2]: https://i.sstatic.net/DqMDi.png
  [3]: https://i.sstatic.net/ALWeh.png
  [4]: https://i.sstatic.net/J8GD9.png
  [5]: https://i.sstatic.net/3wr6l.png