0

So I have this 3x3 G matrix (not shown here, it's irrelevant to my problem) that I created using the two variables u (a vector, x - y) and the scalar k. x_j = (x_1 (j), x_2 (j), x_3 (j)) and y_j = (y_1 (j), y_2 (j), y_3 (j)). alpha_j is a 3x3 matrix. The A matrix is block diagonal matrix of size 3nx3n. I am having trouble with the W matrix. How do I code a matrix of size 3nx3n, where the (i,j)th block is the 3x3 matrix given by alpha_i*G_[ij]*alpha_j?? I am lost.

My alpha_j matrix also seems to be having some trouble. The loop keeps throwing me the error, "only length-1 arrays can be converted to Python scalars." pls help :/

def W(x, y, k, alpha, A):
    u = x - y
    n = x.shape[0]
    W = np.zeros((3*n, 3*n))

    for i in range(0, n-1):
        for j in range(0, n-1):
                #u = -np.array([[x[i,0] - x[j,0]], [x[i,1] -               x[j,1]], [0]]) ??
                W[i][j] = (alpha_j(alpha, A) * G(u, k) * alpha_j(alpha, A))
        W[i][i] = np.zeros((n, n))

    return W

def alpha_j(a, A):
    alph = np.array([[0,0,0],[0,0,0],[0,0,0]],complex)
    rho = np.random.rand(3,1)
    for i in range(0, 2):
        for j in range(0, 2):
            alph[i][j] = (rho[i] * a * A[i][j])
    return alph

#-------------------------------------------------------------------

x1 = np.array([[1], [2], [0]])
y1 = np.array([[4], [5], [0]])

# SYSTEM PARAMETERS

# incoming Wave angle
theta = 0 # can range from [0, 2pi)

# susceptibility
chi = 10 + 1j

# wavelength
lam = 0.5 # microns (values between .4-.7)

# frequency
k = (2 * np.pi)/lam # 1/microns

# volume
V_0 = (0.05)**3 # microns^3

# incoming wave vector
K = k * np.array([[0], [np.sin(theta)], [np.cos(theta)]])

# polarization vector
vecinc = np.array([[1], [0], [0]]) # (can choose any vector perpendicular to K)

# for the fixed alpha case
alpha = (V_0 * 3 * chi)/(chi + 3)

# 3 x 3 matrix
A = np.matlib.identity(3) # could be any symmetric matrix, 


#-------------------------------------------------------------------

# TEST FUNCTIONS

test = G((x1-y1), k)
print(test)

w = W(x1, y1, k, alpha, A)
print(w)

Sometimes my W loops throws me the error, "can't set an array element with a sequence." But I need to set each array element in this arbitrary matrix W to the 3x3 matrix created by multiplying alpha by G...

7
  • Hi @Becs! First, could you create a minimal example that reproduces your problem? (This might even help you answer your own question.) Second, it would help readability if you could surround the inline code with backticks so it looks like this. Third, including some minimal sample input data and desired output might help both you and potential responders. Fourth, and finally, what have you tried so far to get rid of these errors? Commented May 26, 2019 at 19:16
  • hey! somebody ended up pointing me in the right direction but I will keep your tips in mind, thank you :) Commented May 27, 2019 at 2:53
  • The G 'matrix' is relevant to the problem. We can't run your code without it, and thus cannot reproduce your error. But you use G as though it were a function, not a matrix. Commented May 27, 2019 at 6:05
  • Your error is the result of making A a np.matrix and indexing with [i][j] style instead of [i,j]. Correcting those, we get another error - setting element with sequence. That's because W is initialed as 2d, when it should be 4d. Commented May 27, 2019 at 6:11
  • Why do you use: range(0, n-1). Don't you want to iterate over n values? Commented May 27, 2019 at 6:12

1 Answer 1

0

To your question of how to create a new array with a block for each element, the following should do the trick:

G = np.random.random([3,3])
result = np.zeros([9,9])
num_blocks = 3
a = np.random.random([3,3])
b = np.random.random([3,3])
for i in range(G.shape[0]):
    for j in range(G.shape[1]):
        block_result = a*G[i,j]*b
        for k in range(num_blocks):
            for l in range(num_blocks):
                result[3*i + k, 3*j + l] = block_result[i, j]

You should be able to generalize from there. I hope I've understood correctly.

EDIT: It looks like I haven't understood correctly. I'm leaving it in hopes it spurs you to an answer. The general idea is to generate ranges of indices to operate on, and then just operate on them directly. Slicing might be helpful, too.

Ah, you asked how to create a diagonal filled with blocks. In that case:

num_diagonal_blocks = 3 # for example

for block_dim in range(num_diagonal_blocks)
    # do your block calculation...
    for k in range(G.shape[0]):
        for l in range(G.shape[1]):
            result[3*block_dim + k, 3*block_dim + l] = # assign to element of block

I think that's nearly it.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! That's very helpful. I'm not quite sure I understand the line "result[3*i + k, 3*j + l]" yet. How would I make the diagonal, block_result[i, i], equal to a 3x3 matrix of zeros?
Can you mark my answer as the correct one, then? (And/or upvote it?) Thanks!

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.