首页 \ 问答 \ OpenMDAO如何设置子组属性?(OpenMDAO how to set subgroup properties?)

OpenMDAO如何设置子组属性?(OpenMDAO how to set subgroup properties?)

通常,当我使用我的优化组时,我将其包含在问题中。 然后,我可以设置它的组件属性:

# import modules, prepare data for Problem setup
...

# Initialize problem with my group 
prob = Problem(impl=impl, root=AEPGroup(nTurbines=10,                 
                                      nDirections=5,
                                      minSpacing=2))

# Configure driver, desvars, and constraints
prob.driver = pyOptSparseDriver()
prob.driver.add_desvar('turbineX', lower=np.ones(nTurbs)*min(turbineX), upper=np.ones(nTurbs)*max(turbineX), scaler=1E-2)
prob.driver.add_objective('obj', scaler=1E-8)

# run setup()
prob.setup(check=True)

# Now I set several specifications
prob['turbineX'] = turbineX
....

请参阅下面的示例(改编自test_brute_force.py )。 在第204行中,我想将AEPGroup作为另一个组内的组运行。 是否有类似的方法来配置子组内的turbineX规格?

from __future__ import print_function
from florisse.floris import AEPGroup
import unittest

from florisse.GeneralWindFarmComponents import calculate_boundary

from six.moves import range
from six import iteritems

import numpy as np

from openmdao.api import Problem, Group, ParallelGroup, \
                         Component, IndepVarComp, ExecComp, \
                         Driver, ScipyOptimizer, SqliteRecorder

from openmdao.test.sellar import *
from openmdao.test.util import assert_rel_error

from openmdao.core.mpi_wrap import MPI

if MPI:
    from openmdao.core.petsc_impl import PetscImpl as impl
else:
    from openmdao.api import BasicImpl as impl

# load wind rose data
windRose = np.loadtxt('./input_files/windrose_amalia_directionally_averaged_speeds.txt')
indexes = np.where(windRose[:, 1] > 0.1)
#print ("ypppp indexes are ", indexes) 
indexes = [[8]]
#print ("ypppp indexes are ", indexes) ; quit()
windDirections = windRose[indexes[0], 0]
windSpeeds = windRose[indexes[0], 1]
windFrequencies = windRose[indexes[0], 2]
nDirections = len(windDirections)

# load turbine positions
locations = np.loadtxt('./input_files/layout_amalia.txt')
turbineX = locations[:, 0]
turbineY = locations[:, 1]

# generate boundary constraint
boundaryVertices, boundaryNormals = calculate_boundary(locations)
nVertices = boundaryVertices.shape[0]

# define turbine size
rotor_diameter = 126.4  # (m)

# initialize input variable arrays
nTurbines = turbineX.size
rotorDiameter = np.zeros(nTurbines)
axialInduction = np.zeros(nTurbines)
Ct = np.zeros(nTurbines)
Cp = np.zeros(nTurbines)
generatorEfficiency = np.zeros(nTurbines)
yaw = np.zeros(nTurbines)
minSpacing = 2.                         # number of rotor diameters

# define initial values
for turbI in range(0, nTurbines):
    rotorDiameter[turbI] = rotor_diameter      # m
    axialInduction[turbI] = 1.0/3.0
    Ct[turbI] = 4.0*axialInduction[turbI]*(1.0-axialInduction[turbI])
    Cp[turbI] = 0.7737/0.944 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    generatorEfficiency[turbI] = 0.944
    yaw[turbI] = 0.     # deg.

# Define flow properties
air_density = 1.1716    # kg/m^3
class Randomize(Component):
    """ add random uncertainty to params and distribute

    Args
    ----
    n : number of points to generate for each param

    params : collection of (name, value, std_dev) specifying the params
             that are to be randommized.
    """
    def __init__(self, n=0, params=[]):
        super(Randomize, self).__init__()

        self.dists = {}

        for name, value, std_dev in params:
            # add param
            self.add_param(name, val=value)

            # add an output array var to distribute the modified param values
            if isinstance(value, np.ndarray):
                shape = (n, value.size)
            else:
                shape = (n, 1)

            # generate a standard normal distribution (size n) for this param
            self.dists[name] = np.random.normal(0.0, std_dev, n*shape[1]).reshape(shape)
            #self.dists[name] = std_dev*np.random.normal(0.0, 1.0, n*shape[1]).reshape(shape)

            self.add_output('dist_'+name, val=np.zeros(shape))

    def solve_nonlinear(self, params, unknowns, resids):
        """ add random uncertainty to params
        """
        for name, dist in iteritems(self.dists):
            unknowns['dist_'+name] = params[name] + dist

    def linearize(self, params, unknowns, resids):
        """ derivatives
        """
        J = {}
        for u in unknowns:
            name = u.split('_', 1)[1]
            for p in params:
                shape = (unknowns[u].size, params[p].size)
                if p == name:
                    J[u, p] = np.eye(shape[0], shape[1])
                else:
                    J[u, p] = np.zeros(shape)
        return J


