First your error with full traceback:
In [1]: r = np.linspace(0, 3, 20)
In [2]: V = np.piecewise(r, [r < 1, r > 1 ], [1, (r/2)*(3 - (r**2))])
Traceback (most recent call last):
File "<ipython-input-2-0bb13126761c>", line 1, in <module>
V = np.piecewise(r, [r < 1, r > 1 ], [1, (r/2)*(3 - (r**2))])
File "<__array_function__ internals>", line 5, in piecewise
File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 612, in piecewise
y[cond] = func
ValueError: NumPy boolean array indexing assignment cannot assign 20 input values to the 13 output values where the mask is true
The problem is in piecewise. If you (re)read its docs, you'll see that the elements of the 3rd argument list are supposed to scalars or functions. You provided an array as the 2nd.
In [4]: np.size((r/2)*(3 - (r**2)))
Out[4]: 20
In [5]: np.sum(r<1), np.sum(r>1)
Out[5]: (7, 13)
piecewise is trying to assign 7 values from one condition to the array, and 13 for the other. That's why its complaining when you provide all 20 for the 2nd. 20 does not match 13!
If both values are scalar:
In [6]: V = np.piecewise(r, [r < 1, r > 1 ], [1, 2])
In [7]: V
Out[7]:
array([1., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
2., 2., 2.])
We could use a lambda function that will evaluate just the 13 values we want:
In [8]: V = np.piecewise(r, [r < 1, r > 1 ], [1, lambda i: (i/2)*(3-(i**2))])
In [9]: V
Out[9]:
array([ 1. , 1. , 1. , 1. , 1. ,
1. , 1. , 0.98279633, 0.88700977, 0.6967488 ,
0.40020411, -0.01443359, -0.55897361, -1.24522525, -2.08499781,
-3.0901006 , -4.27234291, -5.64353404, -7.21548331, -9. ])
But we don't need to use piecewise. Instead evaluate all values of r, and replace selected ones:
In [10]: V = (r/2)*(3 - (r**2))
In [12]: V[r<1] = 1
In [13]: V
Out[13]:
array([ 1. , 1. , 1. , 1. , 1. ,
1. , 1. , 0.98279633, 0.88700977, 0.6967488 ,
0.40020411, -0.01443359, -0.55897361, -1.24522525, -2.08499781,
-3.0901006 , -4.27234291, -5.64353404, -7.21548331, -9. ])
From the docs:
funclist : list of callables, f(x,*args,**kw), or scalars
Each function is evaluated over `x` wherever its corresponding
condition is True. It should take a 1d array as input and give an 1d
array or a scalar value as output. If, instead of a callable,
a scalar is provided then a constant function (``lambda x: scalar``) is
assumed.
So the working piecewise is doing:
In [17]: fun = lambda i: (i/2)*(3-(i**2))
In [18]: fun(r[r>1])
Out[18]:
array([ 0.98279633, 0.88700977, 0.6967488 , 0.40020411, -0.01443359,
-0.55897361, -1.24522525, -2.08499781, -3.0901006 , -4.27234291,
-5.64353404, -7.21548331, -9. ])
to create 13 values to put in V.
piecewiseis supposed contain scalars or functions, not arrays.1'sonto the 90 values forr>1.piecewiseis overkill, especially since you don't seen to understand its argument requirements.