1

I have a param that is a 2D array. It works fine with getting the correct output but when I try to do anything with the gradients such as optimization or check_total_derivatives I get a sizing error. I was wondering what the best way is to handle params that are of size 2D. Here is a sample code:

import numpy as np
from openmdao.api import Group, Problem, Component, IndepVarComp, ExecComp

class C1(Component):
    def __init__(self, n):
        super(C1, self).__init__()
        self.add_param('grid', val=np.zeros((n, n)))
        self.add_output('x', shape=1)
        self.n = n

def solve_nonlinear(self, params, unknowns, resids):
    x = 0
    for i in range(self.n):
        for j in range(self.n):
            x += params['grid'][i][j]
    unknowns['x'] = x

def linearize(self, params, unknowns, resids):
    J = {}
    J['x', 'grid'] = np.ones((self.n, self.n))
    return J

class Group1(Group):
    def __init__(self, n):
        super(Group1, self).__init__()
        self.add('grid', IndepVarComp('grid', np.zeros((n, n))), promotes=['*'])
        self.add('c1', C1(n), promotes=['*'])
        self.add('obj_cmp', ExecComp('obj = -x', x=1.0), promotes=['*'])
n = 3
p = Problem()
p.root = Group1(n)
p.setup(check=False)
p['grid'] = np.ones((n, n))
p.run()
p.check_total_derivatives()
print p['x']

I get the error:

ValueError: In component 'c1', the derivative of 'x' wrt 'grid' should have shape '(1, 3)' but has shape '(3, 3)' instead.

I feel like the derivative in this case should be of size (3, 3) because that is the size of the input param. How do you handle 2D params?

1
  • While there was a small mistake in the defined Jacobian here, the error msg was also incorrect. As a note, the error msg was fixed in this pull request: github.com/OpenMDAO/OpenMDAO/pull/444 Commented Jan 14, 2016 at 13:09

2 Answers 2

5

You have a small mistake in the Jacobian; it should look like this:

def linearize(self, params, unknowns, resids):
    J = {}
    J['x', 'grid'] = np.ones((1, self.n*self.n))
    return J

The output x is length 1, while the param grid is n by n, so it is length n*n, so the resulting J should be 1 by 9. With that change, I get the right answer.

I did notice a mistake in the error message. It should say that the expected shape is (1, 9) instead of (1, 3). I will put in a fix for that.

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

Comments

2

When you have a 2D variable and need to construct the gradient, flatten it (in row-major order) and formulate the gradient based on the flattened version.

Comments

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.