class Collector(Component):
    """ collect the inputs and compute the mean of each

    Args
    ----
    n : number of points to collect for each input

    names : collection of `Str` specifying the names of the inputs to
            collect and the resulting outputs.
    """
    def __init__(self, n=10, names=[]):
        super(Collector, self).__init__()

        self.names = names

        # create n params for each input
        for i in range(n):
            for name in names:
                self.add_param('%s_%i' % (name, i),  val=0.)

        # create an output for the mean of each input
        for name in names:
            self.add_output(name,  val=0.)

    def solve_nonlinear(self, params, unknowns, resids):
        """ compute the mean of each input
        """
        inputs = {}

        for p in params:
            name = p.split('_', 1)[0]
            if name not in inputs:
                inputs[name] = data = [0.0, 0.0]
            else:
                data = inputs[name]
            data[0] += 1
            data[1] += params[p]

        for name in self.names:
            unknowns[name]  = inputs[name][1]/inputs[name][0]

    def linearize(self, params, unknowns, resids):
        """ derivatives
        """
        J = {}
        for p in params:
            name, idx = p.split('_', 1)
            for u in unknowns:
                if u == name:
                    J[u, p] = 1
                else:
                    J[u, p] = 0
        return J


class BruteForceSellarProblem(Problem):
    """ Performs optimization on the AEP problem.

        Applies a normal distribution to the design vars and runs all of the
        samples, then collects the values of all of the outputs, calculates
        the mean of those and stuffs that back into the unknowns vector.

        This is the brute force version that just stamps out N separate
        AEP models in a parallel group and sets the input of each
        one to be one of these random design vars.

    Args
    ----
    n : number of randomized points to generate for each input value

    derivs : if True, use user-defined derivatives, else use Finite Difference
    """
    def __init__(self, n=10, derivs=False):
        super(BruteForceSellarProblem, self).__init__(impl=impl)

        root = self.root = Group()
        if not derivs:
            root.deriv_options['type'] = 'fd'

        sellars = root.add('sellars', ParallelGroup())
        for i in range(n):
            name = 'sellar%i' % i
            sellars.add(name, AEPGroup(nTurbines=nTurbines, nDirections=nDirections,
                                          differentiable=True,
                                          use_rotor_components=False))
            #sellars.add(name, SellarDerivatives())

            root.connect('dist_air_density', 'sellars.'+name+'.air_density', src_indices=[i])
            #root.connect('yaw0', 'sellars.'+name+'.yaw0')#, src_indices=[i])
            #root.connect('dist_z', 'sellars.'+name+'.z', src_indices=[i*2, i*2+1])

            root.connect('sellars.'+name+'.AEP',  'collect.obj_%i'  % i)
            #root.connect('sellars.'+name+'.con1', 'collect.con1_%i' % i)
            #root.connect('sellars.'+name+'.con2', 'collect.con2_%i' % i)

        root.add('indep', IndepVarComp([
                    ('air_density', 1.0),
                    ('z', np.array([5.0, 2.0]))
                ]),
                promotes=['air_density', 'z'])

        root.add('random', Randomize(n=n, params=[
                    # name, value, std dev
                    ('air_density', 1.0, 1e-2),
                    ('z', np.array([5.0, 2.0]), 1e-2)
                ]),
                promotes=['z', 'dist_air_density', 'dist_z'])
                #promotes=['x', 'z', 'dist_x', 'dist_z'])

        root.add('collect', Collector(n=n, names=['obj', 'con1', 'con2']),
                promotes=['obj', 'con1', 'con2'])

        # top level driver setup
        self.driver = ScipyOptimizer()
        self.driver.options['optimizer'] = 'SLSQP'
        self.driver.options['tol'] = 1.0e-8
        self.driver.options['maxiter'] = 50
        self.driver.options['disp'] = False

        self.driver.add_desvar('z', lower=np.array([-10.0,  0.0]),
                                    upper=np.array([ 10.0, 10.0]))
        #self.driver.add_desvar('x', lower=0.0, upper=10.0)

        self.driver.add_objective('obj')
        self.driver.add_constraint('con1', upper=0.0)
        self.driver.add_constraint('con2', upper=0.0)

