-2

while trying to program something I've come to need to create a 2D array(matrix) from a function that takes matrix indices (i and j in below example) as arguments and returns the matrix element.

I've seen from other answers that numpy.fromfunction() along with numpy.vectorize() should do the trick, however in my case those two seem to give a different result, what could be wrong?

More specifically I am comparing this:

for i in range(velikost):
    for j in range(velikost):
        u[i][j] = pomozna(i,j)
return u

to this(which I thought is equivalent to the above):

return np.fromfunction(np.vectorize(pomozna),u.shape)

Below is my full code, if you wish to run it by yourself. Any help appreciated, thanks!

import numpy as np
def jacobi(u,h,q):
    velikost = u[0].size
    star = np.copy(u)
    def pomozna(i,j):
        if i==0 or i==velikost-1 or j==0 or j==velikost-1:
            return 0
        return 1/4*(star[int(i+1)][int(j)]+star[int(i-1)][int(j)]+star[int(i)][int(j+1)]+star[int(i)][int(j-1)] - h*h*q[int(i)][int(j)])
    #return np.fromfunction(np.vectorize(pomozna),u.shape)
    for i in range(velikost):
        for j in range(velikost):
            u[i][j] = pomozna(i,j)
    return u
h=0.05
iksi = np.linspace(0,1,int(1/h))
ipsiloni = np.linspace(0,1,int(1/h))
qji = [[-1 for iks in iksi] for ips in ipsiloni]
zacetna = np.asarray([[1.0 for iks in iksi] for ips in ipsiloni])
zacetna[0] = np.zeros(iksi.size)
zacetna[-1]=np.zeros(iksi.size)
zacetna[:,0] = np.zeros(iksi.size)
zacetna[:,-1] = np.zeros(iksi.size)
print(jacobi(zacetna,h,qji))
spyro386
  • 103
  • 2
  • Can you provide the output you get in both cases? – user2699 Mar 26 '18 at 15:48
  • Sure, https://pastebin.com/YPGWDszc – spyro386 Mar 26 '18 at 15:57
  • You start with an array of `1`s. While the for-loop takes previously calculated values into account, the vectorized approach sees the array of `1`s all the time and since 1/4*(1+1+1+1) == 1, the result is an array of all ones (except where you set it to `0`. – ImportanceOfBeingErnest Mar 26 '18 at 16:17
  • Where did you see that `fromfunction` can be used this way? I just showed that it isn't useful, [numpy array fromfunction using each previous value as input, with non-zero initial value](https://stackoverflow.com/questions/49434319) – hpaulj Mar 26 '18 at 16:31
  • The for loop shouldn't take previously calculated values into account, that's why I made a copy of my array at start(start=np.copy(u)) Or do changes in my copy also make changes in my original array? – spyro386 Mar 26 '18 at 16:31
  • I was referring to this example: https://stackoverflow.com/questions/18702105/parameters-to-numpys-fromfunction , found one more but can't find it right now. – spyro386 Mar 26 '18 at 16:33
  • You need to initialize `u` to dtype `int` in the first case. – hpaulj Mar 26 '18 at 16:38
  • Why would I need to initialize u to dtype int? I don't want to limit my outputs to ints, I want to allow them to be floats, which is what they should be(The code is part of some differential equation solver I am trying to make) – spyro386 Mar 26 '18 at 16:41
  • Found the answer, the problem was indeed with some sort of integer interpretation, changing the "return 0" to "return 0.0" fixed the problem :) – spyro386 Mar 26 '18 at 16:46
  • `vectorize` chooses the return dtype based on an initial test calculation. If it returned 0, the dtype was 0. A way around this is to use `otypes` parameter. – hpaulj Mar 26 '18 at 16:48
  • But you were right in your answer, fromfunction is actually pretty slow. Thanks for that info and all the help :) – spyro386 Mar 26 '18 at 16:50
  • Experiment with an expression like `u[1:,:]+u[:-1,:]+u[:,1:]+u[:,:-1]` instead of the `i,j` iteration. – hpaulj Mar 26 '18 at 18:09

1 Answers1

0

Perhaps try

return 0.0

in pomozna.

Ardweaden
  • 857
  • 9
  • 23