From 62484fd0244d658e5f395c157fedbaf52f2a5cf5 Mon Sep 17 00:00:00 2001 From: Kevin Jacobson Date: Wed, 11 Dec 2024 13:32:59 -0500 Subject: [PATCH] Some updates to the serial run of the supersonic panel case for the variable naming convention class --- .../supersonic_panel/aerodynamics_mphys.py | 39 +++--- .../supersonic_panel/geometry_morph.py | 26 ++-- .../aerostructural/supersonic_panel/run.py | 23 +++- .../supersonic_panel/run_parallel.py | 4 +- .../supersonic_panel/structures_mphys.py | 111 +++++++++--------- .../supersonic_panel/xfer_mphys.py | 86 +++++++------- 6 files changed, 160 insertions(+), 129 deletions(-) diff --git a/examples/aerostructural/supersonic_panel/aerodynamics_mphys.py b/examples/aerostructural/supersonic_panel/aerodynamics_mphys.py index 48f4d9d5..d3395c76 100644 --- a/examples/aerostructural/supersonic_panel/aerodynamics_mphys.py +++ b/examples/aerostructural/supersonic_panel/aerodynamics_mphys.py @@ -5,13 +5,16 @@ from piston_theory import PistonTheory +X_AERO0_MESH= MPhysVariables.Aerodynamics.Surface.Mesh.COORDINATES +X_AERO = MPhysVariables.Aerodynamics.Surface.COORDINATES +F_AERO = MPhysVariables.Aerodynamics.Surface.LOADS + # IVC which returns a baseline mesh class AeroMesh(om.IndepVarComp): def initialize(self): self.options.declare('x_aero0') def setup(self): - self.x_aero0_name = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL - self.add_output(self.x_aero0_name, val=self.options['x_aero0'], distributed=True, tags=['mphys_coordinates']) + self.add_output(X_AERO0_MESH, val=self.options['x_aero0'], distributed=True, tags=['mphys_coordinates']) # IC which computes aero pressures @@ -19,12 +22,10 @@ class AeroSolver(om.ImplicitComponent): def initialize(self): self.options.declare('solver') - self.x_aero_name = MPhysVariables.Aerodynamics.Surface.COORDINATES - def setup(self): self.solver = self.options['solver'] - self.add_input(self.x_aero_name, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(X_AERO, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) self.add_input('aoa', 0., units = 'deg', tags=['mphys_input']) self.add_input('qdyn', 0., tags=['mphys_input']) self.add_input('mach', 0., tags=['mphys_input']) @@ -38,7 +39,7 @@ def setup(self): def solve_nonlinear(self,inputs,outputs): - self.solver.xyz = inputs[self.x_aero_name] + self.solver.xyz = inputs[X_AERO] self.solver.aoa = inputs['aoa'] self.solver.qdyn = inputs['qdyn'] self.solver.mach = inputs['mach'] @@ -46,7 +47,7 @@ def solve_nonlinear(self,inputs,outputs): outputs['pressure'] = self.solver.compute_pressure() def apply_nonlinear(self,inputs,outputs,residuals): - self.solver.xyz = inputs[self.x_aero_name] + self.solver.xyz = inputs[X_AERO] self.solver.aoa = inputs['aoa'] self.solver.qdyn = inputs['qdyn'] self.solver.mach = inputs['mach'] @@ -69,8 +70,8 @@ def apply_linear(self,inputs,outputs,d_inputs,d_outputs,d_residuals,mode): adjoint=d_residuals['pressure'] ) - if self.x_aero_name in d_inputs: - d_inputs[self.x_aero_name] += d_xa + if X_AERO in d_inputs: + d_inputs[X_AERO] += d_xa if 'aoa' in d_inputs: d_inputs['aoa'] += d_aoa if 'qdyn' in d_inputs: @@ -85,30 +86,28 @@ def initialize(self): self.options.declare('solver') def setup(self): - self.x_aero_name = MPhysVariables.Aerodynamics.Surface.COORDINATES - self.f_aero_name = MPhysVariables.Aerodynamics.Surface.LOADS self.solver = self.options['solver'] - self.add_input(self.x_aero_name, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(X_AERO, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) self.add_input('pressure', shape_by_conn=True, distributed=True, tags=['mphys_coupling']) - self.add_output(self.f_aero_name, np.zeros(self.solver.n_nodes*self.solver.n_dof), distributed=True, tags=['mphys_coupling']) + self.add_output(F_AERO, np.zeros(self.solver.n_nodes*self.solver.n_dof), distributed=True, tags=['mphys_coupling']) def compute(self,inputs,outputs): - self.solver.xyz = inputs[self.x_aero_name] + self.solver.xyz = inputs[X_AERO] self.solver.pressure = inputs['pressure'] - outputs[self.f_aero_name] = self.solver.compute_force() + outputs[F_AERO] = self.solver.compute_force() def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if mode == 'rev': - if self.f_aero_name in d_outputs: + if F_AERO in d_outputs: d_xa, d_p = self.solver.compute_force_derivatives( - adjoint=d_outputs[self.f_aero_name] + adjoint=d_outputs[F_AERO] ) - if self.x_aero_name in d_inputs: - d_inputs[self.x_aero_name] += d_xa + if X_AERO in d_inputs: + d_inputs[X_AERO] += d_xa if 'pressure' in d_inputs: d_inputs['pressure'] += d_p @@ -205,4 +204,4 @@ def get_number_of_nodes(self): return self.solver.n_nodes def get_ndof(self): - return self.soler.n_dof + return self.solver.n_dof diff --git a/examples/aerostructural/supersonic_panel/geometry_morph.py b/examples/aerostructural/supersonic_panel/geometry_morph.py index 5f60f697..cbd9ded5 100644 --- a/examples/aerostructural/supersonic_panel/geometry_morph.py +++ b/examples/aerostructural/supersonic_panel/geometry_morph.py @@ -1,7 +1,14 @@ import numpy as np import openmdao.api as om from mpi4py import MPI -from mphys import Builder +from mphys import Builder, MPhysVariables + + +X_AERO0_GEOM_INPUT = MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_INPUT +X_AERO0_GEOM_OUTPUT = MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_OUTPUT + +X_STRUCT_GEOM_INPUT = MPhysVariables.Structures.Geometry.COORDINATES_INPUT +X_STRUCT_GEOM_OUTPUT = MPhysVariables.Structures.Geometry.COORDINATES_OUTPUT # EC which morphs the geometry class GeometryMorph(om.ExplicitComponent): @@ -9,26 +16,29 @@ def initialize(self): self.options.declare('names') self.options.declare('n_nodes') + self.input_names = {'aero': X_AERO0_GEOM_INPUT, 'struct': X_STRUCT_GEOM_INPUT} + self.output_names = {'aero': X_AERO0_GEOM_OUTPUT, 'struct': X_STRUCT_GEOM_OUTPUT} + def setup(self): self.add_input('geometry_morph_param') for name, n_nodes in zip(self.options['names'], self.options['n_nodes']): - self.add_input(f'x_{name}_in', distributed=True, shape_by_conn=True) - self.add_output(f'x_{name}0', shape=n_nodes*3, distributed=True, tags=['mphys_coordinates']) + self.add_input(self.input_names[name], distributed=True, shape_by_conn=True, tags=['mphys_coordinates']) + self.add_output(self.output_names[name], shape=n_nodes*3, distributed=True, tags=['mphys_coordinates']) def compute(self,inputs,outputs): for name in self.options['names']: - outputs[f'x_{name}0'] = inputs['geometry_morph_param']*inputs[f'x_{name}_in'] + outputs[self.output_names[name]] = inputs['geometry_morph_param']*inputs[self.input_names[name]] def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if mode == 'rev': for name in self.options['names']: - if f'x_{name}0' in d_outputs: + if self.output_names[name] in d_outputs: if 'geometry_morph_param' in d_inputs: - d_inputs['geometry_morph_param'] += self.comm.allreduce(np.sum(d_outputs[f'x_{name}0']*inputs[f'x_{name}_in']), op=MPI.SUM) + d_inputs['geometry_morph_param'] += self.comm.allreduce(np.sum(d_outputs[self.output_names[name]]*inputs[self.input_names[name]]), op=MPI.SUM) - if f'x_{name}_in' in d_inputs: - d_inputs[f'x_{name}_in'] += d_outputs[f'x_{name}0']*inputs['geometry_morph_param'] + if self.input_names[name] in d_inputs: + d_inputs[self.input_names[name]] += d_outputs[self.output_names[name]]*inputs['geometry_morph_param'] # Builder diff --git a/examples/aerostructural/supersonic_panel/run.py b/examples/aerostructural/supersonic_panel/run.py index 67bf0a79..aca74b31 100644 --- a/examples/aerostructural/supersonic_panel/run.py +++ b/examples/aerostructural/supersonic_panel/run.py @@ -3,7 +3,7 @@ import openmdao.api as om import os -from mphys import Multipoint +from mphys import Multipoint, MPhysVariables from mphys.scenarios.aerostructural import ScenarioAeroStructural from structures_mphys import StructBuilder @@ -23,6 +23,17 @@ N_el_struct = 20 N_el_aero = 7 +X_AERO = MPhysVariables.Aerodynamics.Surface.COORDINATES +X_AERO0 = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL +X_AERO0_MESH = MPhysVariables.Aerodynamics.Surface.Mesh.COORDINATES +X_AERO0_GEOM_INPUT = MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_INPUT +X_AERO0_GEOM_OUTPUT = MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_OUTPUT + +X_STRUCT = MPhysVariables.Structures.COORDINATES +X_STRUCT_MESH = MPhysVariables.Structures.Mesh.COORDINATES +X_STRUCT_GEOM_INPUT = MPhysVariables.Structures.Geometry.COORDINATES_INPUT +X_STRUCT_GEOM_OUTPUT = MPhysVariables.Structures.Geometry.COORDINATES_OUTPUT + # Mphys class Model(Multipoint): def initialize(self): @@ -74,10 +85,10 @@ def setup(self): self.add_subsystem('struct_mesh', struct_builder.get_mesh_coordinate_subsystem()) self.add_subsystem('aero_mesh', aero_builder.get_mesh_coordinate_subsystem()) - self.add_subsystem('geometry', geometry_builder.get_mesh_coordinate_subsystem(), promotes=['*']) + self.add_subsystem('geometry', geometry_builder.get_mesh_coordinate_subsystem()) - self.connect('struct_mesh.x_struct0', 'x_struct_in') - self.connect('aero_mesh.x_aero0', 'x_aero_in') + self.connect(f'struct_mesh.{X_STRUCT_MESH}', f'geometry.{X_STRUCT_GEOM_INPUT}') + self.connect(f'aero_mesh.{X_AERO0_MESH}', f'geometry.{X_AERO0_GEOM_INPUT}') # create the run directory if self.comm.rank==0: @@ -97,8 +108,10 @@ def setup(self): coupling_nonlinear_solver=nonlinear_solver, coupling_linear_solver=linear_solver) - for var in ['modulus', 'yield_stress', 'density', 'mach', 'qdyn', 'aoa', 'dv_struct', 'x_struct0', 'x_aero0']: + for var in ['modulus', 'yield_stress', 'density', 'mach', 'qdyn', 'aoa', 'dv_struct']: self.connect(var, self.scenario_name+'.'+var) + self.connect(f'geometry.{X_AERO0_GEOM_OUTPUT}', f'{self.scenario_name}.{X_AERO0}') + self.connect(f'geometry.{X_STRUCT_GEOM_OUTPUT}', f'{self.scenario_name}.{X_STRUCT}') # add design variables, to simplify remote setup self.add_design_var('geometry_morph_param', lower=0.1, upper=10.0) diff --git a/examples/aerostructural/supersonic_panel/run_parallel.py b/examples/aerostructural/supersonic_panel/run_parallel.py index bf2a6dcd..cff191c7 100644 --- a/examples/aerostructural/supersonic_panel/run_parallel.py +++ b/examples/aerostructural/supersonic_panel/run_parallel.py @@ -2,7 +2,7 @@ from mpi4py import MPI import openmdao.api as om -from mphys import Multipoint, MultipointParallel +from mphys import MultipointParallel from mphys.scenarios.aerostructural import ScenarioAeroStructural from structures_mphys import StructBuilder @@ -22,9 +22,7 @@ N_el_struct = 20 N_el_aero = 7 -# Mphys parallel multipoint scenarios class AerostructParallel(MultipointParallel): -#class AerostructParallel(Multipoint): def __init__(self, aero_builder=None, struct_builder=None, xfer_builder=None, geometry_builder=None, scenario_names=None): super().__init__() self.aero_builder = aero_builder diff --git a/examples/aerostructural/supersonic_panel/structures_mphys.py b/examples/aerostructural/supersonic_panel/structures_mphys.py index 4a1b6d24..959afa2e 100644 --- a/examples/aerostructural/supersonic_panel/structures_mphys.py +++ b/examples/aerostructural/supersonic_panel/structures_mphys.py @@ -1,15 +1,21 @@ import numpy as np import openmdao.api as om -from mphys import Builder +from mphys import Builder, MPhysVariables from beam_solver import Beam + +X_STRUCT_MESH = MPhysVariables.Structures.Mesh.COORDINATES +X_STRUCT = MPhysVariables.Structures.COORDINATES +U_STRUCT = MPhysVariables.Structures.DISPLACEMENTS +F_STRUCT = MPhysVariables.Structures.Loads.AERODYNAMIC + # IVC which returns a baseline mesh class StructMesh(om.IndepVarComp): def initialize(self): self.options.declare('x_struct0') def setup(self): - self.add_output('x_struct0', val=self.options['x_struct0'], distributed=True, tags=['mphys_coordinates']) + self.add_output(X_STRUCT_MESH, val=self.options['x_struct0'], distributed=True, tags=['mphys_coordinates']) # IC which computes structural displacements @@ -21,76 +27,76 @@ def setup(self): self.solver = self.options['solver'] self.add_input('dv_struct', shape_by_conn=True, tags=['mphys_input']) - self.add_input('x_struct0', shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) - self.add_input('f_struct', shape_by_conn=True, distributed=True, tags=['mphys_coupling']) + self.add_input(X_STRUCT, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(F_STRUCT, shape_by_conn=True, distributed=True, tags=['mphys_coupling']) self.add_input('modulus', 0., tags=['mphys_input']) - self.add_output('u_struct', np.zeros(self.solver.n_dof*self.solver.n_nodes), distributed=True, tags=['mphys_coupling']) + self.add_output(U_STRUCT, np.zeros(self.solver.n_dof*self.solver.n_nodes), distributed=True, tags=['mphys_coupling']) # bc correct term, needed for LNBGS residuals to properly converge to 0 self.bc_correct = np.zeros(self.solver.n_dof*self.solver.n_nodes) def solve_nonlinear(self,inputs,outputs): self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.modulus = inputs['modulus'] - outputs['u_struct'] = self.solver.solve_system( - f=inputs['f_struct'] + outputs[U_STRUCT] = self.solver.solve_system( + f=inputs[F_STRUCT] ) def apply_nonlinear(self,inputs,outputs,residuals): self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.modulus = inputs['modulus'] - residuals['u_struct'] = self.solver.compute_residual( - u=outputs['u_struct'], - f=inputs['f_struct'] + residuals[U_STRUCT] = self.solver.compute_residual( + u=outputs[U_STRUCT], + f=inputs[F_STRUCT] ) def solve_linear(self,d_outputs,d_residuals,mode): if mode == 'rev': - d_residuals['u_struct'] = self.solver.solve_system( - f=d_outputs['u_struct'] + d_residuals[U_STRUCT] = self.solver.solve_system( + f=d_outputs[U_STRUCT] ) # correct the boundary condition dof, in order to set the LHS equal to the RHS self.bc_correct = self.solver.bc_correction( - u=d_outputs['u_struct'] + u=d_outputs[U_STRUCT] ) - d_residuals['u_struct'] += self.bc_correct + d_residuals[U_STRUCT] += self.bc_correct def apply_linear(self,inputs,outputs,d_inputs,d_outputs,d_residuals,mode): if mode == 'rev': - if 'u_struct' in d_residuals: + if U_STRUCT in d_residuals: self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] - self.solver.modulus = inputs['modulus'] + self.solver.xyz = inputs[X_STRUCT] + self.solver.modulus = inputs['modulus'] adjoint = self.solver.set_adjoint( - adjoint=d_residuals['u_struct'] + adjoint=d_residuals[U_STRUCT] ) - if 'u_struct' in d_outputs: - d_outputs['u_struct'] += self.solver.compute_residual( - u=adjoint, + if U_STRUCT in d_outputs: + d_outputs[U_STRUCT] += self.solver.compute_residual( + u=adjoint, f=np.zeros_like(adjoint) ) # add back in non-zero values at the bc DOFs, so the LNBGS residuals look correct - d_outputs['u_struct'] += self.bc_correct + d_outputs[U_STRUCT] += self.bc_correct d_dv_struct, d_xs, d_modulus = self.solver.compute_stiffness_derivatives( - u=outputs['u_struct'], + u=outputs[U_STRUCT], adjoint=adjoint ) if 'dv_struct' in d_inputs: d_inputs['dv_struct'] += d_dv_struct - if 'x_struct0' in d_inputs: - d_inputs['x_struct0'] += d_xs - if 'f_struct' in d_inputs: - d_inputs['f_struct'] -= adjoint + if X_STRUCT in d_inputs: + d_inputs[X_STRUCT] += d_xs + if F_STRUCT in d_inputs: + d_inputs[F_STRUCT] -= adjoint if 'modulus' in d_inputs: d_inputs['modulus'] += d_modulus @@ -102,29 +108,29 @@ def initialize(self): def setup(self): self.solver = self.options['solver'] - + self.aggregation_parameter = 20. self.add_input('dv_struct', shape_by_conn=True, tags = ['mphys_input']) - self.add_input('x_struct0', shape_by_conn=True, distributed=True, tags = ['mphys_coordinates']) - self.add_input('u_struct', shape_by_conn=True, distributed=True, tags = ['mphys_coupling']) + self.add_input(X_STRUCT, shape_by_conn=True, distributed=True, tags = ['mphys_coordinates']) + self.add_input(U_STRUCT, shape_by_conn=True, distributed=True, tags = ['mphys_coupling']) self.add_input('modulus', 0., tags=['mphys_input']) self.add_input('yield_stress', 0., tags=['mphys_input']) self.add_output('func_struct', 0., tags = ['mphys_result']) def compute(self,inputs,outputs): self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.modulus = inputs['modulus'] self.solver.yield_stress = inputs['yield_stress'] self.stress, outputs['func_struct'] = self.solver.compute_stress( - u=inputs['u_struct'], + u=inputs[U_STRUCT], aggregation_parameter=self.aggregation_parameter ) self.solver.write_output( - u=inputs['u_struct'], + u=inputs[U_STRUCT], stress=self.stress ) @@ -132,23 +138,23 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if mode == 'rev': if 'func_struct' in d_outputs: self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.modulus = inputs['modulus'] self.solver.yield_stress = inputs['yield_stress'] d_dv_struct, d_xs, d_us, d_modulus, d_yield_stress = self.solver.compute_stress_derivatives( - u=inputs['u_struct'], - stress=self.stress, - aggregation_parameter=self.aggregation_parameter, + u=inputs[U_STRUCT], + stress=self.stress, + aggregation_parameter=self.aggregation_parameter, adjoint=d_outputs['func_struct'] ) if 'dv_struct' in d_inputs: d_inputs['dv_struct'] += d_dv_struct - if 'x_struct0' in d_inputs: - d_inputs['x_struct0'] += d_xs - if 'u_struct' in d_inputs: - d_inputs['u_struct'] += d_us + if X_STRUCT in d_inputs: + d_inputs[X_STRUCT] += d_xs + if U_STRUCT in d_inputs: + d_inputs[U_STRUCT] += d_us if 'modulus' in d_inputs: d_inputs['modulus'] += d_modulus if 'yield_stress' in d_inputs: @@ -164,13 +170,13 @@ def setup(self): self.solver = self.options['solver'] self.add_input('dv_struct', shape_by_conn=True, tags = ['mphys_input']) - self.add_input('x_struct0', shape_by_conn=True, distributed=True, tags = ['mphys_coordinates']) + self.add_input(X_STRUCT, shape_by_conn=True, distributed=True, tags = ['mphys_coordinates']) self.add_input('density', 0., tags=['mphys_input']) self.add_output('mass', tags=['mphys_result']) def compute(self,inputs,outputs): self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.density = inputs['density'] outputs['mass'] = self.solver.compute_mass() @@ -179,7 +185,7 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if mode == 'rev': if 'mass' in d_outputs: self.solver.dv_struct = inputs['dv_struct'] - self.solver.xyz = inputs['x_struct0'] + self.solver.xyz = inputs[X_STRUCT] self.solver.density = inputs['density'] d_dv_struct, d_xs, d_density = self.solver.compute_mass_derivatives( @@ -188,12 +194,12 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if 'dv_struct' in d_inputs: d_inputs['dv_struct'] += d_dv_struct - if 'x_struct0' in d_inputs: - d_inputs['x_struct0'] += d_xs + if X_STRUCT in d_inputs: + d_inputs[X_STRUCT] += d_xs if 'density' in d_inputs: d_inputs['density'] += d_density - + # Group which holds the solver class StructSolverGroup(om.Group): def initialize(self): @@ -230,8 +236,8 @@ def __init__(self, options): def initialize(self, comm): self.solver = Beam( - panel_chord=self.options['panel_chord'], - panel_width=self.options['panel_width'], + panel_chord=self.options['panel_chord'], + panel_width=self.options['panel_width'], N_el=self.options['N_el'], comm=comm ) @@ -239,7 +245,7 @@ def initialize(self, comm): def get_mesh_coordinate_subsystem(self, scenario_name=None): if self.solver.owned is not None: x_struct0 = np.c_[self.solver.x,self.solver.y,self.solver.z].flatten(order='C') - else: + else: x_struct0 = np.zeros(0) return StructMesh(x_struct0=x_struct0) @@ -254,4 +260,3 @@ def get_number_of_nodes(self): def get_ndof(self): return self.solver.n_dof - diff --git a/examples/aerostructural/supersonic_panel/xfer_mphys.py b/examples/aerostructural/supersonic_panel/xfer_mphys.py index dcd15601..0657aeec 100644 --- a/examples/aerostructural/supersonic_panel/xfer_mphys.py +++ b/examples/aerostructural/supersonic_panel/xfer_mphys.py @@ -1,9 +1,17 @@ import numpy as np import openmdao.api as om -from mphys import Builder +from mphys import Builder, MPhysVariables from xfer import Xfer +X_STRUCT = MPhysVariables.Structures.COORDINATES +U_STRUCT = MPhysVariables.Structures.DISPLACEMENTS +F_STRUCT = MPhysVariables.Structures.Loads.AERODYNAMIC + +X_AERO0 = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL +U_AERO = MPhysVariables.Aerodynamics.Surface.DISPLACEMENTS +F_AERO = MPhysVariables.Aerodynamics.Surface.LOADS + # EC which transfers displacements from structure to aero class DispXfer(om.ExplicitComponent): def initialize(self): @@ -12,31 +20,31 @@ def initialize(self): def setup(self): self.solver = self.options['solver'] - self.add_input('x_struct0', shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) - self.add_input('x_aero0', shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) - self.add_input('u_struct', shape_by_conn=True, distributed=True, tags=['mphys_coupling']) - self.add_output('u_aero', np.zeros(self.solver.aero.n_dof*self.solver.aero.n_nodes), distributed=True, tags=['mphys_coupling']) + self.add_input(X_STRUCT, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(X_AERO0, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(U_STRUCT, shape_by_conn=True, distributed=True, tags=['mphys_coupling']) + self.add_output(U_AERO, np.zeros(self.solver.aero.n_dof*self.solver.aero.n_nodes), distributed=True, tags=['mphys_coupling']) def compute(self,inputs,outputs): - self.solver.xs = inputs['x_struct0'] - self.solver.xa = inputs['x_aero0'] - self.solver.us = inputs['u_struct'] + self.solver.xs = inputs[X_STRUCT] + self.solver.xa = inputs[X_AERO0] + self.solver.us = inputs[U_STRUCT] + + outputs[U_AERO] = self.solver.transfer_displacements() - outputs['u_aero'] = self.solver.transfer_displacements() - def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): if mode == 'rev': - if 'u_aero' in d_outputs: + if U_AERO in d_outputs: d_xs, d_xa, d_us = self.solver.transfer_displacements_derivatives( - adjoint=d_outputs['u_aero'] + adjoint=d_outputs[U_AERO] ) - if 'x_struct0' in d_inputs: - d_inputs['x_struct0'] += d_xs - if 'x_aero0' in d_inputs: - d_inputs['x_aero0'] += d_xa - if 'u_struct' in d_inputs: - d_inputs['u_struct'] += d_us + if X_STRUCT in d_inputs: + d_inputs[X_STRUCT] += d_xs + if X_AERO0 in d_inputs: + d_inputs[X_AERO0] += d_xa + if U_STRUCT in d_inputs: + d_inputs[U_STRUCT] += d_us # EC which transfers loads from aero to structure @@ -47,31 +55,31 @@ def initialize(self): def setup(self): self.solver = self.options['solver'] - self.add_input('x_struct0', shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) - self.add_input('x_aero0', shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) - self.add_input('f_aero', shape_by_conn=True, distributed=True, tags=['mphys_coupling']) - self.add_output('f_struct', np.zeros(self.solver.struct.n_dof*self.solver.struct.n_nodes), distributed=True, tags=['mphys_coupling']) - + self.add_input(X_STRUCT, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(X_AERO0, shape_by_conn=True, distributed=True, tags=['mphys_coordinates']) + self.add_input(F_AERO, shape_by_conn=True, distributed=True, tags=['mphys_coupling']) + self.add_output(F_STRUCT, np.zeros(self.solver.struct.n_dof*self.solver.struct.n_nodes), distributed=True, tags=['mphys_coupling']) + def compute(self,inputs,outputs): - self.solver.xs = inputs['x_struct0'] - self.solver.xa = inputs['x_aero0'] - self.solver.fa = inputs['f_aero'] + self.solver.xs = inputs[X_STRUCT] + self.solver.xa = inputs[X_AERO0] + self.solver.fa = inputs[F_AERO] + + outputs[F_STRUCT] = self.solver.transfer_loads() - outputs['f_struct'] = self.solver.transfer_loads() - def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): - if mode == 'rev': - if 'f_struct' in d_outputs: + if mode == 'rev': + if F_STRUCT in d_outputs: d_xs, d_xa, d_fa = self.solver.transfer_loads_derivatives( - adjoint=d_outputs['f_struct'] + adjoint=d_outputs[F_STRUCT] ) - if 'x_struct0' in d_inputs: - d_inputs['x_struct0'] += d_xs - if 'x_aero0' in d_inputs: - d_inputs['x_aero0'] += d_xa - if 'f_aero' in d_inputs: - d_inputs['f_aero'] += d_fa + if X_STRUCT in d_inputs: + d_inputs[X_STRUCT] += d_xs + if X_AERO0 in d_inputs: + d_inputs[X_AERO0] += d_xa + if F_AERO in d_inputs: + d_inputs[F_AERO] += d_fa # Builder @@ -80,7 +88,7 @@ def __init__(self, aero_builder, struct_builder): self.aero_builder = aero_builder self.struct_builder = struct_builder - def initialize(self, comm): + def initialize(self, comm): self.solver = Xfer( aero = self.aero_builder.solver, struct = self.struct_builder.solver, @@ -91,5 +99,3 @@ def get_coupling_group_subsystem(self, scenario_name=None): disp_xfer = DispXfer(solver=self.solver) load_xfer = LoadXfer(solver=self.solver) return disp_xfer, load_xfer - -