prob = BruteForceSellarProblem(100, derivs=False)
prob.setup(check=False)
prob.run()
print (prob["obj"])

Normally when I use my optimization group I include it in a problem. Then, I can set it's component properties:

# import modules, prepare data for Problem setup
...

# Initialize problem with my group 
prob = Problem(impl=impl, root=AEPGroup(nTurbines=10,                 
                                      nDirections=5,
                                      minSpacing=2))

# Configure driver, desvars, and constraints
prob.driver = pyOptSparseDriver()
prob.driver.add_desvar('turbineX', lower=np.ones(nTurbs)*min(turbineX), upper=np.ones(nTurbs)*max(turbineX), scaler=1E-2)
prob.driver.add_objective('obj', scaler=1E-8)

# run setup()
prob.setup(check=True)

# Now I set several specifications
prob['turbineX'] = turbineX
....

Please see my example below (adapted from test_brute_force.py). In line 204 I want to run AEPGroup as a group inside of another group. Is there a analogous way to configure specifications like turbineX within the subgroup?

from __future__ import print_function
from florisse.floris import AEPGroup
import unittest

from florisse.GeneralWindFarmComponents import calculate_boundary

from six.moves import range
from six import iteritems

import numpy as np

from openmdao.api import Problem, Group, ParallelGroup, \
                         Component, IndepVarComp, ExecComp, \
                         Driver, ScipyOptimizer, SqliteRecorder

from openmdao.test.sellar import *
from openmdao.test.util import assert_rel_error

from openmdao.core.mpi_wrap import MPI

if MPI:
    from openmdao.core.petsc_impl import PetscImpl as impl
else:
    from openmdao.api import BasicImpl as impl

# load wind rose data
windRose = np.loadtxt('./input_files/windrose_amalia_directionally_averaged_speeds.txt')
indexes = np.where(windRose[:, 1] > 0.1)
#print ("ypppp indexes are ", indexes) 
indexes = [[8]]
#print ("ypppp indexes are ", indexes) ; quit()
windDirections = windRose[indexes[0], 0]
windSpeeds = windRose[indexes[0], 1]
windFrequencies = windRose[indexes[0], 2]
nDirections = len(windDirections)

# load turbine positions
locations = np.loadtxt('./input_files/layout_amalia.txt')
turbineX = locations[:, 0]
turbineY = locations[:, 1]

# generate boundary constraint
boundaryVertices, boundaryNormals = calculate_boundary(locations)
nVertices = boundaryVertices.shape[0]

# define turbine size
rotor_diameter = 126.4  # (m)

# initialize input variable arrays
nTurbines = turbineX.size
rotorDiameter = np.zeros(nTurbines)
axialInduction = np.zeros(nTurbines)
Ct = np.zeros(nTurbines)
Cp = np.zeros(nTurbines)
generatorEfficiency = np.zeros(nTurbines)
yaw = np.zeros(nTurbines)
minSpacing = 2.                         # number of rotor diameters

# define initial values
for turbI in range(0, nTurbines):
    rotorDiameter[turbI] = rotor_diameter      # m
    axialInduction[turbI] = 1.0/3.0
    Ct[turbI] = 4.0*axialInduction[turbI]*(1.0-axialInduction[turbI])
    Cp[turbI] = 0.7737/0.944 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    generatorEfficiency[turbI] = 0.944
    yaw[turbI] = 0.     # deg.

