2017-02-22 1 views
1

Ich versuche, komplexe-Schritt zu verwenden, um die Derivate einer einfachen Komponente in OpenMDAO zu erhalten. Obwohl ich die analytischen Ableitungen habe, möchte ich Leistung mit komplexem Schritt vergleichen. Dies ist Teil eines größeren Designproblems.Complex-Schritt funktioniert nicht wie erwartet in OpenMDAO-Komponente

Hier ist ein minimales Beispiel:

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

class SpatialBeamDisp(Component): 

    def __init__(self, ny): 
     super(SpatialBeamDisp, self).__init__() 

     self.ny = ny 

     self.add_param('disp_aug', val=np.zeros(((self.ny+1)*6), dtype='complex')) 
     self.add_output('disp', val=np.zeros((self.ny, 6), dtype='complex')) 

     # Comment out this line to use analytic derivatives 
     self.deriv_options['type'] = 'cs' 

    def solve_nonlinear(self, params, unknowns, resids): 
     # Obtain the relevant portions of disp_aug and store the reshaped 
     # displacements in disp 
     unknowns['disp'] = params['disp_aug'][:-6].reshape((self.ny, 6)) 

    def linearize(self, params, unknowns, resids): 
     jac = self.alloc_jacobian() 
     n = self.ny * 6 
     jac['disp', 'disp_aug'] = np.hstack((np.eye((n)), np.zeros((n, 6)))) 
     return jac 

top = Problem() 

root = top.root = Group() 

n = 5 

disp_aug = np.random.random(((n+1) * 6)) 

root.add('disp_input', IndepVarComp('disp_aug', disp_aug), promotes=['*']) 

root.add('disp_', SpatialBeamDisp(n), promotes=['*']) 

top.setup() 
top.run_once() 
top.check_partial_derivatives(compact_print=True) 

diesen Code laufen, wie sie ist eine falsche Jacobi erzeugt, während Kommentierung aus der self.deriv_options['type' = 'cs' Linie und mit Hilfe des analytischen Ausdruck die richtige Jacobi produziert.

Ich benutze OpenMDAO 1.7.3 und numpy 1.10.2 auf Ubuntu.

Richte ich die komplexen Schritt-Ableitungen falsch ein? Wenn ja, wie schreibe ich diese Komponente als komplex-stufig?

+0

Ich habe dieses Problem für meine Zwecke gelöst, indem ich die Umformlinie losgeworden bin und sie durch eine explizite Zuweisungsschleife ersetzt habe, obwohl ich immer noch das Gefühl habe, dass die ursprüngliche Code-Show funktioniert hat. –

Antwort

0

Das Problem ist ein Speicher/Zeiger-Problem. Im Wesentlichen, als Sie den Slice gemacht und umgestaltet haben, haben Sie eine Ansicht in das ursprüngliche Array erhalten, die Sie dann unknowns['disp'] zugewiesen haben. Durch diese Zuweisung wurde der Zeiger von OpenMDAO auf die ursprünglichen Daten, die für Berechnungen mit komplexen Schritten verwendet wurden, abgebrochen. Sie können das Problem beheben explizit durch die Zuordnung zu ändern für eine Kopie der Daten in den aktuellen Speicherplatz zu fragen, statt:

def solve_nonlinear(self, params, unknowns, resids): 
    # Obtain the relevant portions of disp_aug and store the reshaped 
    # displacements in disp 
    unknowns['disp'][:] = params['disp_aug'][:-6].reshape((self.ny, 6)) 

Es muss ein zugrunde liegenden Fehler in dem CS-Code von OpenMDAO sein, dass diese Zuordnung Schutz erforderlich machen obwohl. Das Problem tritt nicht für fd auf, nur cs.

Verwandte Themen