# Define flow properties
air_density = 1.1716    # kg/m^3
class Randomize(Component):
    """ add random uncertainty to params and distribute

    Args
    ----
    n : number of points to generate for each param

    params : collection of (name, value, std_dev) specifying the params
             that are to be randommized.
    """
    def __init__(self, n=0, params=[]):
        super(Randomize, self).__init__()

        self.dists = {}

        for name, value, std_dev in params:
            # add param
            self.add_param(name, val=value)

            # add an output array var to distribute the modified param values
            if isinstance(value, np.ndarray):
                shape = (n, value.size)
            else:
                shape = (n, 1)

            # generate a standard normal distribution (size n) for this param
            self.dists[name] = np.random.normal(0.0, std_dev, n*shape[1]).reshape(shape)
            #self.dists[name] = std_dev*np.random.normal(0.0, 1.0, n*shape[1]).reshape(shape)

            self.add_output('dist_'+name, val=np.zeros(shape))

    def solve_nonlinear(self, params, unknowns, resids):
        """ add random uncertainty to params
        """
        for name, dist in iteritems(self.dists):
            unknowns['dist_'+name] = params[name] + dist

    def linearize(self, params, unknowns, resids):
        """ derivatives
        """
        J = {}
        for u in unknowns:
            name = u.split('_', 1)[1]
            for p in params:
                shape = (unknowns[u].size, params[p].size)
                if p == name:
                    J[u, p] = np.eye(shape[0], shape[1])
                else:
                    J[u, p] = np.zeros(shape)
        return J


class Collector(Component):
    """ collect the inputs and compute the mean of each

    Args
    ----
    n : number of points to collect for each input

    names : collection of `Str` specifying the names of the inputs to
            collect and the resulting outputs.
    """
    def __init__(self, n=10, names=[]):
        super(Collector, self).__init__()

        self.names = names

        # create n params for each input
        for i in range(n):
            for name in names:
                self.add_param('%s_%i' % (name, i),  val=0.)

        # create an output for the mean of each input
        for name in names:
            self.add_output(name,  val=0.)

    def solve_nonlinear(self, params, unknowns, resids):
        """ compute the mean of each input
        """
        inputs = {}

        for p in params:
            name = p.split('_', 1)[0]
            if name not in inputs:
                inputs[name] = data = [0.0, 0.0]
            else:
                data = inputs[name]
            data[0] += 1
            data[1] += params[p]

        for name in self.names:
            unknowns[name]  = inputs[name][1]/inputs[name][0]

    def linearize(self, params, unknowns, resids):
        """ derivatives
        """
        J = {}
        for p in params:
            name, idx = p.split('_', 1)
            for u in unknowns:
                if u == name:
                    J[u, p] = 1
                else:
                    J[u, p] = 0
        return J


class BruteForceSellarProblem(Problem):
    """ Performs optimization on the AEP problem.

        Applies a normal distribution to the design vars and runs all of the
        samples, then collects the values of all of the outputs, calculates
        the mean of those and stuffs that back into the unknowns vector.

        This is the brute force version that just stamps out N separate
        AEP models in a parallel group and sets the input of each
        one to be one of these random design vars.

    Args
    ----
    n : number of randomized points to generate for each input value

    derivs : if True, use user-defined derivatives, else use Finite Difference
    """
    def __init__(self, n=10, derivs=False):
        super(BruteForceSellarProblem, self).__init__(impl=impl)

        root = self.root = Group()
        if not derivs:
            root.deriv_options['type'] = 'fd'

        sellars = root.add('sellars', ParallelGroup())
        for i in range(n):
            name = 'sellar%i' % i
            sellars.add(name, AEPGroup(nTurbines=nTurbines, nDirections=nDirections,
                                          differentiable=True,
                                          use_rotor_components=False))
            #sellars.add(name, SellarDerivatives())

            root.connect('dist_air_density', 'sellars.'+name+'.air_density', src_indices=[i])
            #root.connect('yaw0', 'sellars.'+name+'.yaw0')#, src_indices=[i])
            #root.connect('dist_z', 'sellars.'+name+'.z', src_indices=[i*2, i*2+1])

            root.connect('sellars.'+name+'.AEP',  'collect.obj_%i'  % i)
            #root.connect('sellars.'+name+'.con1', 'collect.con1_%i' % i)
            #root.connect('sellars.'+name+'.con2', 'collect.con2_%i' % i)

        root.add('indep', IndepVarComp([
                    ('air_density', 1.0),
                    ('z', np.array([5.0, 2.0]))
                ]),
                promotes=['air_density', 'z'])

        root.add('random', Randomize(n=n, params=[
                    # name, value, std dev
                    ('air_density', 1.0, 1e-2),
                    ('z', np.array([5.0, 2.0]), 1e-2)
                ]),
                promotes=['z', 'dist_air_density', 'dist_z'])
                #promotes=['x', 'z', 'dist_x', 'dist_z'])

        root.add('collect', Collector(n=n, names=['obj', 'con1', 'con2']),
                promotes=['obj', 'con1', 'con2'])

        # top level driver setup
        self.driver = ScipyOptimizer()
        self.driver.options['optimizer'] = 'SLSQP'
        self.driver.options['tol'] = 1.0e-8
        self.driver.options['maxiter'] = 50
        self.driver.options['disp'] = False

        self.driver.add_desvar('z', lower=np.array([-10.0,  0.0]),
                                    upper=np.array([ 10.0, 10.0]))
        #self.driver.add_desvar('x', lower=0.0, upper=10.0)

        self.driver.add_objective('obj')
        self.driver.add_constraint('con1', upper=0.0)
        self.driver.add_constraint('con2', upper=0.0)

prob = BruteForceSellarProblem(100, derivs=False)
prob.setup(check=False)
prob.run()
print (prob["obj"])

原文:https://stackoverflow.com/questions/41624671
更新时间:2023-10-03 17:10

最满意答案

每条消息的硬限制为4MB,但即使是最长的聊天记录也应该足够了。 问题更多的是记录是深度中的原子单位 - 意味着您无法加载半个记录(但它们会发送更新的增量)。 在存储(可能很长)的聊天记录时,我认为有两种选择:

A)如果您的消息仍然可变(例如,用户可以在发送消息后编辑消息)为每条消息创建一条记录并将记录名称存储在列表中。 关于添加分页以使处理大型列表更有效率存在一个悬而未决的问题

B)如果您的聊天记录是不可变的,但是您希望长时间保留大量历史记录,则可以按如下方式构建它:

  • 将事件用于聊天消息
  • 构建一个后端进程,侦听来自任何聊天的事件并将它们存储在数据库中(例如ds.event.listen( 'chat-message/(.*)', () => {} );
  • 添加RPC以检索聊天记录的特定部分

There is a hard limit of 4MB per message, but this should be sufficient for even the longest chat history. The problem is more that a record is an atomic unit in deepstream - meaning you can't load half a record (they do however send deltas for updates). When it comes to storing (possibly very long) chat histories I think there are two alternatives:

A) If your messages remain mutable (e.g. a user can edit a message after it has been sent) create a record per message and store the record names in a list. There is an open issue about adding pagination to make handling large lists more efficient.

B) If your chat history is immutable but you want to keep a large amount of histories for a long time, you might build it as follows:

  • Use events for chat messages
  • Build a backend process that listens for events from any chat and stores them in a database (e.g. ds.event.listen( 'chat-message/(.*)', () => {} );)
  • Add an RPC to retrieve specific parts of your chat history

相关问答

更多
  • Deepstream是一个独立的服务器,像Nginx或任何数据库一样安装。 它可以通过yum / apt获得大多数Linux发行版以及Windows和MacOS可执行文件。 深流服务器通过TCP和WebSocket接受客户端连接。 客户端可以通过目前完全可用于JS / Node和Java / Android的SDK连接到它,部分/很快可用于IO(Obj C / Swift),Python和.NET。 Deepstream提供了三个核心概念: 数据同步:有状态和持久的JSON对象,可以全部或部分操作,并在所有 ...
  • 在Nginx,HAProxy等之后部署和加载平衡深度流是可能的(并且是一个好主意)。但有几点需要注意: engine.io,websockets和粘性会话 。 Deepstream使用engine.io ( socket.io后面的传输层)连接到浏览器。 engine.io使用许多不同的传输机制,最明显的是长轮询(在需要发送数据之前保持http请求打开)和WebSockets。 对于长轮询,将来自同一客户端的所有请求路由到同一个深层服务器至关重要,因此请确保在nginx上游组中启用了粘性/持久会话(只需添加 ...
  • 首先:坏消息: deepstream.io纯粹是一个消息服务器 - 它不会查看通过它的数据。 这意味着任何类型的查询功能都需要由另一个系统提供,例如连接到RethinkDB的客户端。 话虽如此:有一个好消息: 我们也在考虑将聊天功能(包括广泛的历史记录保存和搜索)添加到我们的应用程序中。 由于聊天消息是不可变的(发送后不会改变),我们将使用深流事件,而不是记录。 为了便于保存聊天记录,我们将创建一个“聊天历史记录提供程序”,这是一个位于Deepstream和我们的数据库之间的节点进程,并监听以'chat-' ...
  • 在客户端,你可以切换到这个CDN链接 rawgit指向主分支,它已经是2.0并且与1.x服务器不兼容 On the client, could you switch to this CDN link